fixed chapter generation

This commit is contained in:
stratuma 2024-06-21 18:00:49 +02:00
parent d9fe95dd25
commit 3ed664132c
5 changed files with 94 additions and 30 deletions

View File

@ -715,7 +715,7 @@ export async function downloadCrunchyrollPlaylist(
return null return null
} }
const chapterPath = await createChapterFile(metadata, chapterFolder) const chapterPath = await createChapterFile(metadata, chapterFolder, format)
return chapterPath return chapterPath
} }

View File

@ -1,49 +1,50 @@
import path from 'path' import path from 'path'
import fs from 'fs/promises' import fs from 'fs/promises'
import { VideoMetadata } from '../types/crunchyroll' import { VideoMetadata, VideoMetadataSingle } from '../types/crunchyroll'
import { server } from '../api' import { server } from '../api'
function formatTimeFFMPEG(seconds: number) { function formatTimeFFMPEG(seconds: number) {
return seconds * 1000 return seconds * 1000
} }
export async function createChapterFile(rawchapters: VideoMetadata, dir: string) { export async function createChapterFile(rawchapters: VideoMetadata, dir: string, format: string) {
const filepath = path.join(dir, 'chapters.txt') const filepath = path.join(dir, 'chapters.txt')
var chapters: string[] = [] var chapters: string[] = []
chapters.push(';FFMETADATA1') const addChapter = (chapter: VideoMetadataSingle) => {
if (format === 'mkv') {
chapters.push('[CHAPTER]')
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(chapter.start)}`)
chapters.push(`title=${chapter.title}`)
chapters.push('[CHAPTER]')
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(chapter.end)}`)
chapters.push(`title=Chapter`)
} else {
chapters.push('[CHAPTER]')
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(chapter.start)}`)
chapters.push(`END=${formatTimeFFMPEG(chapter.end)}`)
chapters.push(`title=${chapter.title}`)
}
}
if (rawchapters.intro && rawchapters.intro.type && rawchapters.intro.start && rawchapters.intro.end) { if (rawchapters.intro && rawchapters.intro.type && rawchapters.intro.start && rawchapters.intro.end) {
chapters.push('[CHAPTER]') addChapter(rawchapters.intro)
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(rawchapters.intro.start)}`)
chapters.push(`END=${formatTimeFFMPEG(rawchapters.intro.end) - 1}`)
chapters.push('title=Intro')
} }
if (rawchapters.credits && rawchapters.credits.type && rawchapters.credits.start && rawchapters.credits.end) { if (rawchapters.credits && rawchapters.credits.type && rawchapters.credits.start && rawchapters.credits.end) {
chapters.push('[CHAPTER]') addChapter(rawchapters.credits)
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(rawchapters.credits.start)}`)
chapters.push(`END=${formatTimeFFMPEG(rawchapters.credits.end) - 1}`)
chapters.push('title=Credits')
} }
if (rawchapters.preview && rawchapters.preview.type && rawchapters.preview.start && rawchapters.preview.end) { if (rawchapters.preview && rawchapters.preview.type && rawchapters.preview.start && rawchapters.preview.end) {
chapters.push('[CHAPTER]') addChapter(rawchapters.preview)
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(rawchapters.preview.start)}`)
chapters.push(`END=${formatTimeFFMPEG(rawchapters.preview.end) - 1}`)
chapters.push('title=Preview')
} }
if (rawchapters.recap && rawchapters.recap.type && rawchapters.recap.start && rawchapters.recap.end) { if (rawchapters.recap && rawchapters.recap.type && rawchapters.recap.start && rawchapters.recap.end) {
chapters.push('[CHAPTER]') addChapter(rawchapters.recap)
chapters.push('TIMEBASE=1/1000')
chapters.push(`START=${formatTimeFFMPEG(rawchapters.recap.start)}`)
chapters.push(`END=${formatTimeFFMPEG(rawchapters.recap.end) - 1}`)
chapters.push('title=Recap')
} }
try { try {

View File

@ -230,3 +230,13 @@ export interface VideoMetadata {
lastUpdated: Date lastUpdated: Date
mediaId: string mediaId: string
} }
export interface VideoMetadataSingle {
approverId: string
distributionNumber: string
end: number
seriesId: string
start: number
title: string
type: string
}

View File

@ -352,6 +352,59 @@ ipcMain.handle('dialog:getDefaultCrunchyrollLanguageTemplate', async (events) =>
return seTP return seTP
}) })
ipcMain.handle('dialog:setDefaultVideoQualityTemplate', async (events, quality: number) => {
await settings.set('CrunchyrollDefaultVideoQuality', quality)
return quality
})
ipcMain.handle('dialog:getDefaultVideoQualityTemplate', async (events) => {
const seTP = await settings.get('CrunchyrollDefaultVideoQuality')
if (!seTP) {
await settings.set('CrunchyrollDefaultVideoQuality', 1080)
return 1080
}
return seTP
})
ipcMain.handle('dialog:setDefaultAudioQualityTemplate', async (events, quality: number) => {
await settings.set('CrunchyrollDefaultAudioQuality', quality)
return quality
})
ipcMain.handle('dialog:getDefaultAudioQualityTemplate', async (events) => {
const seTP = await settings.get('CrunchyrollDefaultAudioQuality')
if (!seTP) {
await settings.set('CrunchyrollDefaultAudioQuality', 1)
return 1
}
return seTP
})
ipcMain.handle('dialog:setDefaultOutputFormatTemplate', async (events, format: string) => {
await settings.set('DefaultOutputFormat', format)
return format
})
ipcMain.handle('dialog:getDefaultOutputFormatTemplate', async (events) => {
const seTP = await settings.get('DefaultOutputFormat')
if (!seTP) {
await settings.set('DefaultOutputFormat', 'mkv')
return 'mkv'
}
return seTP
})
const openWindows = new Map() const openWindows = new Map()

