@vosjs/cli 0.24.0 → 0.25.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 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. 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.
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
 
@@ -186,16 +186,17 @@ import {
186
186
  CAM_SPAN_MIN,
187
187
  CARD_ENTER_KINDS,
188
188
  CARD_EXIT_KINDS,
189
- IDLE_KINDS,
190
- MEDIA_ENTER_KINDS,
191
- MEDIA_EXIT_KINDS,
192
- TEXT_ENTER_KINDS,
193
- TEXT_EXIT_KINDS,
194
189
  EXPORT_RESOLUTION_OPTIONS,
195
190
  FREEZE_SECONDS_MAX,
196
191
  FREEZE_SECONDS_MIN,
192
+ IDLE_KINDS,
193
+ MEDIA_ENTER_KINDS,
194
+ MEDIA_EXIT_KINDS,
195
+ MEDIA_FRAME_KEYS,
197
196
  SPEED_RATE_MAX,
198
197
  SPEED_RATE_MIN,
198
+ TEXT_ENTER_KINDS,
199
+ TEXT_EXIT_KINDS,
199
200
  TILT_DEG_MAX,
200
201
  TILT_SPAN_MIN,
201
202
  ZOOM_LEVEL_MAX,
@@ -366,6 +367,21 @@ function lintDoc(docIn) {
366
367
  if (!id) problems.push(`media[${i}]: id must be a string`);
367
368
  else if (mediaLen.has(id))
368
369
  problems.push(`media[${i}] (${id}): duplicate id`);
370
+ const mf = m.frame;
371
+ if (mf !== void 0) {
372
+ if (!isObj(mf)) {
373
+ problems.push(
374
+ `media[${i}]${id ? ` (${id})` : ""}: frame must be an object`
375
+ );
376
+ } else {
377
+ for (const k of Object.keys(mf)) {
378
+ if (!MEDIA_FRAME_KEYS.includes(k))
379
+ problems.push(
380
+ `media[${i}]${id ? ` (${id})` : ""}.frame.${k}: not a card field (a media's frame carries ${MEDIA_FRAME_KEYS.join(", ")}; the rest is the take's frame)`
381
+ );
382
+ }
383
+ }
384
+ }
369
385
  if (typeof m.videoKey !== "string")
370
386
  problems.push(
371
387
  `media[${i}]${id ? ` (${id})` : ""}: videoKey must be a string`
@@ -10343,4 +10359,4 @@ export {
10343
10359
  convertAgentBrowser,
10344
10360
  run
10345
10361
  };
10346
- //# sourceMappingURL=chunk-NOR522G5.js.map
10362
+ //# sourceMappingURL=chunk-TYTUA5L5.js.map