@vosjs/cli 0.70.0 → 0.72.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 +6 -4
- package/dist/{chunk-KIFXVPBR.js → chunk-R4S6V4AC.js} +107 -17
- package/dist/chunk-R4S6V4AC.js.map +1 -0
- package/dist/cli.js +5 -15
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -1
- package/dist/{run-7QR3CQSF.js → run-5FF6WPOQ.js} +2 -2
- package/dist/{shotList-KH6FTX4L.js → shotList-MAQVLZBY.js} +4 -2
- package/dist/shotList-MAQVLZBY.js.map +1 -0
- package/package.json +6 -6
- package/schema/actions.schema.json +111 -4
- package/dist/chunk-KIFXVPBR.js.map +0 -1
- package/dist/shotList-KH6FTX4L.js.map +0 -1
- /package/dist/{run-7QR3CQSF.js.map → run-5FF6WPOQ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ npx vos render animation.json out.webm
|
|
|
15
15
|
|
|
16
16
|
Deterministic: the preview is the render, and every edit is a data patch to `doc.json`, never a re-record. Rendering is local and free at every resolution up to 4K, no watermark. The workflow skills for agents install with `npx skills add vosjs/skills` (`product-video` records and cuts one video, `vos-cut` cuts an existing recording, `launch-kit` ships the media with a release); `vos setup` runs that for you, and falls back to the copy of the catalog this package ships when skills.sh cannot be reached. A coding agent gets the whole procedure from one line: `Read https://vos.so/agent.md and do what it says.`
|
|
17
17
|
|
|
18
|
-
Until 0.9 the take pipeline and the vos.so verbs shipped separately as `@vosso/vos-plugin`, and before that as `@vosso/cli
|
|
18
|
+
Until 0.9 the take pipeline and the vos.so verbs shipped separately as `@vosso/vos-plugin`, and before that as `@vosso/cli`; those names are deprecated on npm and forward here.
|
|
19
19
|
|
|
20
20
|
## Contents
|
|
21
21
|
|
|
@@ -173,7 +173,9 @@ A session never enters a take directory and never reaches vos.so: `vos push` ref
|
|
|
173
173
|
|
|
174
174
|
**Rehearse before you record.** `vos record … --dry-run` runs every step against the real page, in order, because a later selector usually exists only after an earlier click. Nothing is captured and nothing is written: the pointer lands instead of travelling, every pause is cut to a beat, and the take directory beside it keeps its footage, its cut and its script exactly as they were (a real re-record moves `doc.json` aside; a rehearsal does not). Selector lookups keep their whole timeout, so a miss here is a miss in the take. It prints each step with the rect it resolved, in capture px, which are the rects a pin or `vos callout --step` reads, and exits 2 on any miss or a first load that never settled. Add `--dry-run` to the exact command you were about to run; `--storage-state` and `--browser-arg=` apply to it too, and the `Next:` line it prints carries them, so the command it hands you records what it rehearsed.
|
|
175
175
|
|
|
176
|
-
**
|
|
176
|
+
**The planners read the flow's own structure.** On a scripted take the step timeline is a planner input: a `wait` step between the first and the last doing step, or a hover's dwell, in which the digest's activity measured nothing moving is proposed at 2× (`speedParams.stillRate`; the opening and closing waits are the clip's establishing and resting beats and stay at 1×), the presses inside one step (a click and the dialog it opened, a drag's presses) are one zoom while their targets share a window, and a park before the first step (the cursor arriving on the logo) is never a dwell. Manual and rejected spans stay as they are.
|
|
177
|
+
|
|
178
|
+
**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), and after every click and typing run a `changed` moment, the region of the page that answered it (a dialog opening, a 200 landing, a panel re-laying out, a card going dark), with `seed` naming the moment it answers, its `rect` the changed region and its `focus` the centre, so a cut can hold on the consequence and a zoom can frame it, 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; `steps`, every script step with its source and output windows, the page it left and the words its `read` kept, so a layer is placed by the table and quotes the take; 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.
|
|
177
179
|
|
|
178
180
|
**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.
|
|
179
181
|
|
|
@@ -251,7 +253,7 @@ A re-record replaces the footage, the cursor track, the frames and everything de
|
|
|
251
253
|
}
|
|
252
254
|
```
|
|
253
255
|
|
|
254
|
-
|
|
256
|
+
Eight verbs: `wait`, `hover` (`ms` 700, the dwell), `click` (`ms` the settle after the press, 150), `type` (`delayMs` 40 per key, paced by the clock; `focus: false` skips the focusing click; `replace: true` selects the field's value first so the typing replaces it; `at: "end" | "start"` puts the caret there before the first character, for a code editor line; `ms` the settle after, 150), `press` (one named key, `Escape`, `Enter`, `Tab`, `Backspace`, `Delete`, the arrows, `Home`, `End`, `PageUp`, `PageDown`, `Space`, recorded as a typing ping where the pointer is or on `selector` with no click, so an Escape closes what a click opened and an Enter submits what was typed without a second click ringing on the field; `ms` the settle, 150), `scroll` (`ms` the settle, 200), `move`, `drag` (press, move, release: a range input, a canvas element, a timeline clip; `ms` the travel, 700). The recorder's pace is the script's: a gesture is driven by the clock, so a page that answers each pointer sample slowly costs samples, never seconds, and the only pauses are the ones the script names (`wait`, a hover's dwell, a settle). `vos record` ends with a pace line, what the script asked, what the gestures added, what the page cost, and the steps that ran slow, and the `--json` done event carries it as `pace`. Every step takes an optional unique `id`; give steps ids so a span anchored to a step survives script edits and `vos plan --reuse` can follow it, and so a layer can name the element a step touched (`overlays[].pin.step`; the recorder keeps each hover, click, type and drag step's element rect on `meta.steps[].rect`). **The take carries its payload**: every step keeps the page it left (`meta.steps[].url`, origin and path), and a step with `read: "<selector>"` keeps that element's words once the step has settled (`meta.steps[].text`, at most 2 KB; on a click, what the click opened: the URL a share button minted, the code a dialog printed), so a layer quotes the take instead of a replay of the flow. Because the CLI issues every input itself, the cursor track is synthesized with exact coordinates, exact timing and fresh element rects, which is what powers element-aware auto-zoom and click effects downstream. The schema is [`schema/actions.schema.json`](./schema/actions.schema.json); `vos validate actions.json` checks a script without running anything.
|
|
255
257
|
|
|
256
258
|
Verified the flow in agent-browser already? `vos actions from-agent-browser steps.jsonl [--out actions.json] [--url] [--viewport WxH]` writes the script from that walk (each command kept beside its `--json` result, the batch record shape; refs resolve through the last `snapshot -i`), and names every step the recorder cannot follow rather than dropping it.
|
|
257
259
|
|
|
@@ -367,7 +369,7 @@ vos push /tmp/take --label "$TAG launch" --yes --json # VOS_API_KEY as a r
|
|
|
367
369
|
- **`--max-duration <s>`** on `record` and `create` defaults to the hosted recording cap, read live from `GET /api/limits` (2 s, fail-open to 30 min when the origin is unreachable): the capture stops there and the done event says so. Cut the flow rather than raising the cap; the platform refuses a longer take.
|
|
368
370
|
- **`create`** is the one-shot verb: record, auto-plan and render in one command and one browser session. The take directory still lands on disk, so the full loop (frames, edit `doc.json`, re-render) stays open afterwards.
|
|
369
371
|
- **`vos validate <thing>`** takes an `actions.json`, a take directory, a program directory (`config.json`, plus its program document when present), or a `kit.json`; exit 1 on any problem.
|
|
370
|
-
- **Environment.** `VOS_ORIGIN` (the platform, and the studio `vos open` opens), `VOS_API_KEY`, `VOS_BROWSER_PATH`, `VOS_CLIENT` (the client string a push self-reports; unset, a push names the coding agent that spawned the CLI, read from its environment the way `@vercel/detect-agent` reads it, e.g. `claude-code vos-cli`, else `vos-cli`).
|
|
372
|
+
- **Environment.** `VOS_ORIGIN` (the platform, and the studio `vos open` opens), `VOS_API_KEY`, `VOS_BROWSER_PATH`, `VOS_CLIENT` (the client string a push self-reports; unset, a push names the coding agent that spawned the CLI, read from its environment the way `@vercel/detect-agent` reads it, e.g. `claude-code vos-cli`, else `vos-cli`).
|
|
371
373
|
|
|
372
374
|
## Programmatic use
|
|
373
375
|
|
|
@@ -2400,7 +2400,7 @@ async function renderChunk(context2, serverBase, chunk, opts, onChunkProgress) {
|
|
|
2400
2400
|
bitrate: opts.bitrate ?? 1e7,
|
|
2401
2401
|
mediabunnyUrl: MEDIABUNNY_URL,
|
|
2402
2402
|
outName,
|
|
2403
|
-
debug: process.env.
|
|
2403
|
+
debug: process.env.VOS_DEBUG_CHUNKS === "1",
|
|
2404
2404
|
audioProducerCode: audio?.producerCode,
|
|
2405
2405
|
audioDataJson: audio ? JSON.stringify(audio.data) : void 0,
|
|
2406
2406
|
audioDuration: audio?.duration
|
|
@@ -2710,15 +2710,21 @@ import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "f
|
|
|
2710
2710
|
import { existsSync as existsSync2 } from "fs";
|
|
2711
2711
|
import { join as join2, resolve } from "path";
|
|
2712
2712
|
import {
|
|
2713
|
+
CHANGE_GRID,
|
|
2714
|
+
CHANGE_LEAD,
|
|
2715
|
+
CHANGE_OFFSETS,
|
|
2713
2716
|
DIGEST_CROP_MAX,
|
|
2714
2717
|
DIGEST_FULL_MAX,
|
|
2715
2718
|
DIGEST_VERSION,
|
|
2716
2719
|
MOTION_DELTA,
|
|
2720
|
+
ambientDrift,
|
|
2717
2721
|
buildDigest,
|
|
2722
|
+
changedRegion,
|
|
2718
2723
|
cropBox,
|
|
2719
2724
|
frameGeometry,
|
|
2720
2725
|
momentsFromDoc,
|
|
2721
2726
|
outputDurationOf,
|
|
2727
|
+
pickChange,
|
|
2722
2728
|
planForDigest,
|
|
2723
2729
|
sceneChanges
|
|
2724
2730
|
} from "@vosjs/studio-core";
|
|
@@ -2762,7 +2768,40 @@ async function binsInPage(opts) {
|
|
|
2762
2768
|
prev = luma;
|
|
2763
2769
|
w.__progress = (i + 1) / n;
|
|
2764
2770
|
}
|
|
2765
|
-
|
|
2771
|
+
const g = document.createElement("canvas");
|
|
2772
|
+
g.width = opts.grid.w;
|
|
2773
|
+
g.height = opts.grid.h;
|
|
2774
|
+
const gctx = g.getContext("2d", { willReadFrequently: true });
|
|
2775
|
+
const gridAt = async (t) => {
|
|
2776
|
+
const el = await getFrame(Math.max(0, Math.min(opts.durationS, t)));
|
|
2777
|
+
gctx.drawImage(el, 0, 0, opts.grid.w, opts.grid.h);
|
|
2778
|
+
const d = gctx.getImageData(0, 0, opts.grid.w, opts.grid.h).data;
|
|
2779
|
+
const out = new Array(opts.grid.w * opts.grid.h);
|
|
2780
|
+
for (let p = 0; p < out.length; p++) {
|
|
2781
|
+
const o = p * 4;
|
|
2782
|
+
out[p] = (d[o] * 299 + d[o + 1] * 587 + d[o + 2] * 114) / 1e3;
|
|
2783
|
+
}
|
|
2784
|
+
return out;
|
|
2785
|
+
};
|
|
2786
|
+
const changes = [];
|
|
2787
|
+
for (const seed of opts.seeds) {
|
|
2788
|
+
const samples = [];
|
|
2789
|
+
if (seed.t - opts.lead >= 0)
|
|
2790
|
+
samples.push({ dt: -opts.lead, luma: await gridAt(seed.t - opts.lead) });
|
|
2791
|
+
samples.push({ dt: 0, luma: await gridAt(seed.t) });
|
|
2792
|
+
for (const dt of opts.offsets) {
|
|
2793
|
+
if (seed.t + dt > opts.durationS) break;
|
|
2794
|
+
samples.push({ dt, luma: await gridAt(seed.t + dt) });
|
|
2795
|
+
}
|
|
2796
|
+
changes.push({ id: seed.id, samples });
|
|
2797
|
+
}
|
|
2798
|
+
w.__done = {
|
|
2799
|
+
ok: true,
|
|
2800
|
+
bins,
|
|
2801
|
+
width: size.width,
|
|
2802
|
+
height: size.height,
|
|
2803
|
+
changes
|
|
2804
|
+
};
|
|
2766
2805
|
} catch (e) {
|
|
2767
2806
|
w.__error = String(e instanceof Error && e.stack || e);
|
|
2768
2807
|
}
|
|
@@ -2985,23 +3024,66 @@ async function digestTake(browser, dir, opts = {}) {
|
|
|
2985
3024
|
});
|
|
2986
3025
|
await page.goto(`${server.base}/digest.html`);
|
|
2987
3026
|
await page.waitForFunction("window.__pageReady__ === true");
|
|
2988
|
-
|
|
3027
|
+
const seeds = momentsFromDoc(doc, plan, {}).filter(
|
|
3028
|
+
(m) => m.at !== null && (m.kind === "click" || m.kind === "typing")
|
|
3029
|
+
).map((m) => ({
|
|
3030
|
+
id: m.id,
|
|
3031
|
+
t: m.kind === "click" ? m.at : m.source.out
|
|
3032
|
+
}));
|
|
3033
|
+
void page.evaluate(binsInPage, {
|
|
3034
|
+
source,
|
|
3035
|
+
durationS: durS,
|
|
3036
|
+
delta: MOTION_DELTA,
|
|
3037
|
+
seeds,
|
|
3038
|
+
grid: { ...CHANGE_GRID },
|
|
3039
|
+
offsets: [...CHANGE_OFFSETS],
|
|
3040
|
+
lead: CHANGE_LEAD
|
|
3041
|
+
}).catch(() => {
|
|
2989
3042
|
});
|
|
2990
3043
|
const b = await waitForPageDone(
|
|
2991
3044
|
page,
|
|
2992
3045
|
"digest bins",
|
|
2993
3046
|
() => {
|
|
2994
3047
|
},
|
|
2995
|
-
6e4 + durS * 400
|
|
3048
|
+
6e4 + durS * 400 + seeds.length * 2e3
|
|
2996
3049
|
);
|
|
2997
3050
|
bins = b.bins;
|
|
2998
3051
|
plan = planForDigest(doc, bins);
|
|
2999
3052
|
frameW = b.width;
|
|
3000
3053
|
frameH = b.height;
|
|
3054
|
+
const sampled = b.changes ?? [];
|
|
3055
|
+
const changes = seeds.flatMap((seed) => {
|
|
3056
|
+
const row = sampled.find((c) => c.id === seed.id);
|
|
3057
|
+
const at2 = row?.samples.find((smp) => smp.dt === 0);
|
|
3058
|
+
const earlier = row?.samples.find((smp) => smp.dt < 0);
|
|
3059
|
+
const after = row?.samples.filter((smp) => smp.dt > 0) ?? [];
|
|
3060
|
+
if (!row || !at2 || !after.length) return [];
|
|
3061
|
+
const before = { ...CHANGE_GRID, luma: at2.luma };
|
|
3062
|
+
const rate = earlier ? ambientDrift(
|
|
3063
|
+
{ ...CHANGE_GRID, luma: earlier.luma },
|
|
3064
|
+
before,
|
|
3065
|
+
-earlier.dt
|
|
3066
|
+
) : null;
|
|
3067
|
+
const w = pickChange(
|
|
3068
|
+
{ id: seed.id, at: seed.t },
|
|
3069
|
+
after.map((smp) => ({
|
|
3070
|
+
dt: smp.dt,
|
|
3071
|
+
region: changedRegion(
|
|
3072
|
+
before,
|
|
3073
|
+
{ ...CHANGE_GRID, luma: smp.luma },
|
|
3074
|
+
MOTION_DELTA,
|
|
3075
|
+
1,
|
|
3076
|
+
rate ? { rate, dt: smp.dt } : null
|
|
3077
|
+
)
|
|
3078
|
+
}))
|
|
3079
|
+
);
|
|
3080
|
+
return w ? [w] : [];
|
|
3081
|
+
});
|
|
3001
3082
|
moments = momentsFromDoc(doc, plan, {
|
|
3002
3083
|
bins,
|
|
3003
3084
|
scenes: sceneChanges(bins),
|
|
3004
|
-
transcript
|
|
3085
|
+
transcript,
|
|
3086
|
+
changes
|
|
3005
3087
|
});
|
|
3006
3088
|
const geo = frameGeometry(doc, frameW, frameH);
|
|
3007
3089
|
const shots = moments.filter((m) => m.at !== null).map((m) => {
|
|
@@ -3144,7 +3226,7 @@ function parseTranscript(raw) {
|
|
|
3144
3226
|
}
|
|
3145
3227
|
|
|
3146
3228
|
// src/plugin/framesTake.ts
|
|
3147
|
-
var VIDEO_TOKEN = "
|
|
3229
|
+
var VIDEO_TOKEN = "__VOS_CLI_VIDEO__";
|
|
3148
3230
|
function stillSupersample(w, h) {
|
|
3149
3231
|
return Math.min(3, Math.max(1, Math.ceil(1800 / Math.max(1, w, h))));
|
|
3150
3232
|
}
|
|
@@ -3430,7 +3512,7 @@ import {
|
|
|
3430
3512
|
resolveExportSize as resolveExportSize2,
|
|
3431
3513
|
studioAudioPlan
|
|
3432
3514
|
} from "@vosjs/studio-core";
|
|
3433
|
-
var VIDEO_TOKEN2 = "
|
|
3515
|
+
var VIDEO_TOKEN2 = "__VOS_CLI_VIDEO__";
|
|
3434
3516
|
async function renderTake(browser, dir, outFile, opts) {
|
|
3435
3517
|
const take = await loadTake(dir);
|
|
3436
3518
|
if (!take.doc) throw new Error(`${dir} has no doc.json \u2014 run plan first`);
|
|
@@ -5699,7 +5781,8 @@ function planOtherMedia(doc, activity) {
|
|
|
5699
5781
|
height: m.meta.height,
|
|
5700
5782
|
duration: m.meta.durationMs / 1e3,
|
|
5701
5783
|
style: doc.zoomStyle,
|
|
5702
|
-
params: doc.zoomParams
|
|
5784
|
+
params: doc.zoomParams,
|
|
5785
|
+
steps: m.meta.steps
|
|
5703
5786
|
}).filter((z) => !manualZoom.some((x) => overlaps(z, x))).filter((z) => !isRejected("zoom", z, rejected)).map((z) => ({ ...z, id: `${z.id}-${m.id}`, media: m.id }))
|
|
5704
5787
|
);
|
|
5705
5788
|
const manualSpeed = (doc.speed ?? []).filter(
|
|
@@ -5709,7 +5792,8 @@ function planOtherMedia(doc, activity) {
|
|
|
5709
5792
|
...planAutoSpeed(m.cursor, {
|
|
5710
5793
|
durationMs: m.meta.durationMs,
|
|
5711
5794
|
params: doc.speedParams,
|
|
5712
|
-
activity
|
|
5795
|
+
activity,
|
|
5796
|
+
steps: m.meta.steps
|
|
5713
5797
|
}).filter((x) => !manualSpeed.some((y) => x.in < y.out && x.out > y.in)).filter((x) => !isRejected("speed", x, rejected)).map((x) => ({ ...x, id: `${x.id}-${m.id}`, media: m.id }))
|
|
5714
5798
|
);
|
|
5715
5799
|
}
|
|
@@ -5742,14 +5826,16 @@ async function planTake(dir, opts = {}) {
|
|
|
5742
5826
|
height: doc.source.meta.height,
|
|
5743
5827
|
duration: doc.source.meta.durationMs / 1e3,
|
|
5744
5828
|
style: doc.zoomStyle,
|
|
5745
|
-
params: doc.zoomParams
|
|
5829
|
+
params: doc.zoomParams,
|
|
5830
|
+
steps: doc.source.meta.steps
|
|
5746
5831
|
}).filter((z) => !manualZoom.some((m) => overlaps(z, m))).filter((z) => !isRejected("zoom", z, doc.rejected));
|
|
5747
5832
|
doc.zoom = [...manualZoom, ...autoZoom].sort((a, b) => a.in - b.in);
|
|
5748
5833
|
const manualSpeed = rt.speed;
|
|
5749
5834
|
const autoSpeed = planAutoSpeed(doc.source.cursor, {
|
|
5750
5835
|
durationMs: doc.source.meta.durationMs,
|
|
5751
5836
|
params: doc.speedParams,
|
|
5752
|
-
activity
|
|
5837
|
+
activity,
|
|
5838
|
+
steps: doc.source.meta.steps
|
|
5753
5839
|
}).filter((s) => !manualSpeed.some((m) => s.in < m.out && s.out > m.in)).filter((s) => !isRejected("speed", s, doc.rejected));
|
|
5754
5840
|
doc.speed = [...manualSpeed, ...autoSpeed].sort((a, b) => a.in - b.in);
|
|
5755
5841
|
{
|
|
@@ -5797,7 +5883,8 @@ async function planTake(dir, opts = {}) {
|
|
|
5797
5883
|
height: doc.source.meta.height,
|
|
5798
5884
|
duration: doc.source.meta.durationMs / 1e3,
|
|
5799
5885
|
style: doc.zoomStyle,
|
|
5800
|
-
params: doc.zoomParams
|
|
5886
|
+
params: doc.zoomParams,
|
|
5887
|
+
steps: doc.source.meta.steps
|
|
5801
5888
|
}).filter((z) => !manual.some((m) => overlaps(z, m))).filter((z) => !isRejected("zoom", z, doc.rejected));
|
|
5802
5889
|
doc.zoom = [...manual, ...auto].sort((a, b) => a.in - b.in);
|
|
5803
5890
|
const manualSpeed = (doc.speed ?? []).filter(
|
|
@@ -5806,7 +5893,8 @@ async function planTake(dir, opts = {}) {
|
|
|
5806
5893
|
const autoSpeed = planAutoSpeed(doc.source.cursor, {
|
|
5807
5894
|
durationMs: doc.source.meta.durationMs,
|
|
5808
5895
|
params: doc.speedParams,
|
|
5809
|
-
activity
|
|
5896
|
+
activity,
|
|
5897
|
+
steps: doc.source.meta.steps
|
|
5810
5898
|
}).filter((s) => !manualSpeed.some((m) => s.in < m.out && s.out > m.in)).filter((s) => !isRejected("speed", s, doc.rejected));
|
|
5811
5899
|
doc.speed = [...manualSpeed, ...autoSpeed].sort((a, b) => a.in - b.in);
|
|
5812
5900
|
{
|
|
@@ -5837,12 +5925,14 @@ async function planTake(dir, opts = {}) {
|
|
|
5837
5925
|
height: doc.source.meta.height,
|
|
5838
5926
|
duration: doc.source.meta.durationMs / 1e3,
|
|
5839
5927
|
style: doc.zoomStyle,
|
|
5840
|
-
params: doc.zoomParams
|
|
5928
|
+
params: doc.zoomParams,
|
|
5929
|
+
steps: doc.source.meta.steps
|
|
5841
5930
|
});
|
|
5842
5931
|
doc.speed = planAutoSpeed(doc.source.cursor, {
|
|
5843
5932
|
durationMs: doc.source.meta.durationMs,
|
|
5844
5933
|
params: doc.speedParams,
|
|
5845
|
-
activity
|
|
5934
|
+
activity,
|
|
5935
|
+
steps: doc.source.meta.steps
|
|
5846
5936
|
});
|
|
5847
5937
|
fresh = true;
|
|
5848
5938
|
}
|
|
@@ -11386,7 +11476,7 @@ function summary2(result) {
|
|
|
11386
11476
|
async function cmdActionsScript(input, flags) {
|
|
11387
11477
|
const r = createReporter(flags.json === true);
|
|
11388
11478
|
const { readFile: readFile14 } = await import("fs/promises");
|
|
11389
|
-
const { shotList, formatShotList } = await import("./shotList-
|
|
11479
|
+
const { shotList, formatShotList } = await import("./shotList-MAQVLZBY.js");
|
|
11390
11480
|
const raw = JSON.parse(await readFile14(resolve11(input), "utf8"));
|
|
11391
11481
|
const errors = validateActions(raw);
|
|
11392
11482
|
if (errors.length) throw new UsageError(`${input}:
|
|
@@ -14238,4 +14328,4 @@ export {
|
|
|
14238
14328
|
verbHelp,
|
|
14239
14329
|
run
|
|
14240
14330
|
};
|
|
14241
|
-
//# sourceMappingURL=chunk-
|
|
14331
|
+
//# sourceMappingURL=chunk-R4S6V4AC.js.map
|