View File

@ -25,12 +25,12 @@ contextBridge.exposeInMainWorld('myAPI', {
getSeasonTemplate: () => ipcRenderer.invoke('dialog:getSeasonTemplate'), getSeasonTemplate: () => ipcRenderer.invoke('dialog:getSeasonTemplate'),
setSeasonEnabled: (active: boolean) => ipcRenderer.invoke('dialog:setSeasonEnabledTemplate', active), setSeasonEnabled: (active: boolean) => ipcRenderer.invoke('dialog:setSeasonEnabledTemplate', active),
getSeasonEnabled: () => ipcRenderer.invoke('dialog:getSeasonEnabledTemplate'), getSeasonEnabled: () => ipcRenderer.invoke('dialog:getSeasonEnabledTemplate'),
// setDefaultVideoQuality: (quality: number) => ipcRenderer.invoke('dialog:setDefaultVideoQualityTemplate', quality), setDefaultVideoQuality: (quality: number) => ipcRenderer.invoke('dialog:setDefaultVideoQualityTemplate', quality),
// getDefaultVideoQuality: () => ipcRenderer.invoke('dialog:getDefaultVideoQualityTemplate'), getDefaultVideoQuality: () => ipcRenderer.invoke('dialog:getDefaultVideoQualityTemplate'),
// setDefaultAudioQuality: (quality: number) => ipcRenderer.invoke('dialog:setDefaultAudioQualityTemplate', quality), setDefaultAudioQuality: (quality: number) => ipcRenderer.invoke('dialog:setDefaultAudioQualityTemplate', quality),
// getDefaultAudioQuality: () => ipcRenderer.invoke('dialog:getDefaultAudioQualityTemplate'), getDefaultAudioQuality: () => ipcRenderer.invoke('dialog:getDefaultAudioQualityTemplate'),
// setDefaultOutputFormat: (format: string) => ipcRenderer.invoke('dialog:setDefaultOutputFormatTemplate', format), setDefaultOutputFormat: (format: string) => ipcRenderer.invoke('dialog:setDefaultOutputFormatTemplate', format),
// getDefaultOutputFormat: () => ipcRenderer.invoke('dialog:getDefaultOutputFormatTemplate'), getDefaultOutputFormat: () => ipcRenderer.invoke('dialog:getDefaultOutputFormatTemplate'),
setDefaultCrunchyrollLanguage: (lang: string) => ipcRenderer.invoke('dialog:setDefaultCrunchyrollLanguageTemplate', lang), setDefaultCrunchyrollLanguage: (lang: string) => ipcRenderer.invoke('dialog:setDefaultCrunchyrollLanguageTemplate', lang),
getDefaultCrunchyrollLanguage: () => ipcRenderer.invoke('dialog:getDefaultCrunchyrollLanguageTemplate') getDefaultCrunchyrollLanguage: () => ipcRenderer.invoke('dialog:getDefaultCrunchyrollLanguageTemplate')
}) })