Spaces:
Running
Running
Commit ·
f36baef
1
Parent(s): 4021252
Fix overly
Browse files- common-utils +1 -1
- server-plugins/overlay.js +15 -5
common-utils
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
Subproject commit
|
|
|
|
| 1 |
+
Subproject commit 48ca73211bd3385143512d8bdc5aba48ea72c0ab
|
server-plugins/overlay.js
CHANGED
|
@@ -19,7 +19,7 @@ export class OverlayPlugin extends Plugin {
|
|
| 19 |
|
| 20 |
let overlayPath = null;
|
| 21 |
// if option looks like a file path
|
| 22 |
-
if (/\.(mp4|webm)$/i.test(overlayOpt)) {
|
| 23 |
const flattened = this.mediaPathFlatten(overlayOpt);
|
| 24 |
if (fs.existsSync(flattened)) overlayPath = flattened;
|
| 25 |
else if (fs.existsSync(overlayOpt)) overlayPath = overlayOpt;
|
|
@@ -28,12 +28,14 @@ export class OverlayPlugin extends Plugin {
|
|
| 28 |
return;
|
| 29 |
}
|
| 30 |
} else {
|
| 31 |
-
// look inside public/assets/effects for mp4 or
|
| 32 |
const effectsDir = path.join('public', 'assets', 'effects');
|
| 33 |
const mp4Path = path.join(effectsDir, `${overlayOpt}.mp4`);
|
| 34 |
const webmPath = path.join(effectsDir, `${overlayOpt}.webm`);
|
|
|
|
| 35 |
if (fs.existsSync(mp4Path)) overlayPath = mp4Path;
|
| 36 |
else if (fs.existsSync(webmPath)) overlayPath = webmPath;
|
|
|
|
| 37 |
else {
|
| 38 |
this.log(`No overlay found for '${overlayOpt}' in ${effectsDir}`);
|
| 39 |
return;
|
|
@@ -68,6 +70,8 @@ export class OverlayPlugin extends Plugin {
|
|
| 68 |
|
| 69 |
const srcW = parseInt(meta.video.width);
|
| 70 |
const srcH = parseInt(meta.video.height);
|
|
|
|
|
|
|
| 71 |
|
| 72 |
const ext = path.extname(mediaPath);
|
| 73 |
const base = path.basename(mediaPath, ext);
|
|
@@ -78,10 +82,16 @@ export class OverlayPlugin extends Plugin {
|
|
| 78 |
if (overlayExt === '.mp4') {
|
| 79 |
// mp4 uses green-screen (chroma key) -> remove green then overlay
|
| 80 |
// chromakey params: color (green), similarity, blend
|
| 81 |
-
cmd = `ffmpeg -i "${mediaPath}" -i "${overlayPath}" -filter_complex "[1:v]scale=${srcW}:${srcH},chromakey=0x00FF00:0.3:0.1[ovr];[0:v][ovr]overlay=0:0:format=auto,format=yuv420p" -c:v libx264 -preset veryfast -crf 23 -c:a copy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
} else {
|
| 83 |
-
|
| 84 |
-
|
| 85 |
}
|
| 86 |
|
| 87 |
this.log(`Applying overlay ${overlayPath} -> ${outPath} on ${mediaPath}`);
|
|
|
|
| 19 |
|
| 20 |
let overlayPath = null;
|
| 21 |
// if option looks like a file path
|
| 22 |
+
if (/\.(mp4|webm|png)$/i.test(overlayOpt)) {
|
| 23 |
const flattened = this.mediaPathFlatten(overlayOpt);
|
| 24 |
if (fs.existsSync(flattened)) overlayPath = flattened;
|
| 25 |
else if (fs.existsSync(overlayOpt)) overlayPath = overlayOpt;
|
|
|
|
| 28 |
return;
|
| 29 |
}
|
| 30 |
} else {
|
| 31 |
+
// look inside public/assets/effects for mp4, webm, or png
|
| 32 |
const effectsDir = path.join('public', 'assets', 'effects');
|
| 33 |
const mp4Path = path.join(effectsDir, `${overlayOpt}.mp4`);
|
| 34 |
const webmPath = path.join(effectsDir, `${overlayOpt}.webm`);
|
| 35 |
+
const pngPath = path.join(effectsDir, `${overlayOpt}.png`);
|
| 36 |
if (fs.existsSync(mp4Path)) overlayPath = mp4Path;
|
| 37 |
else if (fs.existsSync(webmPath)) overlayPath = webmPath;
|
| 38 |
+
else if (fs.existsSync(pngPath)) overlayPath = pngPath;
|
| 39 |
else {
|
| 40 |
this.log(`No overlay found for '${overlayOpt}' in ${effectsDir}`);
|
| 41 |
return;
|
|
|
|
| 70 |
|
| 71 |
const srcW = parseInt(meta.video.width);
|
| 72 |
const srcH = parseInt(meta.video.height);
|
| 73 |
+
const srcDuration = parseFloat(meta.duration || meta.format?.duration || 0);
|
| 74 |
+
const durationArg = srcDuration > 0 ? `-t ${srcDuration}` : '';
|
| 75 |
|
| 76 |
const ext = path.extname(mediaPath);
|
| 77 |
const base = path.basename(mediaPath, ext);
|
|
|
|
| 82 |
if (overlayExt === '.mp4') {
|
| 83 |
// mp4 uses green-screen (chroma key) -> remove green then overlay
|
| 84 |
// chromakey params: color (green), similarity, blend
|
| 85 |
+
cmd = `ffmpeg -i "${mediaPath}" -stream_loop -1 -i "${overlayPath}" -filter_complex "[1:v]scale=${srcW}:${srcH},chromakey=0x00FF00:0.3:0.1[ovr];[0:v][ovr]overlay=0:0:format=auto,format=yuv420p" -c:v libx264 -preset veryfast -crf 23 -c:a copy ${durationArg} "${outPath}" -y`;
|
| 86 |
+
} else if (overlayExt === '.webm') {
|
| 87 |
+
// webm assumed to have alpha (transparent video) and should loop to match source duration
|
| 88 |
+
cmd = `ffmpeg -i "${mediaPath}" -stream_loop -1 -i "${overlayPath}" -filter_complex "[1:v]scale=${srcW}:${srcH}[ovr];[0:v][ovr]overlay=0:0:format=auto,format=yuv420p" -c:v libx264 -preset veryfast -crf 23 -c:a copy ${durationArg} "${outPath}" -y`;
|
| 89 |
+
} else if (overlayExt === '.png') {
|
| 90 |
+
// png is static image overlay, loop to cover full video duration
|
| 91 |
+
cmd = `ffmpeg -i "${mediaPath}" -loop 1 -i "${overlayPath}" -filter_complex "[1:v]scale=${srcW}:${srcH}[ovr];[0:v][ovr]overlay=0:0:format=auto,format=yuv420p" -c:v libx264 -preset veryfast -crf 23 -c:a copy ${durationArg} "${outPath}" -y`;
|
| 92 |
} else {
|
| 93 |
+
this.log(`Unsupported overlay extension: ${overlayExt}`);
|
| 94 |
+
continue;
|
| 95 |
}
|
| 96 |
|
| 97 |
this.log(`Applying overlay ${overlayPath} -> ${outPath} on ${mediaPath}`);
|