Spaces:
Running
Running
Commit ·
9db2ad9
1
Parent(s): 23a704f
Bubble feature done and dusted
Browse files- utils/AvatarRender.js +20 -22
utils/AvatarRender.js
CHANGED
|
@@ -60,40 +60,38 @@ export class AvatarRenderer {
|
|
| 60 |
tempFiles.push(sectionVideo);
|
| 61 |
}
|
| 62 |
|
| 63 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
const captionFile = section.audioCaptionFile;
|
| 65 |
-
let sourceForBubbles;
|
| 66 |
if (captionFile && captionFile.endsWith('.ass')) {
|
| 67 |
const subbedFile = path.join(outDir, `${jobId}_section${i}_subbed.mp4`);
|
| 68 |
const esc = captionFile.replace(/\\/g, '/').replace(/:/g, '\\:');
|
| 69 |
const subArgs = [
|
| 70 |
-
'-i',
|
| 71 |
'-vf', `subtitles='${esc}'`,
|
| 72 |
'-c:a', 'copy',
|
| 73 |
'-y', subbedFile
|
| 74 |
];
|
| 75 |
-
onLog && onLog(`Burning captions for section ${i}...\n`);
|
| 76 |
await this.runFFmpeg(subArgs, controller, onLog);
|
| 77 |
tempFiles.push(subbedFile);
|
| 78 |
-
|
| 79 |
-
} else {
|
| 80 |
-
sourceForBubbles = sectionVideo;
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
// Apply bubbles if present on this section
|
| 84 |
-
if (section.bubbles && Array.isArray(section.bubbles) && section.bubbles.length) {
|
| 85 |
-
const bubbledFile = path.join(outDir, `${jobId}_section${i}_bubbled.mp4`);
|
| 86 |
-
try {
|
| 87 |
-
onLog && onLog(`Applying ${section.bubbles.length} bubble(s) to section ${i}...\n`);
|
| 88 |
-
await Bubble.makeBubble(sourceForBubbles, section.bubbles, bubbledFile, onLog);
|
| 89 |
-
tempFiles.push(bubbledFile);
|
| 90 |
-
sectionCaptionedVideos.push(bubbledFile);
|
| 91 |
-
} catch (e) {
|
| 92 |
-
onLog && onLog(`Bubble application failed for section ${i}, using original: ${e}\n`);
|
| 93 |
-
sectionCaptionedVideos.push(sourceForBubbles);
|
| 94 |
-
}
|
| 95 |
} else {
|
| 96 |
-
sectionCaptionedVideos.push(
|
| 97 |
}
|
| 98 |
}
|
| 99 |
|
|
|
|
| 60 |
tempFiles.push(sectionVideo);
|
| 61 |
}
|
| 62 |
|
| 63 |
+
// First apply bubbles (so they are below caption layer)
|
| 64 |
+
let sourceAfterBubbles = sectionVideo;
|
| 65 |
+
if (section.bubbles && Array.isArray(section.bubbles) && section.bubbles.length) {
|
| 66 |
+
const bubbledFile = path.join(outDir, `${jobId}_section${i}_bubbled.mp4`);
|
| 67 |
+
try {
|
| 68 |
+
onLog && onLog(`Applying ${section.bubbles.length} bubble(s) to section ${i}...\n`);
|
| 69 |
+
await Bubble.makeBubble(sectionVideo, section.bubbles, bubbledFile, onLog);
|
| 70 |
+
tempFiles.push(bubbledFile);
|
| 71 |
+
sourceAfterBubbles = bubbledFile;
|
| 72 |
+
} catch (e) {
|
| 73 |
+
onLog && onLog(`Bubble application failed for section ${i}, using original: ${e}\n`);
|
| 74 |
+
sourceAfterBubbles = sectionVideo;
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
// Then burn captions on top of bubbled video (so captions stay visible)
|
| 79 |
const captionFile = section.audioCaptionFile;
|
|
|
|
| 80 |
if (captionFile && captionFile.endsWith('.ass')) {
|
| 81 |
const subbedFile = path.join(outDir, `${jobId}_section${i}_subbed.mp4`);
|
| 82 |
const esc = captionFile.replace(/\\/g, '/').replace(/:/g, '\\:');
|
| 83 |
const subArgs = [
|
| 84 |
+
'-i', sourceAfterBubbles,
|
| 85 |
'-vf', `subtitles='${esc}'`,
|
| 86 |
'-c:a', 'copy',
|
| 87 |
'-y', subbedFile
|
| 88 |
];
|
| 89 |
+
onLog && onLog(`Burning captions for section ${i} after bubbles...\n`);
|
| 90 |
await this.runFFmpeg(subArgs, controller, onLog);
|
| 91 |
tempFiles.push(subbedFile);
|
| 92 |
+
sectionCaptionedVideos.push(subbedFile);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
} else {
|
| 94 |
+
sectionCaptionedVideos.push(sourceAfterBubbles);
|
| 95 |
}
|
| 96 |
}
|
| 97 |
|