@vosjs/cli 0.10.1 → 0.11.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-CJPWZVHQ.js → chunk-3W3XD6HL.js} +118 -27
- package/dist/chunk-3W3XD6HL.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +1 -1
- package/dist/{run-4LSBJO7N.js → run-U3NAAIKH.js} +2 -2
- package/package.json +3 -3
- package/dist/chunk-CJPWZVHQ.js.map +0 -1
- /package/dist/{run-4LSBJO7N.js.map → run-U3NAAIKH.js.map} +0 -0
|
@@ -1609,30 +1609,107 @@ async function renderAnimation(browser, opts) {
|
|
|
1609
1609
|
}
|
|
1610
1610
|
}
|
|
1611
1611
|
|
|
1612
|
-
// src/plugin/
|
|
1612
|
+
// src/plugin/backdrops.ts
|
|
1613
|
+
async function fetchBackdropSet(origin) {
|
|
1614
|
+
const base = origin.replace(/\/+$/, "");
|
|
1615
|
+
const res = await fetch(`${base}/api/backdrops`);
|
|
1616
|
+
if (!res.ok)
|
|
1617
|
+
throw new Error(`GET ${base}/api/backdrops answered ${res.status}`);
|
|
1618
|
+
const body = await res.json();
|
|
1619
|
+
return Array.isArray(body.backdrops) ? body.backdrops : [];
|
|
1620
|
+
}
|
|
1621
|
+
function rowBackdrop(row) {
|
|
1622
|
+
const key = row.urls["1080p"];
|
|
1623
|
+
if (!key) return null;
|
|
1624
|
+
return {
|
|
1625
|
+
slug: row.slug,
|
|
1626
|
+
key,
|
|
1627
|
+
kind: "video",
|
|
1628
|
+
duration: row.duration,
|
|
1629
|
+
...row.urls.poster ? { poster: row.urls.poster } : {},
|
|
1630
|
+
...row.ground ? { ground: row.ground } : {}
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
function houseBackdrop(rows) {
|
|
1634
|
+
for (const row of rows) {
|
|
1635
|
+
const b = rowBackdrop(row);
|
|
1636
|
+
if (b) return b;
|
|
1637
|
+
}
|
|
1638
|
+
return null;
|
|
1639
|
+
}
|
|
1640
|
+
function backdropBySlug(rows, slug) {
|
|
1641
|
+
const row = rows.find((r) => r.slug === slug);
|
|
1642
|
+
return row ? rowBackdrop(row) : null;
|
|
1643
|
+
}
|
|
1613
1644
|
function isBackdropSlug(value) {
|
|
1614
1645
|
return /^[a-z0-9][a-z0-9-]{0,49}$/.test(value) && value !== "none";
|
|
1615
1646
|
}
|
|
1647
|
+
var VIDEO_EXT = /\.(webm|mp4|mov|m4v)(\?|#|$)/i;
|
|
1648
|
+
var IMAGE_EXT = /\.(jpe?g|png|webp|gif|avif)(\?|#|$)/i;
|
|
1649
|
+
function inferBackgroundKind(url) {
|
|
1650
|
+
if (IMAGE_EXT.test(url)) return "image";
|
|
1651
|
+
if (VIDEO_EXT.test(url)) return "video";
|
|
1652
|
+
return "video";
|
|
1653
|
+
}
|
|
1654
|
+
var BACKGROUND_DEFAULT_DURATION = 10;
|
|
1655
|
+
function backdropFromKey(key, duration) {
|
|
1656
|
+
const kind = inferBackgroundKind(key);
|
|
1657
|
+
return kind === "video" ? { key, kind, duration: duration ?? BACKGROUND_DEFAULT_DURATION } : { key, kind };
|
|
1658
|
+
}
|
|
1659
|
+
async function openingBackdrop(background, origin) {
|
|
1660
|
+
if (background === "none" || background === "") return { backdrop: null };
|
|
1661
|
+
if (background !== void 0 && !isBackdropSlug(background)) {
|
|
1662
|
+
return { backdrop: backdropFromKey(background) };
|
|
1663
|
+
}
|
|
1664
|
+
let rows;
|
|
1665
|
+
try {
|
|
1666
|
+
rows = await fetchBackdropSet(origin);
|
|
1667
|
+
} catch (err) {
|
|
1668
|
+
if (background !== void 0) {
|
|
1669
|
+
throw new UsageError(
|
|
1670
|
+
`--background "${background}" \u2014 could not read the backdrop set from ${origin}/api/backdrops (${err.message}); pass a URL instead`
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
return {
|
|
1674
|
+
backdrop: null,
|
|
1675
|
+
note: `could not read the backdrop set from ${origin}/api/backdrops; the take opens on a flat ground (--background <slug|url> picks one later)`
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
if (background !== void 0) {
|
|
1679
|
+
const hit = backdropBySlug(rows, background);
|
|
1680
|
+
if (!hit) {
|
|
1681
|
+
throw new UsageError(
|
|
1682
|
+
`--background "${background}" is not in the set (${rows.map((b) => b.slug).join(" | ") || "empty"}); GET ${origin}/api/backdrops lists it, or pass a URL`
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
return { backdrop: hit };
|
|
1686
|
+
}
|
|
1687
|
+
const house = houseBackdrop(rows);
|
|
1688
|
+
return house ? { backdrop: house } : {
|
|
1689
|
+
backdrop: null,
|
|
1690
|
+
note: `the backdrop set at ${origin}/api/backdrops has no ready loop; the take opens on a flat ground`
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// src/plugin/docOverride.ts
|
|
1616
1695
|
async function resolveBackdropSlug(o) {
|
|
1617
1696
|
if (!o.background || !isBackdropSlug(o.background)) return;
|
|
1618
1697
|
const origin = (o.origin ?? "https://vos.so").replace(/\/+$/, "");
|
|
1619
|
-
let list
|
|
1698
|
+
let list;
|
|
1620
1699
|
try {
|
|
1621
|
-
|
|
1622
|
-
if (res.ok)
|
|
1623
|
-
list = (await res.json()).backdrops;
|
|
1700
|
+
list = await fetchBackdropSet(origin);
|
|
1624
1701
|
} catch {
|
|
1625
1702
|
throw new UsageError(
|
|
1626
1703
|
`--background "${o.background}" \u2014 could not read the backdrop set from ${origin}/api/backdrops; pass a URL instead`
|
|
1627
1704
|
);
|
|
1628
1705
|
}
|
|
1629
|
-
const hit = list
|
|
1630
|
-
if (!hit
|
|
1706
|
+
const hit = backdropBySlug(list, o.background);
|
|
1707
|
+
if (!hit) {
|
|
1631
1708
|
throw new UsageError(
|
|
1632
1709
|
`--background "${o.background}" is not in the set (${list.map((b) => b.slug).join(" | ") || "empty"}); GET ${origin}/api/backdrops lists it, or pass a URL`
|
|
1633
1710
|
);
|
|
1634
1711
|
}
|
|
1635
|
-
o.background = hit.
|
|
1712
|
+
o.background = hit.key;
|
|
1636
1713
|
o.backgroundDuration = hit.duration;
|
|
1637
1714
|
}
|
|
1638
1715
|
function hasOverrides(o) {
|
|
@@ -1650,9 +1727,6 @@ var FRAME_KINDS = {
|
|
|
1650
1727
|
none: "none",
|
|
1651
1728
|
hidden: "none"
|
|
1652
1729
|
};
|
|
1653
|
-
var BACKGROUND_DEFAULT_DURATION = 10;
|
|
1654
|
-
var VIDEO_EXT = /\.(webm|mp4|mov|m4v)(\?|#|$)/i;
|
|
1655
|
-
var IMAGE_EXT = /\.(jpe?g|png|webp|gif|avif)(\?|#|$)/i;
|
|
1656
1730
|
function coerceValue(raw) {
|
|
1657
1731
|
try {
|
|
1658
1732
|
return JSON.parse(raw);
|
|
@@ -1712,11 +1786,6 @@ function setPath(root, path, value) {
|
|
|
1712
1786
|
;
|
|
1713
1787
|
node[segs[segs.length - 1].key] = value;
|
|
1714
1788
|
}
|
|
1715
|
-
function inferBackgroundKind(url) {
|
|
1716
|
-
if (IMAGE_EXT.test(url)) return "image";
|
|
1717
|
-
if (VIDEO_EXT.test(url)) return "video";
|
|
1718
|
-
return "video";
|
|
1719
|
-
}
|
|
1720
1789
|
function applyDocOverrides(doc, o) {
|
|
1721
1790
|
const applied = [];
|
|
1722
1791
|
const d = doc;
|
|
@@ -3673,12 +3742,14 @@ import { existsSync as existsSync6 } from "fs";
|
|
|
3673
3742
|
import { readFile as readFile6 } from "fs/promises";
|
|
3674
3743
|
import { join as join9 } from "path";
|
|
3675
3744
|
import {
|
|
3745
|
+
DEFAULT_FRAME_STYLE,
|
|
3676
3746
|
STYLE_FIELDS,
|
|
3677
3747
|
copyStyle,
|
|
3678
3748
|
isRejected,
|
|
3679
3749
|
planAutoSpeed,
|
|
3680
3750
|
planAutoZoom,
|
|
3681
|
-
projectFromArtifact
|
|
3751
|
+
projectFromArtifact,
|
|
3752
|
+
withBackdrop
|
|
3682
3753
|
} from "@vosjs/studio-core";
|
|
3683
3754
|
|
|
3684
3755
|
// src/plugin/reuse.ts
|
|
@@ -3875,6 +3946,7 @@ async function planTake(dir, opts = {}) {
|
|
|
3875
3946
|
const take = await loadTake(dir);
|
|
3876
3947
|
const { meta, cursor } = take;
|
|
3877
3948
|
const activity = await readDigestActivity(dir);
|
|
3949
|
+
const ingest = opts.backdrop ? { frame: withBackdrop(DEFAULT_FRAME_STYLE, opts.backdrop) } : {};
|
|
3878
3950
|
let doc;
|
|
3879
3951
|
let fresh;
|
|
3880
3952
|
if (opts.reuse) {
|
|
@@ -3884,7 +3956,7 @@ async function planTake(dir, opts = {}) {
|
|
|
3884
3956
|
cursor,
|
|
3885
3957
|
meta
|
|
3886
3958
|
};
|
|
3887
|
-
doc = projectFromArtifact(artifact, RECORDING_NAME).doc;
|
|
3959
|
+
doc = projectFromArtifact(artifact, RECORDING_NAME, ingest).doc;
|
|
3888
3960
|
doc = copyStyle(prev, doc);
|
|
3889
3961
|
const rt = retimeCut(prev, meta.steps ?? [], meta.durationMs);
|
|
3890
3962
|
doc.segments = rt.segments;
|
|
@@ -3943,7 +4015,7 @@ async function planTake(dir, opts = {}) {
|
|
|
3943
4015
|
cursor,
|
|
3944
4016
|
meta
|
|
3945
4017
|
};
|
|
3946
|
-
doc = projectFromArtifact(artifact, RECORDING_NAME).doc;
|
|
4018
|
+
doc = projectFromArtifact(artifact, RECORDING_NAME, ingest).doc;
|
|
3947
4019
|
if (opts.style) doc = copyStyle(opts.style.doc, doc);
|
|
3948
4020
|
doc.zoom = planAutoZoom(doc.source.cursor, {
|
|
3949
4021
|
width: doc.source.meta.width,
|
|
@@ -3965,6 +4037,7 @@ async function planTake(dir, opts = {}) {
|
|
|
3965
4037
|
zoomManual: doc.zoom.filter((z) => z.source === "manual").length,
|
|
3966
4038
|
cursorKept: doc.source.cursor.length > 0,
|
|
3967
4039
|
fresh,
|
|
4040
|
+
...opts.backdrop ? { backdrop: doc.frame.backgroundMedia?.key ?? "none" } : {},
|
|
3968
4041
|
...opts.style ? {
|
|
3969
4042
|
styleFrom: opts.style.from,
|
|
3970
4043
|
styleFields: STYLE_FIELDS.filter(
|
|
@@ -6394,9 +6467,9 @@ var MULTI_FLAGS2 = /* @__PURE__ */ new Set(["set", "override"]);
|
|
|
6394
6467
|
var HELP = `vos \u2014 record a browser flow, plan effects, render a product video; sync with vos.so
|
|
6395
6468
|
|
|
6396
6469
|
Take pipeline
|
|
6397
|
-
vos create --actions actions.json [--url <url>] [--out take] [out.webm] [--strict] [--max-duration <s>] [render flags] [--json]
|
|
6398
|
-
vos record --actions actions.json [--url <url>] [--out take] [--strict] [--max-duration <s>] [--json]
|
|
6399
|
-
vos plan <take> [--fresh] [--reuse [--from <doc.json>]] [--style <doc.json|vosId>] [--json]
|
|
6470
|
+
vos create --actions actions.json [--url <url>] [--out take] [out.webm] [--strict] [--max-duration <s>] [--background <slug|url|none>] [render flags] [--json]
|
|
6471
|
+
vos record --actions actions.json [--url <url>] [--out take] [--strict] [--max-duration <s>] [--background <slug|url|none>] [--json]
|
|
6472
|
+
vos plan <take> [--fresh] [--reuse [--from <doc.json>]] [--style <doc.json|vosId>] [--background <slug|url|none>] [--json]
|
|
6400
6473
|
vos render <take> [out.webm] [--width] [--height] [--fps] [--format webm|mp4] [--parallel N] [--range a..b] [--draft] [--frame <kind>] [--background <url|slug>] [--set <path=value>]... [--json]
|
|
6401
6474
|
vos frames <take> [--times 0,25%,50%,75%,100%] [--frame <t>] [--at-zooms] [--at-moments] [--size WxH] [--out dir] [--background <url|slug>] [--set <path=value>]... [--json]
|
|
6402
6475
|
vos deliver <take> --to cws,producthunt,x,linkedin,og,github,youtube (or all) [--poster <config.json|vosId>] [--shot-time <t>] [--poster-time <t>] [--composed] [--set path=value] [--release v2.1] [--out dir] [--times a,b] [--range a..b] [--parallel N] [--json]
|
|
@@ -6563,7 +6636,9 @@ lint-gated, so a bad override fails like a bad doc.json):
|
|
|
6563
6636
|
--set frame.padding=120 --set frame.browserBar.kind=mac-light)
|
|
6564
6637
|
--frame <kind> (render) browser frame: macos|mac-dark|windows|windows-dark|minimal|none
|
|
6565
6638
|
--background <url|slug> background media: a URL (kind inferred), or a backdrop slug from GET /api/backdrops
|
|
6566
|
-
(.webm/.mp4 = video @10s loop, image otherwise); "none" clears
|
|
6639
|
+
(.webm/.mp4 = video @10s loop, image otherwise); "none" clears.
|
|
6640
|
+
On create/record/plan it is the frame a FRESH take opens on; absent, the set's
|
|
6641
|
+
first ready loop (the house backdrop the studio opens on), or a flat ground offline
|
|
6567
6642
|
`;
|
|
6568
6643
|
async function loadActions(file) {
|
|
6569
6644
|
const raw = JSON.parse(await readFile9(file, "utf8"));
|
|
@@ -6584,6 +6659,17 @@ function strictReason(rec) {
|
|
|
6584
6659
|
if (rec.capped) parts.push("stopped at --max-duration");
|
|
6585
6660
|
return parts.join(" + ");
|
|
6586
6661
|
}
|
|
6662
|
+
async function takeBackdrop(flags, r) {
|
|
6663
|
+
const { backdrop, note } = await openingBackdrop(
|
|
6664
|
+
strFlag(flags, "background"),
|
|
6665
|
+
platformOrigin({
|
|
6666
|
+
origin: strFlag(flags, "origin"),
|
|
6667
|
+
api: strFlag(flags, "api")
|
|
6668
|
+
})
|
|
6669
|
+
);
|
|
6670
|
+
if (note) r.log(`note: ${note}`);
|
|
6671
|
+
return backdrop;
|
|
6672
|
+
}
|
|
6587
6673
|
async function cmdRecord(argv) {
|
|
6588
6674
|
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS5);
|
|
6589
6675
|
const actionsPath = strFlag(flags, "actions") ?? positionals[0];
|
|
@@ -6597,6 +6683,7 @@ async function cmdRecord(argv) {
|
|
|
6597
6683
|
if (!url)
|
|
6598
6684
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
6599
6685
|
const outDir = resolve6(strFlag(flags, "out") ?? "take");
|
|
6686
|
+
const backdrop = await takeBackdrop(flags, r);
|
|
6600
6687
|
if (existsSync10(join14(outDir, "meta.json"))) {
|
|
6601
6688
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
6602
6689
|
r.log(
|
|
@@ -6620,7 +6707,7 @@ async function cmdRecord(argv) {
|
|
|
6620
6707
|
(p) => r.event({ event: "progress", phase: "encode", fraction: p })
|
|
6621
6708
|
);
|
|
6622
6709
|
r.event({ event: "phase", phase: "plan" });
|
|
6623
|
-
const plan = await planTake(outDir);
|
|
6710
|
+
const plan = await planTake(outDir, { backdrop });
|
|
6624
6711
|
const clicks = rec.events.filter((e) => e.type === "down").length;
|
|
6625
6712
|
const strict = flags.strict === true;
|
|
6626
6713
|
const strictFail = strict && (rec.skipped.length > 0 || rec.navTimeout || rec.capped);
|
|
@@ -6678,6 +6765,7 @@ async function cmdCreate2(argv) {
|
|
|
6678
6765
|
if (!Number.isInteger(parallel) || parallel < 1 || parallel > 16) {
|
|
6679
6766
|
throw new UsageError("--parallel expects an integer between 1 and 16");
|
|
6680
6767
|
}
|
|
6768
|
+
const backdrop = await takeBackdrop(flags, r);
|
|
6681
6769
|
if (existsSync10(join14(outDir, "meta.json"))) {
|
|
6682
6770
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
6683
6771
|
r.log(
|
|
@@ -6701,7 +6789,7 @@ async function cmdCreate2(argv) {
|
|
|
6701
6789
|
(p) => r.event({ event: "progress", phase: "encode", fraction: p })
|
|
6702
6790
|
);
|
|
6703
6791
|
r.event({ event: "phase", phase: "plan" });
|
|
6704
|
-
await planTake(outDir);
|
|
6792
|
+
await planTake(outDir, { backdrop });
|
|
6705
6793
|
if (flags.strict === true && (rec.skipped.length > 0 || rec.navTimeout || rec.capped)) {
|
|
6706
6794
|
r.done(
|
|
6707
6795
|
{
|
|
@@ -6782,9 +6870,11 @@ async function cmdPlan(argv) {
|
|
|
6782
6870
|
};
|
|
6783
6871
|
}
|
|
6784
6872
|
const style = await resolveStyleRef(flags);
|
|
6873
|
+
const backdrop = existsSync10(join14(dir, "doc.json")) ? null : await takeBackdrop(flags, r);
|
|
6785
6874
|
const s = await planTake(dir, {
|
|
6786
6875
|
...style ? { style } : {},
|
|
6787
|
-
...reuse ? { reuse } : {}
|
|
6876
|
+
...reuse ? { reuse } : {},
|
|
6877
|
+
backdrop
|
|
6788
6878
|
});
|
|
6789
6879
|
const reuseLines = s.reuse ? `
|
|
6790
6880
|
reused ${s.reuse.from}: ${s.reuse.anchored} anchored + ${s.reuse.mapped} mapped span(s)` + (s.reuse.flagged.length ? `
|
|
@@ -6798,6 +6888,7 @@ async function cmdPlan(argv) {
|
|
|
6798
6888
|
zoomAuto: s.zoomAuto,
|
|
6799
6889
|
zoomManual: s.zoomManual,
|
|
6800
6890
|
duration: s.doc.source.meta.durationMs / 1e3,
|
|
6891
|
+
...s.backdrop !== void 0 ? { backdrop: s.backdrop } : {},
|
|
6801
6892
|
...s.styleFrom ? { styleFrom: s.styleFrom, styleFields: s.styleFields } : {},
|
|
6802
6893
|
...s.reuse ? { reuse: s.reuse } : {}
|
|
6803
6894
|
},
|
|
@@ -7474,4 +7565,4 @@ export {
|
|
|
7474
7565
|
convertAgentBrowser,
|
|
7475
7566
|
run
|
|
7476
7567
|
};
|
|
7477
|
-
//# sourceMappingURL=chunk-
|
|
7568
|
+
//# sourceMappingURL=chunk-3W3XD6HL.js.map
|