storyforge 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
FINAL_LOUDNORM_FILTER,
|
|
3
4
|
buildCrossfadeArgs,
|
|
4
5
|
buildFinalConcatArgs,
|
|
6
|
+
buildFinalEncodeArgs,
|
|
5
7
|
buildNormalizeClipArgs,
|
|
6
8
|
probeDuration,
|
|
7
9
|
runCmd
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-NSPRIPOP.js";
|
|
10
|
+
} from "./chunk-ZHECC3YI.js";
|
|
10
11
|
|
|
11
12
|
// ../pipeline/src/stitch/stitch-final.ts
|
|
12
13
|
import * as fs3 from "fs";
|
|
@@ -293,7 +294,8 @@ async function stitchFinalVideo(args) {
|
|
|
293
294
|
}
|
|
294
295
|
}
|
|
295
296
|
const segmentPaths = [];
|
|
296
|
-
|
|
297
|
+
const skipTransitions = args.skipTransitions ?? true;
|
|
298
|
+
if (skipTransitions) {
|
|
297
299
|
segmentPaths.push(...normalizedPaths);
|
|
298
300
|
} else {
|
|
299
301
|
emit("compositing", { percent: 65 });
|
|
@@ -433,14 +435,85 @@ async function stitchFinalVideo(args) {
|
|
|
433
435
|
function sanitizeId(id) {
|
|
434
436
|
return id.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 64);
|
|
435
437
|
}
|
|
438
|
+
|
|
439
|
+
// ../pipeline/src/stitch/final-encode-contract.ts
|
|
440
|
+
function buildFinalEncodeContract() {
|
|
441
|
+
const tail = buildFinalEncodeArgs("");
|
|
442
|
+
const encodeTail = tail.slice(0, -1);
|
|
443
|
+
return {
|
|
444
|
+
crf: 8,
|
|
445
|
+
preset: "slow",
|
|
446
|
+
pixFmt: "yuv420p",
|
|
447
|
+
colorspace: "bt709",
|
|
448
|
+
colorRange: "tv",
|
|
449
|
+
profile: "high",
|
|
450
|
+
level: "4.1",
|
|
451
|
+
gop: 30,
|
|
452
|
+
audioCodec: "aac",
|
|
453
|
+
audioBitrate: "192k",
|
|
454
|
+
loudnormFilter: FINAL_LOUDNORM_FILTER,
|
|
455
|
+
encodeTail
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// ../pipeline/src/stitch/resolve-channel-package.ts
|
|
460
|
+
var AGNOSTIC = "__any__";
|
|
461
|
+
function normAspect(raw) {
|
|
462
|
+
if (!raw) return "any";
|
|
463
|
+
const s = String(raw).trim().toLowerCase();
|
|
464
|
+
if (s === "16:9" || s === "horizontal" || s === "h") return "16:9";
|
|
465
|
+
if (s === "9:16" || s === "vertical" || s === "v") return "9:16";
|
|
466
|
+
return "any";
|
|
467
|
+
}
|
|
468
|
+
function pick(assets, type, wantAspect) {
|
|
469
|
+
const ofType = assets.filter((a) => a.type === type && a.storj_key);
|
|
470
|
+
if (ofType.length === 0) return void 0;
|
|
471
|
+
let chosen;
|
|
472
|
+
if (wantAspect === AGNOSTIC) {
|
|
473
|
+
chosen = ofType.find((a) => normAspect(a.aspect) === "any") ?? ofType[0];
|
|
474
|
+
} else {
|
|
475
|
+
chosen = ofType.find((a) => normAspect(a.aspect) === wantAspect);
|
|
476
|
+
}
|
|
477
|
+
if (!chosen) return void 0;
|
|
478
|
+
return { assetId: chosen.id, storjKey: chosen.storj_key, aspect: normAspect(chosen.aspect) };
|
|
479
|
+
}
|
|
480
|
+
function resolveChannelPackage(assets, aspect) {
|
|
481
|
+
const rows = Array.isArray(assets) ? assets : [];
|
|
482
|
+
return {
|
|
483
|
+
aspect,
|
|
484
|
+
watermark: pick(rows, "watermark", AGNOSTIC),
|
|
485
|
+
introMusic: pick(rows, "intro_music", AGNOSTIC),
|
|
486
|
+
outroMusic: pick(rows, "outro_music", AGNOSTIC),
|
|
487
|
+
introVideo: pick(rows, "intro_video", aspect),
|
|
488
|
+
outroVideo: pick(rows, "outro_video", aspect),
|
|
489
|
+
endCard: pick(rows, "end_card", aspect)
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
function channelPackageProvenance(pkg) {
|
|
493
|
+
const slots = {};
|
|
494
|
+
const add = (name, slot) => {
|
|
495
|
+
if (slot) slots[name] = { assetId: slot.assetId, storjKey: slot.storjKey, aspect: slot.aspect };
|
|
496
|
+
};
|
|
497
|
+
add("watermark", pkg.watermark);
|
|
498
|
+
add("intro_music", pkg.introMusic);
|
|
499
|
+
add("outro_music", pkg.outroMusic);
|
|
500
|
+
add("intro_video", pkg.introVideo);
|
|
501
|
+
add("outro_video", pkg.outroVideo);
|
|
502
|
+
add("end_card", pkg.endCard);
|
|
503
|
+
return { aspect: pkg.aspect, slots };
|
|
504
|
+
}
|
|
505
|
+
|
|
436
506
|
export {
|
|
507
|
+
resolutionFor,
|
|
508
|
+
normalizeClip,
|
|
437
509
|
LEGACY_SECTION_TRANSITION_ROOT,
|
|
510
|
+
renderSectionTransition,
|
|
511
|
+
renderCrossfadeFallback,
|
|
438
512
|
concatWithExtras,
|
|
439
513
|
formatSrtTime,
|
|
440
|
-
normalizeClip,
|
|
441
|
-
renderCrossfadeFallback,
|
|
442
|
-
renderSectionTransition,
|
|
443
|
-
resolutionFor,
|
|
444
514
|
srtFromTimings,
|
|
445
|
-
stitchFinalVideo
|
|
515
|
+
stitchFinalVideo,
|
|
516
|
+
buildFinalEncodeContract,
|
|
517
|
+
resolveChannelPackage,
|
|
518
|
+
channelPackageProvenance
|
|
446
519
|
};
|
|
@@ -155,16 +155,10 @@ function buildNormalizeClipArgs(videoPath, outPath, opts) {
|
|
|
155
155
|
);
|
|
156
156
|
return args;
|
|
157
157
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
watermarkPath,
|
|
163
|
-
brandAudioPath,
|
|
164
|
-
brandAudioVolume = 0.1
|
|
165
|
-
} = opts;
|
|
166
|
-
const vol = brandAudioVolume.toFixed(3);
|
|
167
|
-
const encoderTail = [
|
|
158
|
+
var FINAL_LOUDNORM_FILTER = "loudnorm=I=-14:TP=-1.5:LRA=11";
|
|
159
|
+
function buildFinalEncodeArgs(outPath) {
|
|
160
|
+
return [
|
|
161
|
+
// ── video ──────────────────────────────────────────────────────────
|
|
168
162
|
"-c:v",
|
|
169
163
|
"libx264",
|
|
170
164
|
"-preset",
|
|
@@ -179,12 +173,40 @@ function buildFinalConcatArgs(opts) {
|
|
|
179
173
|
"bt709",
|
|
180
174
|
"-color_trc",
|
|
181
175
|
"bt709",
|
|
176
|
+
"-color_range",
|
|
177
|
+
"tv",
|
|
178
|
+
// x264-level VUI atoms — required so color_primaries/color_transfer land
|
|
179
|
+
// in the container on full-range yuvj/bt470bg (Remotion) sources.
|
|
180
|
+
"-x264-params",
|
|
181
|
+
"colorprim=bt709:transfer=bt709:colormatrix=bt709",
|
|
182
|
+
"-profile:v",
|
|
183
|
+
"high",
|
|
184
|
+
"-level",
|
|
185
|
+
"4.1",
|
|
186
|
+
"-g",
|
|
187
|
+
"30",
|
|
188
|
+
"-keyint_min",
|
|
189
|
+
"30",
|
|
190
|
+
"-movflags",
|
|
191
|
+
"+faststart",
|
|
192
|
+
// ── audio ──────────────────────────────────────────────────────────
|
|
182
193
|
"-c:a",
|
|
183
194
|
"aac",
|
|
184
195
|
"-b:a",
|
|
185
196
|
"192k",
|
|
186
197
|
outPath
|
|
187
198
|
];
|
|
199
|
+
}
|
|
200
|
+
function buildFinalConcatArgs(opts) {
|
|
201
|
+
const {
|
|
202
|
+
manifestPath,
|
|
203
|
+
outPath,
|
|
204
|
+
watermarkPath,
|
|
205
|
+
brandAudioPath,
|
|
206
|
+
brandAudioVolume = 0.1
|
|
207
|
+
} = opts;
|
|
208
|
+
const vol = brandAudioVolume.toFixed(3);
|
|
209
|
+
const encoderTail = buildFinalEncodeArgs(outPath);
|
|
188
210
|
if (watermarkPath && brandAudioPath) {
|
|
189
211
|
return [
|
|
190
212
|
"-y",
|
|
@@ -199,7 +221,7 @@ function buildFinalConcatArgs(opts) {
|
|
|
199
221
|
"-i",
|
|
200
222
|
brandAudioPath,
|
|
201
223
|
"-filter_complex",
|
|
202
|
-
`[0:v][1:v]overlay=W-w-20:H-h-20,format=yuv420p[vout];[2:a]volume=${vol}[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=2[aout]`,
|
|
224
|
+
`[0:v][1:v]overlay=W-w-20:H-h-20,format=yuv420p[vout];[2:a]volume=${vol}[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=2,${FINAL_LOUDNORM_FILTER}[aout]`,
|
|
203
225
|
"-map",
|
|
204
226
|
"[vout]",
|
|
205
227
|
"-map",
|
|
@@ -219,11 +241,11 @@ function buildFinalConcatArgs(opts) {
|
|
|
219
241
|
"-i",
|
|
220
242
|
watermarkPath,
|
|
221
243
|
"-filter_complex",
|
|
222
|
-
`[0:v][1:v]overlay=W-w-20:H-h-20,format=yuv420p[vout]`,
|
|
244
|
+
`[0:v][1:v]overlay=W-w-20:H-h-20,format=yuv420p[vout];[0:a]${FINAL_LOUDNORM_FILTER}[aout]`,
|
|
223
245
|
"-map",
|
|
224
246
|
"[vout]",
|
|
225
247
|
"-map",
|
|
226
|
-
"
|
|
248
|
+
"[aout]",
|
|
227
249
|
...encoderTail
|
|
228
250
|
];
|
|
229
251
|
}
|
|
@@ -239,7 +261,7 @@ function buildFinalConcatArgs(opts) {
|
|
|
239
261
|
"-i",
|
|
240
262
|
brandAudioPath,
|
|
241
263
|
"-filter_complex",
|
|
242
|
-
`[1:a]volume=${vol}[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=2[aout]`,
|
|
264
|
+
`[1:a]volume=${vol}[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=2,${FINAL_LOUDNORM_FILTER}[aout]`,
|
|
243
265
|
"-map",
|
|
244
266
|
"0:v",
|
|
245
267
|
"-map",
|
|
@@ -255,6 +277,8 @@ function buildFinalConcatArgs(opts) {
|
|
|
255
277
|
"0",
|
|
256
278
|
"-i",
|
|
257
279
|
manifestPath,
|
|
280
|
+
"-af",
|
|
281
|
+
FINAL_LOUDNORM_FILTER,
|
|
258
282
|
...encoderTail
|
|
259
283
|
];
|
|
260
284
|
}
|
|
@@ -337,6 +361,8 @@ export {
|
|
|
337
361
|
muxAudio,
|
|
338
362
|
concatScenes,
|
|
339
363
|
buildNormalizeClipArgs,
|
|
364
|
+
FINAL_LOUDNORM_FILTER,
|
|
365
|
+
buildFinalEncodeArgs,
|
|
340
366
|
buildFinalConcatArgs,
|
|
341
367
|
buildCrossfadeArgs,
|
|
342
368
|
probeDuration,
|