Spaces:
Running
Running
Commit ·
7504977
1
Parent(s): ad6b549
Fix concat cleanup
Browse files- utils/CaptionRender.js +50 -3
utils/CaptionRender.js
CHANGED
|
@@ -25,6 +25,13 @@ export class CaptionRenderer {
|
|
| 25 |
|
| 26 |
const segmentFiles = [];
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
// Render each transcript section separately
|
| 29 |
for (const [i, section] of originalManuscript.transcript.entries()) {
|
| 30 |
const segmentFile = path.join(outDir, `${jobId}_segment_${i}.mp4`);
|
|
@@ -85,7 +92,8 @@ export class CaptionRenderer {
|
|
| 85 |
}
|
| 86 |
|
| 87 |
// Concatenate all segments together
|
| 88 |
-
const
|
|
|
|
| 89 |
const concatList = path.join(outDir, `${jobId}_concat_list.txt`);
|
| 90 |
|
| 91 |
fs.writeFileSync(concatList, segmentFiles.map(f => `file '${f}'`).join('\n'));
|
|
@@ -97,12 +105,51 @@ export class CaptionRenderer {
|
|
| 97 |
'-c', 'copy',
|
| 98 |
'-y', concatFile
|
| 99 |
];
|
| 100 |
-
|
| 101 |
await this.runFFmpeg(concatArgs, controller, onLog);
|
| 102 |
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
}
|
| 105 |
|
|
|
|
| 106 |
runFFmpeg(args, controller, onLog) {
|
| 107 |
console.log('FFMPEG cmd:', args.join(' '));
|
| 108 |
|
|
|
|
| 25 |
|
| 26 |
const segmentFiles = [];
|
| 27 |
|
| 28 |
+
// Helper to clean up intermediate files
|
| 29 |
+
function cleanupFiles(files) {
|
| 30 |
+
for (const f of files) {
|
| 31 |
+
try { fs.unlinkSync(f); } catch (e) { /* ignore */ }
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
// Render each transcript section separately
|
| 36 |
for (const [i, section] of originalManuscript.transcript.entries()) {
|
| 37 |
const segmentFile = path.join(outDir, `${jobId}_segment_${i}.mp4`);
|
|
|
|
| 92 |
}
|
| 93 |
|
| 94 |
// Concatenate all segments together
|
| 95 |
+
const resultFile = path.join(outDir, `${jobId}_final.mp4`);
|
| 96 |
+
const concatFile = path.join(outDir, `${jobId}_combined_final.mp4`);
|
| 97 |
const concatList = path.join(outDir, `${jobId}_concat_list.txt`);
|
| 98 |
|
| 99 |
fs.writeFileSync(concatList, segmentFiles.map(f => `file '${f}'`).join('\n'));
|
|
|
|
| 105 |
'-c', 'copy',
|
| 106 |
'-y', concatFile
|
| 107 |
];
|
|
|
|
| 108 |
await this.runFFmpeg(concatArgs, controller, onLog);
|
| 109 |
|
| 110 |
+
// Add background music if present
|
| 111 |
+
const { bgMusic, bgMusicVolume = 0.25 } = originalManuscript;
|
| 112 |
+
if (bgMusic) {
|
| 113 |
+
const finalWithMusic = resultFile; // Overwrite the _final.mp4 file
|
| 114 |
+
const getDuration = (filePath) => {
|
| 115 |
+
try {
|
| 116 |
+
const ffprobeSync = require('child_process').spawnSync;
|
| 117 |
+
const result = ffprobeSync(ffmpegLocation.replace('ffmpeg', 'ffprobe'), [
|
| 118 |
+
'-v', 'error',
|
| 119 |
+
'-show_entries', 'format=duration',
|
| 120 |
+
'-of', 'default=noprint_wrappers=1:nokey=1',
|
| 121 |
+
filePath
|
| 122 |
+
]);
|
| 123 |
+
return parseFloat(result.stdout.toString().trim());
|
| 124 |
+
} catch (e) {
|
| 125 |
+
return null;
|
| 126 |
+
}
|
| 127 |
+
};
|
| 128 |
+
const videoDuration = getDuration(concatFile);
|
| 129 |
+
const atrimArg = (videoDuration && !isNaN(videoDuration)) ? `,atrim=end=${videoDuration}` : '';
|
| 130 |
+
|
| 131 |
+
const musicArgs = [
|
| 132 |
+
'-i', concatFile,
|
| 133 |
+
'-i', bgMusic,
|
| 134 |
+
'-filter_complex', `[1:a]volume=${bgMusicVolume}${atrimArg}[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=2[mixeda]`,
|
| 135 |
+
'-map', '0:v',
|
| 136 |
+
'-map', '[mixeda]',
|
| 137 |
+
'-c:v', 'copy',
|
| 138 |
+
'-c:a', 'aac',
|
| 139 |
+
'-y', finalWithMusic
|
| 140 |
+
];
|
| 141 |
+
await this.runFFmpeg(musicArgs, controller, onLog);
|
| 142 |
+
segmentFiles.push(concatFile);
|
| 143 |
+
}
|
| 144 |
+
else {
|
| 145 |
+
fs.renameSync(concatFile, resultFile);
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
cleanupFiles([...segmentFiles, concatList]);
|
| 149 |
+
return resultFile;
|
| 150 |
}
|
| 151 |
|
| 152 |
+
|
| 153 |
runFFmpeg(args, controller, onLog) {
|
| 154 |
console.log('FFMPEG cmd:', args.join(' '));
|
| 155 |
|