@vosjs/cli 0.15.0 → 0.16.0
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.
- package/dist/{chunk-HGLKXIXH.js → chunk-PKHORUJ2.js} +342 -94
- package/dist/chunk-PKHORUJ2.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-37GVK3VS.js → run-5TIKH2IB.js} +2 -2
- package/package.json +4 -4
- package/schema/doc.schema.json +15 -6
- package/dist/chunk-HGLKXIXH.js.map +0 -1
- /package/dist/{run-37GVK3VS.js.map → run-5TIKH2IB.js.map} +0 -0
|
@@ -2359,8 +2359,13 @@ function parseTranscript(raw) {
|
|
|
2359
2359
|
|
|
2360
2360
|
// src/plugin/framesTake.ts
|
|
2361
2361
|
var VIDEO_TOKEN = "__VOILA_CLI_VIDEO__";
|
|
2362
|
+
function stillSupersample(w, h) {
|
|
2363
|
+
return Math.min(3, Math.max(1, Math.ceil(1800 / Math.max(1, w, h))));
|
|
2364
|
+
}
|
|
2362
2365
|
async function stillsInPage(opts) {
|
|
2363
2366
|
const w = window;
|
|
2367
|
+
const RW = opts.W * opts.ss;
|
|
2368
|
+
const RH = opts.H * opts.ss;
|
|
2364
2369
|
try {
|
|
2365
2370
|
const vblob = await (await fetch(opts.videoUrl)).blob();
|
|
2366
2371
|
const vurl = URL.createObjectURL(vblob);
|
|
@@ -2377,11 +2382,11 @@ async function stillsInPage(opts) {
|
|
|
2377
2382
|
THREE: w.__THREE__,
|
|
2378
2383
|
gsap: w.__gsap__,
|
|
2379
2384
|
resolution: {
|
|
2380
|
-
width:
|
|
2381
|
-
height:
|
|
2385
|
+
width: RW,
|
|
2386
|
+
height: RH,
|
|
2382
2387
|
pixelRatio: 1,
|
|
2383
|
-
drawingBufferWidth:
|
|
2384
|
-
drawingBufferHeight:
|
|
2388
|
+
drawingBufferWidth: RW,
|
|
2389
|
+
drawingBufferHeight: RH
|
|
2385
2390
|
},
|
|
2386
2391
|
preserveDrawingBuffer: true
|
|
2387
2392
|
};
|
|
@@ -2391,32 +2396,44 @@ async function stillsInPage(opts) {
|
|
|
2391
2396
|
timeline.pause();
|
|
2392
2397
|
timeline.seek(0, false);
|
|
2393
2398
|
const canvas = document.querySelector("canvas");
|
|
2394
|
-
canvas.width =
|
|
2395
|
-
canvas.height =
|
|
2396
|
-
canvas.style.width =
|
|
2397
|
-
canvas.style.height =
|
|
2399
|
+
canvas.width = RW;
|
|
2400
|
+
canvas.height = RH;
|
|
2401
|
+
canvas.style.width = RW + "px";
|
|
2402
|
+
canvas.style.height = RH + "px";
|
|
2403
|
+
const out = document.createElement("canvas");
|
|
2404
|
+
out.width = opts.W;
|
|
2405
|
+
out.height = opts.H;
|
|
2398
2406
|
const raf = () => new Promise((r) => requestAnimationFrame(r));
|
|
2399
2407
|
const wvr = () => w.__vos__?.waitForVideosReady ? w.__vos__.waitForVideosReady() : null;
|
|
2400
2408
|
const pending = () => w.__vos__?.pendingDecodes?.size ?? 0;
|
|
2401
|
-
const toPng = () => new Promise(
|
|
2402
|
-
|
|
2409
|
+
const toPng = () => new Promise((res, rej) => {
|
|
2410
|
+
let src = canvas;
|
|
2411
|
+
if (opts.ss > 1) {
|
|
2412
|
+
const g = out.getContext("2d");
|
|
2413
|
+
g.imageSmoothingEnabled = true;
|
|
2414
|
+
g.imageSmoothingQuality = "high";
|
|
2415
|
+
g.clearRect(0, 0, opts.W, opts.H);
|
|
2416
|
+
g.drawImage(canvas, 0, 0, opts.W, opts.H);
|
|
2417
|
+
src = out;
|
|
2418
|
+
}
|
|
2419
|
+
src.toBlob(
|
|
2403
2420
|
(b) => b ? res(b) : rej(new Error("toBlob failed")),
|
|
2404
2421
|
"image/png"
|
|
2405
|
-
)
|
|
2406
|
-
);
|
|
2422
|
+
);
|
|
2423
|
+
});
|
|
2407
2424
|
const collectVideos = () => {
|
|
2408
|
-
const
|
|
2425
|
+
const out2 = /* @__PURE__ */ new Set();
|
|
2409
2426
|
const cache = w.__vos__?.videoCache;
|
|
2410
2427
|
if (cache) {
|
|
2411
2428
|
const vals = cache instanceof Map ? [...cache.values()] : Object.values(cache);
|
|
2412
2429
|
for (const v of vals) {
|
|
2413
|
-
if (v?.tagName === "VIDEO")
|
|
2414
|
-
else if (v?.el?.tagName === "VIDEO")
|
|
2415
|
-
else if (v?.video?.tagName === "VIDEO")
|
|
2430
|
+
if (v?.tagName === "VIDEO") out2.add(v);
|
|
2431
|
+
else if (v?.el?.tagName === "VIDEO") out2.add(v.el);
|
|
2432
|
+
else if (v?.video?.tagName === "VIDEO") out2.add(v.video);
|
|
2416
2433
|
}
|
|
2417
2434
|
}
|
|
2418
|
-
document.querySelectorAll("video").forEach((v) =>
|
|
2419
|
-
return [...
|
|
2435
|
+
document.querySelectorAll("video").forEach((v) => out2.add(v));
|
|
2436
|
+
return [...out2];
|
|
2420
2437
|
};
|
|
2421
2438
|
const videosSettled = () => collectVideos().every((v) => !v.seeking && v.readyState >= 2);
|
|
2422
2439
|
const waitVideosSettled = async (maxMs) => {
|
|
@@ -2502,7 +2519,10 @@ async function framesTake(browser, dir, opts) {
|
|
|
2502
2519
|
const server = await startTakeServer(dir, {
|
|
2503
2520
|
"/render.html": renderPageHtml()
|
|
2504
2521
|
});
|
|
2505
|
-
const
|
|
2522
|
+
const ss = stillSupersample(width, height);
|
|
2523
|
+
const context = await browser.newContext({
|
|
2524
|
+
viewport: { width: width * ss, height: height * ss }
|
|
2525
|
+
});
|
|
2506
2526
|
try {
|
|
2507
2527
|
const page = await context.newPage();
|
|
2508
2528
|
page.on("console", (m) => {
|
|
@@ -2522,6 +2542,7 @@ async function framesTake(browser, dir, opts) {
|
|
|
2522
2542
|
videoUrl: `/${RECORDING_NAME}`,
|
|
2523
2543
|
W: width,
|
|
2524
2544
|
H: height,
|
|
2545
|
+
ss,
|
|
2525
2546
|
shots: named.map(({ time, name }) => ({ time, name }))
|
|
2526
2547
|
}).catch(() => {
|
|
2527
2548
|
});
|
|
@@ -2592,14 +2613,7 @@ async function writeIndexJson(result) {
|
|
|
2592
2613
|
}
|
|
2593
2614
|
|
|
2594
2615
|
// src/plugin/deliver.ts
|
|
2595
|
-
import {
|
|
2596
|
-
mkdir as mkdir4,
|
|
2597
|
-
mkdtemp,
|
|
2598
|
-
rename as rename4,
|
|
2599
|
-
rm as rm3,
|
|
2600
|
-
stat,
|
|
2601
|
-
writeFile as writeFile6
|
|
2602
|
-
} from "fs/promises";
|
|
2616
|
+
import { mkdir as mkdir4, mkdtemp, rename as rename4, rm as rm3, stat, writeFile as writeFile6 } from "fs/promises";
|
|
2603
2617
|
import { tmpdir } from "os";
|
|
2604
2618
|
import { join as join5, relative, resolve as resolve3 } from "path";
|
|
2605
2619
|
import { totalDuration } from "@vosjs/timeline";
|
|
@@ -2720,6 +2734,8 @@ async function renderTake(browser, dir, outFile, opts) {
|
|
|
2720
2734
|
import { compileVosConfig as compileVosConfig3 } from "@vosjs/core";
|
|
2721
2735
|
async function posterStillInPage(opts) {
|
|
2722
2736
|
const w = window;
|
|
2737
|
+
const RW = opts.W * opts.ss;
|
|
2738
|
+
const RH = opts.H * opts.ss;
|
|
2723
2739
|
try {
|
|
2724
2740
|
const mod = await import(
|
|
2725
2741
|
/* @vite-ignore */
|
|
@@ -2733,11 +2749,11 @@ async function posterStillInPage(opts) {
|
|
|
2733
2749
|
THREE: w.__THREE__,
|
|
2734
2750
|
gsap: w.__gsap__,
|
|
2735
2751
|
resolution: {
|
|
2736
|
-
width:
|
|
2737
|
-
height:
|
|
2752
|
+
width: RW,
|
|
2753
|
+
height: RH,
|
|
2738
2754
|
pixelRatio: 1,
|
|
2739
|
-
drawingBufferWidth:
|
|
2740
|
-
drawingBufferHeight:
|
|
2755
|
+
drawingBufferWidth: RW,
|
|
2756
|
+
drawingBufferHeight: RH
|
|
2741
2757
|
},
|
|
2742
2758
|
preserveDrawingBuffer: true
|
|
2743
2759
|
};
|
|
@@ -2747,16 +2763,27 @@ async function posterStillInPage(opts) {
|
|
|
2747
2763
|
timeline.pause();
|
|
2748
2764
|
timeline.seek(opts.time, false);
|
|
2749
2765
|
const canvas = document.querySelector("canvas");
|
|
2750
|
-
canvas.width =
|
|
2751
|
-
canvas.height =
|
|
2752
|
-
canvas.style.width =
|
|
2753
|
-
canvas.style.height =
|
|
2766
|
+
canvas.width = RW;
|
|
2767
|
+
canvas.height = RH;
|
|
2768
|
+
canvas.style.width = RW + "px";
|
|
2769
|
+
canvas.style.height = RH + "px";
|
|
2754
2770
|
const raf = () => new Promise((r) => requestAnimationFrame(r));
|
|
2755
2771
|
await raf();
|
|
2756
2772
|
await raf();
|
|
2757
2773
|
await raf();
|
|
2774
|
+
let src = canvas;
|
|
2775
|
+
if (opts.ss > 1) {
|
|
2776
|
+
const out = document.createElement("canvas");
|
|
2777
|
+
out.width = opts.W;
|
|
2778
|
+
out.height = opts.H;
|
|
2779
|
+
const g = out.getContext("2d");
|
|
2780
|
+
g.imageSmoothingEnabled = true;
|
|
2781
|
+
g.imageSmoothingQuality = "high";
|
|
2782
|
+
g.drawImage(canvas, 0, 0, opts.W, opts.H);
|
|
2783
|
+
src = out;
|
|
2784
|
+
}
|
|
2758
2785
|
const png = await new Promise(
|
|
2759
|
-
(res) =>
|
|
2786
|
+
(res) => src.toBlob((b) => res(b), "image/png")
|
|
2760
2787
|
);
|
|
2761
2788
|
if (!png) throw new Error("toBlob returned null");
|
|
2762
2789
|
await fetch("/save?name=" + opts.outName, { method: "POST", body: png });
|
|
@@ -2774,8 +2801,9 @@ async function renderPosterStills(browser, config, serveDir, shots, time) {
|
|
|
2774
2801
|
});
|
|
2775
2802
|
try {
|
|
2776
2803
|
for (const shot of shots) {
|
|
2804
|
+
const ss = stillSupersample(shot.width, shot.height);
|
|
2777
2805
|
const context = await browser.newContext({
|
|
2778
|
-
viewport: { width: shot.width, height: shot.height }
|
|
2806
|
+
viewport: { width: shot.width * ss, height: shot.height * ss }
|
|
2779
2807
|
});
|
|
2780
2808
|
try {
|
|
2781
2809
|
const page = await context.newPage();
|
|
@@ -2794,6 +2822,7 @@ async function renderPosterStills(browser, config, serveDir, shots, time) {
|
|
|
2794
2822
|
animationCode,
|
|
2795
2823
|
W: shot.width,
|
|
2796
2824
|
H: shot.height,
|
|
2825
|
+
ss,
|
|
2797
2826
|
time,
|
|
2798
2827
|
outName: shot.name
|
|
2799
2828
|
}).catch(() => {
|
|
@@ -3325,7 +3354,8 @@ function blurPlane(src, w, h, r, passes = 3) {
|
|
|
3325
3354
|
for (let y = 0; y < h; y++) {
|
|
3326
3355
|
let acc = 0;
|
|
3327
3356
|
const row = y * w;
|
|
3328
|
-
for (let x = -r; x <= r; x++)
|
|
3357
|
+
for (let x = -r; x <= r; x++)
|
|
3358
|
+
acc += src[row + Math.min(w - 1, Math.max(0, x))];
|
|
3329
3359
|
for (let x = 0; x < w; x++) {
|
|
3330
3360
|
tmp[row + x] = acc / (2 * r + 1);
|
|
3331
3361
|
const add = src[row + Math.min(w - 1, x + r + 1)];
|
|
@@ -3335,7 +3365,8 @@ function blurPlane(src, w, h, r, passes = 3) {
|
|
|
3335
3365
|
}
|
|
3336
3366
|
for (let x = 0; x < w; x++) {
|
|
3337
3367
|
let acc = 0;
|
|
3338
|
-
for (let y = -r; y <= r; y++)
|
|
3368
|
+
for (let y = -r; y <= r; y++)
|
|
3369
|
+
acc += tmp[Math.min(h - 1, Math.max(0, y)) * w + x];
|
|
3339
3370
|
for (let y = 0; y < h; y++) {
|
|
3340
3371
|
src[y * w + x] = acc / (2 * r + 1);
|
|
3341
3372
|
const add = tmp[Math.min(h - 1, y + r + 1) * w + x];
|
|
@@ -3351,7 +3382,8 @@ function roundedCoverage(x, y, rect, r) {
|
|
|
3351
3382
|
for (const dx of [0.25, 0.75]) {
|
|
3352
3383
|
const px = x + dx;
|
|
3353
3384
|
const py = y + dy;
|
|
3354
|
-
if (px < rect.x || py < rect.y || px > rect.x + rect.w || py > rect.y + rect.h)
|
|
3385
|
+
if (px < rect.x || py < rect.y || px > rect.x + rect.w || py > rect.y + rect.h)
|
|
3386
|
+
continue;
|
|
3355
3387
|
const cx = Math.min(Math.max(px, rect.x + r), rect.x + rect.w - r);
|
|
3356
3388
|
const cy = Math.min(Math.max(py, rect.y + r), rect.y + rect.h - r);
|
|
3357
3389
|
if ((px - cx) ** 2 + (py - cy) ** 2 <= r * r) inside++;
|
|
@@ -3362,24 +3394,34 @@ function roundedCoverage(x, y, rect, r) {
|
|
|
3362
3394
|
function bakeShot(shot, opts = {}) {
|
|
3363
3395
|
const margin = Math.round(shot.w * (opts.margin ?? 0.06));
|
|
3364
3396
|
const radius = shot.w * (opts.radius ?? 0.014);
|
|
3365
|
-
const shadowA = opts.shadow ?? 0.
|
|
3366
|
-
const blur = Math.round(shot.w * (opts.blur ?? 0.
|
|
3367
|
-
const offsetY = Math.round(shot.w * (opts.offsetY ?? 0.
|
|
3397
|
+
const shadowA = opts.shadow ?? 0.3;
|
|
3398
|
+
const blur = Math.round(shot.w * (opts.blur ?? 0.05));
|
|
3399
|
+
const offsetY = Math.round(shot.w * (opts.offsetY ?? 0.02));
|
|
3368
3400
|
const hair = opts.hairline ?? 0;
|
|
3369
3401
|
const w = shot.w + margin * 2;
|
|
3370
3402
|
const h = shot.h + margin * 2;
|
|
3371
3403
|
const out = new Uint8Array(w * h * 4);
|
|
3372
3404
|
const rect = { x: margin, y: margin, w: shot.w, h: shot.h };
|
|
3373
3405
|
if (shadowA > 0) {
|
|
3374
|
-
const
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3406
|
+
const layers = [
|
|
3407
|
+
[Math.max(1, Math.round(blur / 4)), Math.round(offsetY / 5), 0.4],
|
|
3408
|
+
[blur, offsetY, 0.6]
|
|
3409
|
+
];
|
|
3410
|
+
const acc = new Float32Array(w * h);
|
|
3411
|
+
for (const [lb, lo, share] of layers) {
|
|
3412
|
+
const mask = new Float32Array(w * h);
|
|
3413
|
+
for (let y = 0; y < h; y++)
|
|
3414
|
+
for (let x = 0; x < w; x++) {
|
|
3415
|
+
const c = roundedCoverage(x, y - lo, rect, radius);
|
|
3416
|
+
if (c > 0) mask[y * w + x] = c;
|
|
3417
|
+
}
|
|
3418
|
+
blurPlane(mask, w, h, Math.max(1, Math.round(lb / 2)));
|
|
3419
|
+
const a = shadowA * share;
|
|
3420
|
+
for (let i = 0; i < w * h; i++)
|
|
3421
|
+
acc[i] = 1 - (1 - acc[i]) * (1 - mask[i] * a);
|
|
3422
|
+
}
|
|
3381
3423
|
for (let i = 0; i < w * h; i++) {
|
|
3382
|
-
const a =
|
|
3424
|
+
const a = acc[i];
|
|
3383
3425
|
if (a <= 2e-3) continue;
|
|
3384
3426
|
out[i * 4] = 0;
|
|
3385
3427
|
out[i * 4 + 1] = 0;
|
|
@@ -3399,7 +3441,12 @@ function bakeShot(shot, opts = {}) {
|
|
|
3399
3441
|
let g = shot.data[si + 1];
|
|
3400
3442
|
let b = shot.data[si + 2];
|
|
3401
3443
|
if (hair > 0) {
|
|
3402
|
-
const edge = Math.min(
|
|
3444
|
+
const edge = Math.min(
|
|
3445
|
+
x - rect.x,
|
|
3446
|
+
rect.x + rect.w - x,
|
|
3447
|
+
y - rect.y,
|
|
3448
|
+
rect.y + rect.h - y
|
|
3449
|
+
);
|
|
3403
3450
|
if (edge < 1.5) {
|
|
3404
3451
|
r = Math.round(r * (1 - hair));
|
|
3405
3452
|
g = Math.round(g * (1 - hair));
|
|
@@ -3924,12 +3971,18 @@ var rgb = (hex2) => {
|
|
|
3924
3971
|
const n = parseInt(m[1], 16);
|
|
3925
3972
|
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
3926
3973
|
};
|
|
3927
|
-
var toHex = (c) => "#" + c.map(
|
|
3974
|
+
var toHex = (c) => "#" + c.map(
|
|
3975
|
+
(v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0")
|
|
3976
|
+
).join("");
|
|
3928
3977
|
function mixHex(a, b, t) {
|
|
3929
3978
|
const pa = rgb(a);
|
|
3930
3979
|
const pb = rgb(b);
|
|
3931
3980
|
if (!pa || !pb) return a;
|
|
3932
|
-
return toHex([
|
|
3981
|
+
return toHex([
|
|
3982
|
+
pa[0] + (pb[0] - pa[0]) * t,
|
|
3983
|
+
pa[1] + (pb[1] - pa[1]) * t,
|
|
3984
|
+
pa[2] + (pb[2] - pa[2]) * t
|
|
3985
|
+
]);
|
|
3933
3986
|
}
|
|
3934
3987
|
function rgba(hex2, alpha) {
|
|
3935
3988
|
const c = rgb(hex2) ?? [255, 255, 255];
|
|
@@ -3945,14 +3998,15 @@ function resolveFace(family, weights) {
|
|
|
3945
3998
|
const first = family.split(",")[0].replace(/['"]/g, "").replace(/\s+variable$/i, "").trim();
|
|
3946
3999
|
const entry = findFontFamily2(first);
|
|
3947
4000
|
if (!entry) return null;
|
|
3948
|
-
const fonts = [
|
|
4001
|
+
const fonts = [
|
|
4002
|
+
...new Set(weights.map((w) => nearestFontWeight(entry, w)))
|
|
4003
|
+
].map((w) => ({
|
|
3949
4004
|
family: entry.family,
|
|
3950
4005
|
url: fontFaceUrl(entry.slug, w),
|
|
3951
4006
|
weight: w
|
|
3952
4007
|
}));
|
|
3953
4008
|
return { stack: fontStack(entry), category: entry.category, fonts };
|
|
3954
4009
|
}
|
|
3955
|
-
var HOUSE_SERIF = "Fraunces";
|
|
3956
4010
|
function posterValues(brand, words) {
|
|
3957
4011
|
const b = brand ?? {};
|
|
3958
4012
|
const bgA = b.bgA && HEX.test(b.bgA) ? b.bgA : null;
|
|
@@ -3974,7 +4028,11 @@ function posterValues(brand, words) {
|
|
|
3974
4028
|
if (bgA) values.grain = lightGround ? 10 : 22;
|
|
3975
4029
|
if (accent) values.blobA = rgba(accent, lightGround ? 0.28 : 0.4);
|
|
3976
4030
|
if (bgC) values.blobB = rgba(bgC, 0.75);
|
|
3977
|
-
if (accent)
|
|
4031
|
+
if (accent)
|
|
4032
|
+
values.blobC = rgba(
|
|
4033
|
+
mixHex(accent, "#ffffff", 0.55),
|
|
4034
|
+
lightGround ? 0.35 : 0.25
|
|
4035
|
+
);
|
|
3978
4036
|
if (wordmark) values.brand = wordmark;
|
|
3979
4037
|
const headline = (words.headline ?? "").trim();
|
|
3980
4038
|
if (headline) values.headline = headline;
|
|
@@ -3982,10 +4040,9 @@ function posterValues(brand, words) {
|
|
|
3982
4040
|
values.kicker = kicker ? kicker : [wordmark, release].filter(Boolean).join(" ").toUpperCase();
|
|
3983
4041
|
const fonts = [];
|
|
3984
4042
|
const display = resolveFace(b.fontDisplay, [600, 700]);
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
fonts.push(...serif.fonts);
|
|
4043
|
+
if (display) {
|
|
4044
|
+
values.fontDisplay = display.stack;
|
|
4045
|
+
fonts.push(...display.fonts);
|
|
3989
4046
|
}
|
|
3990
4047
|
const body = resolveFace(b.fontBody, [700]);
|
|
3991
4048
|
if (body) {
|
|
@@ -3996,7 +4053,6 @@ function posterValues(brand, words) {
|
|
|
3996
4053
|
}
|
|
3997
4054
|
|
|
3998
4055
|
// src/plugin/stages.ts
|
|
3999
|
-
var HOUSE_SERIF2 = "Fraunces";
|
|
4000
4056
|
var str = (v, fallback) => typeof v === "string" && v.trim() ? v.trim() : fallback;
|
|
4001
4057
|
var firstFamily = (stack) => stack.split(",")[0].replace(/['"]/g, "").trim();
|
|
4002
4058
|
function stageSplitCover(input) {
|
|
@@ -4007,7 +4063,7 @@ function stageSplitCover(input) {
|
|
|
4007
4063
|
const ground = `linear-gradient(135deg, ${str(v.bgA, "#8a3d2a")}, ${str(v.bgC, str(v.bgB, "#5c5a2e"))})`;
|
|
4008
4064
|
const ink = str(v.ink, "#fff6ec");
|
|
4009
4065
|
const inkSoft = str(v.inkSoft, ink);
|
|
4010
|
-
const
|
|
4066
|
+
const display = firstFamily(str(v.fontDisplay, "Lexend"));
|
|
4011
4067
|
const body = firstFamily(str(v.fontBody, "Lexend"));
|
|
4012
4068
|
const headline = str(v.headline, "");
|
|
4013
4069
|
const kicker = str(v.kicker, "");
|
|
@@ -4026,8 +4082,8 @@ function stageSplitCover(input) {
|
|
|
4026
4082
|
`frame.inset=${JSON.stringify(inset)}`,
|
|
4027
4083
|
'frame.focus={"cx":0,"cy":0}',
|
|
4028
4084
|
"frame.radius=16",
|
|
4029
|
-
"frame.shadow=0.
|
|
4030
|
-
"frame.shadowContact=0
|
|
4085
|
+
"frame.shadow=0.5",
|
|
4086
|
+
"frame.shadowContact=0",
|
|
4031
4087
|
"frame.border=0",
|
|
4032
4088
|
"zoom=[]",
|
|
4033
4089
|
`tilt=[{"id":"stage","in":0,"out":${input.sourceSeconds.toFixed(3)},"rx":3,"ry":${portrait || square ? 0 : 10}}]`,
|
|
@@ -4044,7 +4100,10 @@ function stageSplitCover(input) {
|
|
|
4044
4100
|
if (!text) return;
|
|
4045
4101
|
const lines = text.split("\n");
|
|
4046
4102
|
const longest = Math.max(...lines.map((l) => l.length));
|
|
4047
|
-
const widest = Math.min(
|
|
4103
|
+
const widest = Math.min(
|
|
4104
|
+
column,
|
|
4105
|
+
longest * px * (preset === "title" ? 0.5 : 0.62) / designW
|
|
4106
|
+
);
|
|
4048
4107
|
const lh = preset === "title" ? 1.05 : 1.2;
|
|
4049
4108
|
const h = lines.length * px * lh / 1080;
|
|
4050
4109
|
clips.push({
|
|
@@ -4059,24 +4118,157 @@ function stageSplitCover(input) {
|
|
|
4059
4118
|
maxWidth: column,
|
|
4060
4119
|
lineHeight: lh,
|
|
4061
4120
|
transform: { x: left + widest / 2, y, scale: 1, rotation: 0 },
|
|
4062
|
-
shadow:
|
|
4121
|
+
// Words on the ground carry no footage shadow: a drop shadow under a
|
|
4122
|
+
// headline on a plate is the old-web tell.
|
|
4123
|
+
shadow: 0,
|
|
4063
4124
|
start: 0,
|
|
4064
4125
|
duration: +input.outputSeconds.toFixed(3),
|
|
4065
4126
|
enter: "none",
|
|
4066
4127
|
exit: "none",
|
|
4067
4128
|
...extra
|
|
4068
4129
|
});
|
|
4069
|
-
boxes.push({
|
|
4130
|
+
boxes.push({
|
|
4131
|
+
x: left,
|
|
4132
|
+
y: y - h / 2,
|
|
4133
|
+
w: widest,
|
|
4134
|
+
h,
|
|
4135
|
+
color,
|
|
4136
|
+
role,
|
|
4137
|
+
label: text.length > 24 ? `${text.slice(0, 24)}\u2026` : text
|
|
4138
|
+
});
|
|
4070
4139
|
};
|
|
4071
4140
|
const kickerY = portrait ? 0.1 : square ? 0.12 : 0.24;
|
|
4072
4141
|
const titleY = portrait ? 0.24 : square ? 0.28 : 0.46;
|
|
4073
4142
|
const brandY = portrait ? 0.94 : square ? 0.94 : 0.86;
|
|
4074
|
-
word(
|
|
4075
|
-
|
|
4076
|
-
|
|
4143
|
+
word(
|
|
4144
|
+
"stage-kicker",
|
|
4145
|
+
kicker,
|
|
4146
|
+
"label",
|
|
4147
|
+
"JetBrains Mono",
|
|
4148
|
+
19,
|
|
4149
|
+
kickerY,
|
|
4150
|
+
inkSoft,
|
|
4151
|
+
{ letterSpacing: 6, weight: 400 },
|
|
4152
|
+
"body"
|
|
4153
|
+
);
|
|
4154
|
+
word(
|
|
4155
|
+
"stage-title",
|
|
4156
|
+
headline,
|
|
4157
|
+
"title",
|
|
4158
|
+
display,
|
|
4159
|
+
size,
|
|
4160
|
+
titleY,
|
|
4161
|
+
ink,
|
|
4162
|
+
{ weight: 600, letterSpacing: -Math.round(size * 0.02) },
|
|
4163
|
+
"headline"
|
|
4164
|
+
);
|
|
4165
|
+
word(
|
|
4166
|
+
"stage-brand",
|
|
4167
|
+
brand,
|
|
4168
|
+
"label",
|
|
4169
|
+
body,
|
|
4170
|
+
25,
|
|
4171
|
+
brandY,
|
|
4172
|
+
ink,
|
|
4173
|
+
{ weight: 700, letterSpacing: 1 },
|
|
4174
|
+
"body"
|
|
4175
|
+
);
|
|
4077
4176
|
set.push(`overlays=${JSON.stringify(clips)}`);
|
|
4078
4177
|
return { set, text: boxes, shot };
|
|
4079
4178
|
}
|
|
4179
|
+
var TILE_MAX_PX = 700;
|
|
4180
|
+
function isTileSize(size) {
|
|
4181
|
+
return Math.max(size.w, size.h) < TILE_MAX_PX;
|
|
4182
|
+
}
|
|
4183
|
+
function stageTile(input) {
|
|
4184
|
+
const R = input.size.w / Math.max(1, input.size.h);
|
|
4185
|
+
const square = R <= 1.15;
|
|
4186
|
+
const v = input.values;
|
|
4187
|
+
const ground = `linear-gradient(135deg, ${str(v.bgA, "#8a3d2a")}, ${str(v.bgC, str(v.bgB, "#5c5a2e"))})`;
|
|
4188
|
+
const ink = str(v.ink, "#fff6ec");
|
|
4189
|
+
const display = firstFamily(str(v.fontDisplay, "Lexend"));
|
|
4190
|
+
const headline = str(v.headline, "") || str(v.brand, "Release");
|
|
4191
|
+
const wordless = input.text === "none";
|
|
4192
|
+
const aspect = input.footageAspect && input.footageAspect > 0 ? input.footageAspect : 16 / 9;
|
|
4193
|
+
const left = square ? 0.08 : 0.07;
|
|
4194
|
+
const top = wordless ? square ? 0.1 : 0.12 : square ? 0.42 : 0.47;
|
|
4195
|
+
const visible = wordless ? square ? 0.66 : 0.8 : square ? 0.56 : 0.62;
|
|
4196
|
+
const cardW = (1 - left) / visible;
|
|
4197
|
+
const cardH = cardW * R / aspect;
|
|
4198
|
+
const inset = {
|
|
4199
|
+
left,
|
|
4200
|
+
right: +(1 - left - cardW).toFixed(4),
|
|
4201
|
+
top,
|
|
4202
|
+
bottom: +(1 - top - cardH).toFixed(4)
|
|
4203
|
+
};
|
|
4204
|
+
const shot = {
|
|
4205
|
+
x: inset.left,
|
|
4206
|
+
y: inset.top,
|
|
4207
|
+
w: 1 - inset.left - inset.right,
|
|
4208
|
+
h: 1 - inset.top - inset.bottom
|
|
4209
|
+
};
|
|
4210
|
+
const set = [
|
|
4211
|
+
`frame.background=${JSON.stringify(ground)}`,
|
|
4212
|
+
"frame.backgroundMedia=null",
|
|
4213
|
+
"frame.fit=cover",
|
|
4214
|
+
`frame.inset=${JSON.stringify(inset)}`,
|
|
4215
|
+
'frame.focus={"cx":0,"cy":0}',
|
|
4216
|
+
"frame.radius=24",
|
|
4217
|
+
"frame.shadow=0.5",
|
|
4218
|
+
"frame.shadowContact=0",
|
|
4219
|
+
"frame.border=0",
|
|
4220
|
+
"zoom=[]",
|
|
4221
|
+
"tilt=[]",
|
|
4222
|
+
"cursor.visible=false",
|
|
4223
|
+
"cursor.clickFx.style=none"
|
|
4224
|
+
];
|
|
4225
|
+
const designW = 1080 * input.size.w / input.size.h;
|
|
4226
|
+
const column = square ? 0.84 : 0.86;
|
|
4227
|
+
const px = square ? 96 : 108;
|
|
4228
|
+
const lines = headline.split("\n");
|
|
4229
|
+
const longest = Math.max(...lines.map((l) => l.length));
|
|
4230
|
+
const widest = Math.min(column, longest * px * 0.5 / designW);
|
|
4231
|
+
const lh = 1.05;
|
|
4232
|
+
const h = lines.length * px * lh / 1080;
|
|
4233
|
+
const y = square ? 0.2 : 0.24;
|
|
4234
|
+
const clip = {
|
|
4235
|
+
id: "stage-title",
|
|
4236
|
+
kind: "text",
|
|
4237
|
+
text: headline,
|
|
4238
|
+
preset: "title",
|
|
4239
|
+
family: display,
|
|
4240
|
+
size: px,
|
|
4241
|
+
color: ink,
|
|
4242
|
+
align: "left",
|
|
4243
|
+
maxWidth: column,
|
|
4244
|
+
lineHeight: lh,
|
|
4245
|
+
weight: 600,
|
|
4246
|
+
letterSpacing: -Math.round(px * 0.02),
|
|
4247
|
+
transform: { x: left + widest / 2, y, scale: 1, rotation: 0 },
|
|
4248
|
+
shadow: 0,
|
|
4249
|
+
start: 0,
|
|
4250
|
+
duration: +input.outputSeconds.toFixed(3),
|
|
4251
|
+
enter: "none",
|
|
4252
|
+
exit: "none"
|
|
4253
|
+
};
|
|
4254
|
+
if (wordless) {
|
|
4255
|
+
set.push("overlays=[]");
|
|
4256
|
+
return { set, text: [], shot };
|
|
4257
|
+
}
|
|
4258
|
+
set.push(`overlays=${JSON.stringify([clip])}`);
|
|
4259
|
+
const text = [
|
|
4260
|
+
{
|
|
4261
|
+
x: left,
|
|
4262
|
+
y: y - h / 2,
|
|
4263
|
+
w: widest,
|
|
4264
|
+
h,
|
|
4265
|
+
color: ink,
|
|
4266
|
+
role: "headline",
|
|
4267
|
+
label: headline.length > 24 ? `${headline.slice(0, 24)}\u2026` : headline
|
|
4268
|
+
}
|
|
4269
|
+
];
|
|
4270
|
+
return { set, text, shot };
|
|
4271
|
+
}
|
|
4080
4272
|
|
|
4081
4273
|
// src/plugin/motionPlan.ts
|
|
4082
4274
|
import { ratedSegments as ratedSegments4, spanOutputExtent as spanOutputExtent4 } from "@vosjs/studio-core";
|
|
@@ -4293,6 +4485,10 @@ function templateForCard(d, opts) {
|
|
|
4293
4485
|
if (opts.poster === null) return null;
|
|
4294
4486
|
if (opts.poster) return { config: opts.poster.config, from: opts.poster.from };
|
|
4295
4487
|
if (!d.template) return null;
|
|
4488
|
+
if (isTileSize(d.px)) {
|
|
4489
|
+
const config2 = templateByName(d.template) ?? templateByName("card-on-gradient");
|
|
4490
|
+
if (config2) return { config: config2, from: "stage tile", stage: "tile" };
|
|
4491
|
+
}
|
|
4296
4492
|
let name = d.template;
|
|
4297
4493
|
let note;
|
|
4298
4494
|
const wants = templateOf(templateByName(name) ?? {});
|
|
@@ -4303,7 +4499,8 @@ function templateForCard(d, opts) {
|
|
|
4303
4499
|
}
|
|
4304
4500
|
const config = templateByName(name);
|
|
4305
4501
|
if (!config) return null;
|
|
4306
|
-
if (name === "split-cover")
|
|
4502
|
+
if (name === "split-cover")
|
|
4503
|
+
return { config, from: "stage split-cover", note, stage: "split-cover" };
|
|
4307
4504
|
return { config, from: `template ${name}`, note };
|
|
4308
4505
|
}
|
|
4309
4506
|
function lookOverrides(look, placement, size, video, opts) {
|
|
@@ -4324,7 +4521,12 @@ function lookOverrides(look, placement, size, video, opts) {
|
|
|
4324
4521
|
}
|
|
4325
4522
|
if (!opts.keepMedia) set.push("frame.backgroundMedia=null");
|
|
4326
4523
|
if (opts.still) {
|
|
4327
|
-
set.push(
|
|
4524
|
+
set.push(
|
|
4525
|
+
"zoom=[]",
|
|
4526
|
+
"tilt=[]",
|
|
4527
|
+
"cursor.visible=false",
|
|
4528
|
+
"cursor.clickFx.style=none"
|
|
4529
|
+
);
|
|
4328
4530
|
}
|
|
4329
4531
|
return set;
|
|
4330
4532
|
}
|
|
@@ -4496,9 +4698,14 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4496
4698
|
if (!set.length) return opts.overrides;
|
|
4497
4699
|
return { ...opts.overrides, set };
|
|
4498
4700
|
};
|
|
4499
|
-
const cardPlans = destinations.filter(
|
|
4701
|
+
const cardPlans = destinations.filter(
|
|
4702
|
+
(d) => d.kind !== "video" && d.genre === "card" && !NOT_FROM_FOOTAGE[d.id]
|
|
4703
|
+
).map((d) => ({ d, plan: templateForCard(d, opts) })).filter(
|
|
4704
|
+
(p) => p.plan !== null
|
|
4705
|
+
);
|
|
4500
4706
|
const posterCardIds = new Set(cardPlans.map((p) => p.d.id));
|
|
4501
|
-
for (const p of cardPlans)
|
|
4707
|
+
for (const p of cardPlans)
|
|
4708
|
+
if (p.plan.note) skipped.push(`note: ${p.plan.note}`);
|
|
4502
4709
|
if (cardPlans.length) {
|
|
4503
4710
|
const meta = doc.source.meta;
|
|
4504
4711
|
const heroTime = opts.shotTime ?? (stillTimes.length ? stillTimes[0] : duration / 2);
|
|
@@ -4534,19 +4741,24 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4534
4741
|
const baked = bakeShot(raw, {
|
|
4535
4742
|
margin: PAD,
|
|
4536
4743
|
hairline: fill.lightGround ? 0.14 : 0,
|
|
4537
|
-
shadow: fill.lightGround ? 0.
|
|
4744
|
+
shadow: fill.lightGround ? 0.28 : 0.4
|
|
4538
4745
|
});
|
|
4539
4746
|
await writeFile6(join5(serveDir, "shot.png"), encodePng(baked));
|
|
4540
4747
|
const shotAspect = raw.w / raw.h;
|
|
4541
4748
|
for (const { d, plan } of cardPlans) {
|
|
4542
4749
|
if (plan.stage) {
|
|
4543
|
-
const
|
|
4750
|
+
const stageInput = {
|
|
4544
4751
|
size: d.px,
|
|
4545
4752
|
values: fill.values,
|
|
4546
4753
|
sourceSeconds: meta.durationMs / 1e3,
|
|
4547
|
-
outputSeconds: duration
|
|
4548
|
-
|
|
4549
|
-
|
|
4754
|
+
outputSeconds: duration,
|
|
4755
|
+
text: d.text,
|
|
4756
|
+
footageAspect: (meta.captureWidth ?? meta.width) / (meta.captureHeight ?? meta.height)
|
|
4757
|
+
};
|
|
4758
|
+
const staged = plan.stage === "tile" ? stageTile(stageInput) : stageSplitCover(stageInput);
|
|
4759
|
+
opts.onPhase?.(
|
|
4760
|
+
`${d.channel} ${d.asset} (${specWords(d)}) from ${plan.from}`
|
|
4761
|
+
);
|
|
4550
4762
|
const shotDir = await mkdtemp(join5(tmpdir(), "vos-stage-"));
|
|
4551
4763
|
try {
|
|
4552
4764
|
const captured = await framesTake(browser, dir, {
|
|
@@ -4563,7 +4775,9 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4563
4775
|
await rename4(captured.frames[0].file, to2);
|
|
4564
4776
|
const bytes2 = (await stat(to2)).size;
|
|
4565
4777
|
if (d.maxBytes !== void 0 && bytes2 > d.maxBytes) {
|
|
4566
|
-
skipped.push(
|
|
4778
|
+
skipped.push(
|
|
4779
|
+
`${d.channel} ${d.asset}: ${overCeiling(bytes2, d.maxBytes)} (kept at ${to2})`
|
|
4780
|
+
);
|
|
4567
4781
|
continue;
|
|
4568
4782
|
}
|
|
4569
4783
|
assets.push({
|
|
@@ -4577,9 +4791,10 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4577
4791
|
seconds: null,
|
|
4578
4792
|
frameTime: heroTime,
|
|
4579
4793
|
source: "stage",
|
|
4580
|
-
template:
|
|
4794
|
+
template: `${plan.stage}-stage`,
|
|
4581
4795
|
text: staged.text,
|
|
4582
|
-
shot: staged.shot
|
|
4796
|
+
shot: staged.shot,
|
|
4797
|
+
...plan.stage === "tile" ? { crop: true } : {}
|
|
4583
4798
|
});
|
|
4584
4799
|
} finally {
|
|
4585
4800
|
await rm3(shotDir, { recursive: true, force: true });
|
|
@@ -4618,7 +4833,9 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4618
4833
|
opts.posterTime ?? posterDuration * 0.9,
|
|
4619
4834
|
Math.max(0, posterDuration - 0.05)
|
|
4620
4835
|
);
|
|
4621
|
-
opts.onPhase?.(
|
|
4836
|
+
opts.onPhase?.(
|
|
4837
|
+
`${d.channel} ${d.asset} (${specWords(d)}) from ${plan.from}, ${filled.aspect}`
|
|
4838
|
+
);
|
|
4622
4839
|
await renderPosterStills(
|
|
4623
4840
|
browser,
|
|
4624
4841
|
config,
|
|
@@ -5033,7 +5250,7 @@ function stillFindings(a, img, m) {
|
|
|
5033
5250
|
const sh = Math.min(1, a.shot.y + a.shot.h) * img.h - sy;
|
|
5034
5251
|
const rect = { x: sx, y: sy, w: Math.max(1, sw), h: Math.max(1, sh) };
|
|
5035
5252
|
const ink = inkCoverage(img, rect);
|
|
5036
|
-
if (ink < BLANK_INK) {
|
|
5253
|
+
if (ink < (a.crop ? BLANK_INK / 2 : BLANK_INK)) {
|
|
5037
5254
|
out.push({
|
|
5038
5255
|
code: "blank",
|
|
5039
5256
|
severity: "error",
|
|
@@ -5043,7 +5260,7 @@ function stillFindings(a, img, m) {
|
|
|
5043
5260
|
bbox: rect
|
|
5044
5261
|
});
|
|
5045
5262
|
}
|
|
5046
|
-
if (a.shot.w < 0.5 || a.shot.w > 1.2) {
|
|
5263
|
+
if (!a.crop && (a.shot.w < 0.5 || a.shot.w > 1.2)) {
|
|
5047
5264
|
out.push({
|
|
5048
5265
|
code: "subject",
|
|
5049
5266
|
severity: "error",
|
|
@@ -5131,7 +5348,12 @@ function stillFindings(a, img, m) {
|
|
|
5131
5348
|
function textFindings(a, img) {
|
|
5132
5349
|
const out = [];
|
|
5133
5350
|
for (const t of a.text ?? []) {
|
|
5134
|
-
const box = {
|
|
5351
|
+
const box = {
|
|
5352
|
+
x: t.x * img.w,
|
|
5353
|
+
y: t.y * img.h,
|
|
5354
|
+
w: t.w * img.w,
|
|
5355
|
+
h: t.h * img.h
|
|
5356
|
+
};
|
|
5135
5357
|
const name = t.label ? `"${t.label}"` : "a text box";
|
|
5136
5358
|
if (box.x < 0 || box.y < 0 || box.x + box.w > img.w + 0.5 || box.y + box.h > img.h + 0.5) {
|
|
5137
5359
|
out.push({
|
|
@@ -5206,7 +5428,9 @@ function duplicateFindings(stills) {
|
|
|
5206
5428
|
if (g.length > 1) groups.push(g);
|
|
5207
5429
|
}
|
|
5208
5430
|
return groups.map((g) => {
|
|
5209
|
-
const composed = g.every(
|
|
5431
|
+
const composed = g.every(
|
|
5432
|
+
(s) => stills.find((x) => x.destination === s.destination)?.composed
|
|
5433
|
+
);
|
|
5210
5434
|
return {
|
|
5211
5435
|
code: "duplicate",
|
|
5212
5436
|
severity: composed ? "info" : g.length >= 3 ? "error" : "warning",
|
|
@@ -5220,7 +5444,21 @@ async function videoFrame(file, at2, ffmpeg) {
|
|
|
5220
5444
|
try {
|
|
5221
5445
|
const { stdout } = await execFileP(
|
|
5222
5446
|
ffmpeg,
|
|
5223
|
-
[
|
|
5447
|
+
[
|
|
5448
|
+
"-v",
|
|
5449
|
+
"error",
|
|
5450
|
+
"-ss",
|
|
5451
|
+
at2.toFixed(3),
|
|
5452
|
+
"-i",
|
|
5453
|
+
file,
|
|
5454
|
+
"-frames:v",
|
|
5455
|
+
"1",
|
|
5456
|
+
"-f",
|
|
5457
|
+
"image2pipe",
|
|
5458
|
+
"-vcodec",
|
|
5459
|
+
"png",
|
|
5460
|
+
"-"
|
|
5461
|
+
],
|
|
5224
5462
|
{ encoding: "buffer", maxBuffer: 64 * 1024 * 1024 }
|
|
5225
5463
|
);
|
|
5226
5464
|
return decodePng(new Uint8Array(stdout));
|
|
@@ -5283,14 +5521,19 @@ async function pictureChecks(assets) {
|
|
|
5283
5521
|
}
|
|
5284
5522
|
const seconds = a.seconds ?? 0;
|
|
5285
5523
|
const first = await videoFrame(a.file, 0, "ffmpeg");
|
|
5286
|
-
const last = await videoFrame(
|
|
5524
|
+
const last = await videoFrame(
|
|
5525
|
+
a.file,
|
|
5526
|
+
Math.max(0, seconds - 0.1),
|
|
5527
|
+
"ffmpeg"
|
|
5528
|
+
);
|
|
5287
5529
|
for (const [name, img] of [
|
|
5288
5530
|
["first", first],
|
|
5289
5531
|
["last", last]
|
|
5290
5532
|
]) {
|
|
5291
5533
|
if (!img) continue;
|
|
5292
5534
|
const m = measureStill(img);
|
|
5293
|
-
if (name === "first")
|
|
5535
|
+
if (name === "first")
|
|
5536
|
+
measured.push({ destination: a.destination, measure: m });
|
|
5294
5537
|
const subject = m.card ?? { x: 0, y: 0, w: img.w, h: img.h };
|
|
5295
5538
|
const ink = inkCoverage(img, subject);
|
|
5296
5539
|
if (ink < BLANK_INK) {
|
|
@@ -5316,7 +5559,11 @@ async function pictureChecks(assets) {
|
|
|
5316
5559
|
}
|
|
5317
5560
|
}
|
|
5318
5561
|
findings.push(...duplicateFindings(stills));
|
|
5319
|
-
const order = {
|
|
5562
|
+
const order = {
|
|
5563
|
+
error: 0,
|
|
5564
|
+
warning: 1,
|
|
5565
|
+
info: 2
|
|
5566
|
+
};
|
|
5320
5567
|
findings.sort((a, b) => order[a.severity] - order[b.severity]);
|
|
5321
5568
|
return { findings, measured };
|
|
5322
5569
|
}
|
|
@@ -5468,7 +5715,8 @@ async function validateKit(kitPath, opts = {}) {
|
|
|
5468
5715
|
text: a.text,
|
|
5469
5716
|
seconds,
|
|
5470
5717
|
composed: a.composed,
|
|
5471
|
-
shot: a.source === "poster" || a.source === "stage" ? a.shot : void 0
|
|
5718
|
+
shot: a.source === "poster" || a.source === "stage" ? a.shot : void 0,
|
|
5719
|
+
crop: a.crop
|
|
5472
5720
|
});
|
|
5473
5721
|
if (!spec) {
|
|
5474
5722
|
if (a.channel !== "demo")
|
|
@@ -10149,4 +10397,4 @@ export {
|
|
|
10149
10397
|
convertAgentBrowser,
|
|
10150
10398
|
run
|
|
10151
10399
|
};
|
|
10152
|
-
//# sourceMappingURL=chunk-
|
|
10400
|
+
//# sourceMappingURL=chunk-PKHORUJ2.js.map
|