feat(merge-split): add splitMergedFile() function using FFmpeg stream-copy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5a20c1c6a4
commit
03f47a7240
68
src/main.ts
68
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<boolean>((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
|
// DOWNLOAD FUNCTIONS
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user