@vosjs/cli 0.26.0 → 0.27.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/README.md +1 -1
- package/dist/{chunk-I3UUIBSH.js → chunk-IJ5A4TL3.js} +35 -2
- package/dist/chunk-IJ5A4TL3.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-VSENMRFF.js → run-XR464TW5.js} +2 -2
- package/package.json +4 -4
- package/schema/doc.schema.json +39 -1
- package/dist/chunk-I3UUIBSH.js.map +0 -1
- /package/dist/{run-VSENMRFF.js.map → run-XR464TW5.js.map} +0 -0
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ vos plan take --reuse # re-time that cut onto
|
|
|
89
89
|
|
|
90
90
|
**Digest first.** `vos digest <take>` is how an agent sees a recording without reading the video. It writes `digest/digest.json`: one moment per thing the cursor track says mattered (click clusters, typing sessions, scroll runs, dwells, idle gaps, head, tail, and frame-diff scene changes), each with source and output extents, a normalized `focus` and `rect` you can copy into a zoom span, per-second `activity`, and the planners' `proposed` span ids; plus one footage frame and a crop around the target per moment, and `sheet.png`, the contact sheet. Read the JSON, then the sheet, then a crop only where you must decide. `vos validate` then warns when a zoom does not contain what was clicked under it, and `vos frames --at-moments` renders the composed output at every moment so a still and its footage crop share an id.
|
|
91
91
|
|
|
92
|
-
**Many media in one take (concat).** `doc.json` may carry `media: [{ id, videoKey, cursor, meta, … }]`, the take's OTHER recordings or uploads, each the `source` shape with an `id`; a segment on one (`{ in, out, media: "m1" }`) plays it, and a zoom, tilt, speed, freeze or cam-move span names the media its source seconds belong to (absent = the primary, `source`). The Video row shows the clips in order, a span is drawn where its media plays, `vos plan` proposes zoom and speed spans on every media from its own cursor track, `vos validate` measures each span against its own media's length, and `vos push` and `vos pull --media` carry every media through the recording door. A media wears its OWN card: `media[].frame` carries the card-owned fields (its placement and size as `inset`, the browser bar, the corner, the shadow, the border, the cover fit and its focus) over the take's frame while it plays; the bar names that media's recorded page, an upload with no page wears none, and the frame-wide fields (the aspect, the padding, the ground, the backdrop, the card's animation) stay the take's. Sound: the primary's tracks play at the primary's moments; another media's own audio is not spliced into the cut yet.
|
|
92
|
+
**Many media in one take (concat).** `doc.json` may carry `media: [{ id, videoKey, cursor, meta, … }]`, the take's OTHER recordings or uploads, each the `source` shape with an `id`; a segment on one (`{ in, out, media: "m1" }`) plays it, and a zoom, tilt, speed, freeze or cam-move span names the media its source seconds belong to (absent = the primary, `source`). The Video row shows the clips in order, a span is drawn where its media plays, `vos plan` proposes zoom and speed spans on every media from its own cursor track, `vos validate` measures each span against its own media's length, and `vos push` and `vos pull --media` carry every media through the recording door. A media wears its OWN card: `media[].frame` carries the card-owned fields (its placement and size as `inset`, the browser bar, the corner, the shadow, the border, the cover fit and its focus) over the take's frame while it plays; the bar names that media's recorded page, an upload with no page wears none, and the frame-wide fields (the aspect, the padding, the ground, the backdrop, the card's animation) stay the take's. Sound: the primary's tracks play at the primary's moments; another media's own audio is not spliced into the cut yet. **Many cards**: an image or video overlay may show a document media by reference (`key: "media:<id>"`, `media:` alone the primary; its cursor track and recorded page come with it) and wear a card (`frame`: `browserBar`, a `lean` `{rx, ry}` in degrees, `shadow`, `shadowContact`, `shadowColor`, `cursor`), drawn by the card painter on its own plane above the primary card with the media's cursor dot and click rings inside it; a layer without `frame` stays the flat picture. The primary card stays primary: the sequence, the camera and the cut are its.
|
|
93
93
|
|
|
94
94
|
**A series shares its look by data.** `vos plan <take> --style <seed doc.json | vosId>` copies the seed's `zoomStyle`, `zoomParams`, `speedParams`, `tiltStyle`, `frame`, `cursor`, `cam` and `export` onto a new take (never its spans, overlays or audio) and re-plans the automatic spans under them. A seed that is a POSTER carries its layout too: its card placement, its `stage-*` clips by id (with the release's words from LAUNCH.md's `headline` and `kicker` roles, BRAND.md's `wordmark`, or `--headline` and `--kicker` patched in; the brand's mark from BRAND.md `logoUrl` fetched into `<take>/brand/` for `stage-mark`), its rest lean, its trailing freeze. What could not follow is said in words.
|
|
95
95
|
|
|
@@ -988,6 +988,39 @@ function lintDoc(docIn) {
|
|
|
988
988
|
if (o.fx !== void 0) {
|
|
989
989
|
problems.push(`${name}.fx is text-only (media clips have enter/exit)`);
|
|
990
990
|
}
|
|
991
|
+
if (typeof o.key === "string" && o.key.startsWith("media:")) {
|
|
992
|
+
const ref = o.key.slice("media:".length);
|
|
993
|
+
const ids = new Set(
|
|
994
|
+
(Array.isArray(doc.media) ? doc.media : []).map((m) => typeof m.id === "string" ? m.id : "")
|
|
995
|
+
);
|
|
996
|
+
if (ref !== "" && !ids.has(ref))
|
|
997
|
+
problems.push(
|
|
998
|
+
`${name}.key names media "${ref}", which is not one of media[].id (media: alone is the primary)`
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
const lcf = o.frame;
|
|
1002
|
+
if (lcf !== void 0) {
|
|
1003
|
+
if (!isObj(lcf)) {
|
|
1004
|
+
problems.push(`${name}.frame must be an object (the layer's card)`);
|
|
1005
|
+
} else {
|
|
1006
|
+
const LCF = [
|
|
1007
|
+
"browserBar",
|
|
1008
|
+
"lean",
|
|
1009
|
+
"shadow",
|
|
1010
|
+
"shadowContact",
|
|
1011
|
+
"shadowColor",
|
|
1012
|
+
"cursor"
|
|
1013
|
+
];
|
|
1014
|
+
for (const k of Object.keys(lcf))
|
|
1015
|
+
if (!LCF.includes(k))
|
|
1016
|
+
problems.push(
|
|
1017
|
+
`${name}.frame.${k}: not a layer card field (${LCF.join(", ")})`
|
|
1018
|
+
);
|
|
1019
|
+
const lean = lcf.lean;
|
|
1020
|
+
if (lean !== void 0 && (!isObj(lean) || !isNum(lean.rx) || !isNum(lean.ry)))
|
|
1021
|
+
problems.push(`${name}.frame.lean must be { rx, ry } in degrees`);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
991
1024
|
if (typeof o.key !== "string" || o.key.length === 0) {
|
|
992
1025
|
problems.push(
|
|
993
1026
|
`${name}.key must be a non-empty media URL or take-dir file (e.g. "/logo.png")`
|
|
@@ -6381,7 +6414,7 @@ var KEYS = [
|
|
|
6381
6414
|
{ key: "camKey", file: CAM_NAME }
|
|
6382
6415
|
];
|
|
6383
6416
|
function isTakeRelativeKey(key) {
|
|
6384
|
-
return !!key && !/^(https?:|blob:|data:|\/\/)/.test(key) && !key.startsWith("/api/");
|
|
6417
|
+
return !!key && !/^(https?:|blob:|data:|media:|\/\/)/.test(key) && !key.startsWith("/api/");
|
|
6385
6418
|
}
|
|
6386
6419
|
var takeRelativeFile = (key) => key.replace(/^\/+/, "");
|
|
6387
6420
|
function docMediaRefs(doc, keep = isTakeRelativeKey) {
|
|
@@ -10388,4 +10421,4 @@ export {
|
|
|
10388
10421
|
convertAgentBrowser,
|
|
10389
10422
|
run
|
|
10390
10423
|
};
|
|
10391
|
-
//# sourceMappingURL=chunk-
|
|
10424
|
+
//# sourceMappingURL=chunk-IJ5A4TL3.js.map
|