From 03f47a7240aa941e12f32fca5e99b1467b6c62c5 Mon Sep 17 00:00:00 2001 From: xRangerDE Date: Thu, 19 Mar 2026 17:49:15 +0100 Subject: [PATCH] feat(merge-split): add splitMergedFile() function using FFmpeg stream-copy Co-Authored-By: Claude Opus 4.6 (1M context) --- src/main.ts | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/main.ts b/src/main.ts index 336d135..ec27704 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2526,6 +2526,74 @@ async function mergeVideos( } } +// ========================================== +// SPLIT MERGED FILE +// ========================================== +async function splitMergedFile( + inputFile: string, + outputFolder: string, + partDurationSec: number, + totalDurationSec: number, + filenameGenerator: (partNum: number) => string, + onProgress: (currentPart: number, totalParts: number) => void +): Promise<{ success: boolean; files: string[] }> { + const ffmpegReady = await ensureFfmpegInstalled(); + if (!ffmpegReady) { + appendDebugLog('split-merged-missing-ffmpeg'); + return { success: false, files: [] }; + } + + const ffmpeg = getFFmpegPath(); + const numParts = Math.ceil(totalDurationSec / partDurationSec); + const splitFiles: string[] = []; + + for (let i = 0; i < numParts; i++) { + if (currentDownloadCancelled) { + return { success: false, files: splitFiles }; + } + + const startSec = i * partDurationSec; + const thisDuration = Math.min(partDurationSec, totalDurationSec - startSec); + const outputFile = path.join(outputFolder, filenameGenerator(i + 1)); + + onProgress(i + 1, numParts); + + const args = [ + '-ss', formatDuration(startSec), + '-i', inputFile, + '-t', formatDuration(thisDuration), + '-c', 'copy', + '-y', outputFile + ]; + + appendDebugLog('split-merged-part', { part: i + 1, total: numParts, startSec, duration: thisDuration }); + + const success = await new Promise((resolve) => { + const proc = spawn(ffmpeg, args, { windowsHide: true }); + currentProcess = proc; + + proc.on('close', (code) => { + currentProcess = null; + resolve(code === 0 && fs.existsSync(outputFile)); + }); + + proc.on('error', () => { + currentProcess = null; + resolve(false); + }); + }); + + if (!success) { + appendDebugLog('split-merged-part-failed', { part: i + 1, outputFile }); + return { success: false, files: splitFiles }; + } + + splitFiles.push(outputFile); + } + + return { success: true, files: splitFiles }; +} + // ========================================== // DOWNLOAD FUNCTIONS // ==========================================