recordable 0.4.0 → 0.5.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 +184 -30
- package/dist/actions.d.ts +7 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +5 -0
- package/dist/actions.js.map +1 -1
- package/dist/audio/track.d.ts +10 -0
- package/dist/audio/track.d.ts.map +1 -1
- package/dist/audio/track.js +19 -0
- package/dist/audio/track.js.map +1 -1
- package/dist/compose/boundaries.d.ts +13 -0
- package/dist/compose/boundaries.d.ts.map +1 -0
- package/dist/compose/boundaries.js +49 -0
- package/dist/compose/boundaries.js.map +1 -0
- package/dist/compose/mix.d.ts +3 -2
- package/dist/compose/mix.d.ts.map +1 -1
- package/dist/compose/mix.js +8 -3
- package/dist/compose/mix.js.map +1 -1
- package/dist/compose/recordable.d.ts +24 -2
- package/dist/compose/recordable.d.ts.map +1 -1
- package/dist/compose/recordable.js +56 -11
- package/dist/compose/recordable.js.map +1 -1
- package/dist/compose/session.d.ts +19 -8
- package/dist/compose/session.d.ts.map +1 -1
- package/dist/compose/session.js +99 -28
- package/dist/compose/session.js.map +1 -1
- package/dist/ffmpeg.d.ts.map +1 -1
- package/dist/ffmpeg.js +8 -3
- package/dist/ffmpeg.js.map +1 -1
- package/dist/formats/json.d.ts +2 -1
- package/dist/formats/json.d.ts.map +1 -1
- package/dist/formats/json.js.map +1 -1
- package/dist/fs.d.ts +16 -0
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +33 -4
- package/dist/fs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/result.d.ts +30 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +8 -0
- package/dist/result.js.map +1 -0
- package/dist/video/recorder.d.ts +26 -3
- package/dist/video/recorder.d.ts.map +1 -1
- package/dist/video/recorder.js +43 -19
- package/dist/video/recorder.js.map +1 -1
- package/package.json +19 -6
- package/recordable.schema.json +78 -0
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# recordable
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/recordable)
|
|
4
|
+
|
|
3
5
|
Programmatic, repeatable browser screen recording. Describe a session as a fluent
|
|
4
6
|
chain of actions — `visit`, `click`, `type`, `zoom`, `scroll` — and `recordable`
|
|
5
7
|
drives a real [Puppeteer](https://pptr.dev/) browser and captures a clean MP4,
|
|
@@ -22,12 +24,14 @@ await new Recordable({ typingSpeed: 120 })
|
|
|
22
24
|
.scroll("bottom")
|
|
23
25
|
.resetZoom()
|
|
24
26
|
.wait(1500)
|
|
25
|
-
.run(); // finalises automatically —
|
|
27
|
+
.run(); // finalises automatically — bookends are optional
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
Recording is **on by default** and finalises when `.run()` ends
|
|
29
|
-
`
|
|
30
|
-
|
|
30
|
+
Recording is **on by default** and finalises when `.run()` ends. Use `pause()` /
|
|
31
|
+
`resume()` to carve out anything you don't want on camera; every captured segment
|
|
32
|
+
is stitched into one seamless MP4. Need explicit bookends or several output files?
|
|
33
|
+
`start()` / `end()` / `split()` move the file boundaries (see
|
|
34
|
+
[Multiple output files](#multiple-output-files-start--end--split)).
|
|
31
35
|
|
|
32
36
|
## Features
|
|
33
37
|
|
|
@@ -45,9 +49,10 @@ want on camera; every captured segment is stitched into one seamless MP4.
|
|
|
45
49
|
- **Manual steps / logins** — `resumeOnPlay()` waits for an in-page ▶ Play button
|
|
46
50
|
(see below), so you can sign in by hand before recording.
|
|
47
51
|
- **Auto-scroll** to bring elements into view before interacting.
|
|
48
|
-
- **Declarative JSON
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
- **Declarative scripts (JSON _or_ Markdown) + CLI** — author a recording as data,
|
|
53
|
+
not code, and run it with `npx recordable demo.json` / `demo.md`, no install or
|
|
54
|
+
TypeScript required. JSON ships a published schema for editor autocomplete;
|
|
55
|
+
Markdown adds prose narration for voiceover.
|
|
51
56
|
|
|
52
57
|
## Install
|
|
53
58
|
|
|
@@ -57,7 +62,7 @@ npm install recordable
|
|
|
57
62
|
|
|
58
63
|
Frames are captured via the Chrome DevTools Protocol and encoded with **FFmpeg** —
|
|
59
64
|
there's no external screen-recorder dependency. The ffmpeg binary ships via
|
|
60
|
-
[
|
|
65
|
+
[`ffmpeg-static`](https://www.npmjs.com/package/ffmpeg-static),
|
|
61
66
|
so there's nothing else to install (a system `ffmpeg` on your `PATH` is used as a
|
|
62
67
|
fallback).
|
|
63
68
|
|
|
@@ -93,27 +98,132 @@ local copy) and your editor gives you autocomplete, required-key checking, and
|
|
|
93
98
|
typo catching for every action — no TypeScript needed. The schema is published as
|
|
94
99
|
`recordable.schema.json`.
|
|
95
100
|
|
|
96
|
-
Run a script from code
|
|
101
|
+
Run a JSON script from code by handing it to a `Recordable` — a parsed object or
|
|
102
|
+
the raw file string both work:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { readFileSync } from "node:fs";
|
|
106
|
+
import { Recordable } from "recordable";
|
|
107
|
+
|
|
108
|
+
const script = readFileSync("./demo.json", "utf8");
|
|
109
|
+
await new Recordable({ baseDir: "." }).fromJSON(script).run();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`baseDir` is the script's folder — `recordable` resolves relative `visit` URLs
|
|
113
|
+
and a relative `outputDir` against it. (Standalone `runScript` / `fromJSON`
|
|
114
|
+
helpers are also exported if you prefer a single call.)
|
|
115
|
+
|
|
116
|
+
## Declarative scripts (Markdown)
|
|
117
|
+
|
|
118
|
+
Markdown is the richest authoring surface — the **same actions as JSON**, written
|
|
119
|
+
as backtick method-call spans, with optional narration prose woven around them for
|
|
120
|
+
voiceover. YAML frontmatter carries the [config](#configuration); an optional
|
|
121
|
+
`voiceover` block opts into narration audio (`voiceover: true` reads provider /
|
|
122
|
+
voice from the environment, or pass an object to set them inline).
|
|
123
|
+
|
|
124
|
+
Two flavours, mixable in one document:
|
|
125
|
+
|
|
126
|
+
**1. A fenced action list** — one call per line, no prose. The closest Markdown
|
|
127
|
+
gets to JSON; compiles to the exact same actions:
|
|
128
|
+
|
|
129
|
+
````md
|
|
130
|
+
---
|
|
131
|
+
viewport: { width: 1280, height: 800 }
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
pause()
|
|
136
|
+
visit("./index.html")
|
|
137
|
+
resume()
|
|
138
|
+
zoom(1.4, { origin: "#email" })
|
|
139
|
+
type("#email", "hello@example.com")
|
|
140
|
+
click("text:Sign up", { waitForNav: true })
|
|
141
|
+
waitFor("text:Thanks", { state: "visible" })
|
|
142
|
+
resetZoom()
|
|
143
|
+
```
|
|
144
|
+
````
|
|
145
|
+
|
|
146
|
+
**2. Inline markers in prose** — drop call spans into narration; each fires at its
|
|
147
|
+
position in the spoken line. With `voiceover` on, the prose is read aloud and waits
|
|
148
|
+
are timed to the narration:
|
|
149
|
+
|
|
150
|
+
```md
|
|
151
|
+
---
|
|
152
|
+
typingSpeed: 16
|
|
153
|
+
voiceover: true
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
`visit("./signin.html")` Welcome — first we sign in with our work account
|
|
157
|
+
`type("#email", "maya@example.com")` then our password
|
|
158
|
+
`type("#password", "•••••")` `click("#signInBtn", { waitForNav: true })` — and
|
|
159
|
+
we're straight into the dashboard.
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Each backtick span holds exactly one call; its arguments are the method's
|
|
163
|
+
arguments, identical to the chainable API and the JSON `action` keys. Whole-line
|
|
164
|
+
`//` comments are stripped before parsing, so toggle-comment in your editor is
|
|
165
|
+
safe. Run a Markdown file through the [CLI](#cli) (`npx recordable demo.md`) or
|
|
166
|
+
from code:
|
|
97
167
|
|
|
98
168
|
```ts
|
|
99
|
-
import {
|
|
100
|
-
import
|
|
169
|
+
import { readFileSync } from "node:fs";
|
|
170
|
+
import { Recordable } from "recordable";
|
|
101
171
|
|
|
102
|
-
|
|
172
|
+
const md = readFileSync("./demo.md", "utf8");
|
|
173
|
+
await new Recordable({ baseDir: "." }).fromMarkdown(md).run();
|
|
103
174
|
```
|
|
104
175
|
|
|
105
|
-
|
|
176
|
+
## Voiceover
|
|
106
177
|
|
|
107
|
-
|
|
178
|
+
A Markdown script can narrate itself. The prose around your inline markers becomes
|
|
179
|
+
spoken audio (text-to-speech), and the markers are **timed to the narration** — each
|
|
180
|
+
action fires at its position in the spoken line, so the demo and the voice stay in
|
|
181
|
+
sync without hand-tuned `wait`s.
|
|
182
|
+
|
|
183
|
+
Opt in from frontmatter. With credentials in the environment, `voiceover: true` is
|
|
184
|
+
all a document needs; spell out a `voiceover` object to set provider / voice / model
|
|
185
|
+
inline (it overrides the environment):
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
voiceover: true
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```yaml
|
|
192
|
+
voiceover:
|
|
193
|
+
provider: elevenlabs # or `mock` for silent, offline audio
|
|
194
|
+
voiceId: EXAVITQu4vr4xnSDxMaL
|
|
195
|
+
modelId: eleven_multilingual_v2
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Credentials & defaults** come from a `.env` loaded automatically from **beside the
|
|
199
|
+
document** (copy [`.env.example`](.env.example)):
|
|
200
|
+
|
|
201
|
+
```sh
|
|
202
|
+
ELEVENLABS_API_KEY=... # required for real synthesis
|
|
203
|
+
RECORDABLE_TTS_PROVIDER=elevenlabs # or `mock` for silent, offline audio
|
|
204
|
+
RECORDABLE_VOICE_ID=... # default voice when frontmatter omits it
|
|
205
|
+
RECORDABLE_MODEL_ID=eleven_multilingual_v2
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Generated audio is written to the `assetsDir` (default `assets/`, beside the output)
|
|
209
|
+
and cached, so re-running an unchanged script doesn't re-synthesize. Validate a
|
|
210
|
+
voiceover script without hitting the TTS API — or a browser — with `recordable
|
|
211
|
+
demo.md --check`. For a music bed or a hand-recorded narration file, drop it straight
|
|
212
|
+
onto the timeline with `audio(path, opts?)` (see the [API](#recording)).
|
|
213
|
+
|
|
214
|
+
## CLI
|
|
215
|
+
|
|
216
|
+
Run a JSON **or** Markdown file directly — **no install required** via `npx`:
|
|
108
217
|
|
|
109
218
|
```sh
|
|
110
219
|
npx recordable demo.json
|
|
220
|
+
npx recordable demo.md
|
|
111
221
|
```
|
|
112
222
|
|
|
113
223
|
```
|
|
114
|
-
recordable <script.json> [options]
|
|
224
|
+
recordable <script.json | script.md> [options]
|
|
115
225
|
|
|
116
|
-
--check Validate the script and exit (no browser, no recording)
|
|
226
|
+
--check Validate the script and exit (no browser, no audio, no recording)
|
|
117
227
|
--headless Run without a visible browser window
|
|
118
228
|
--silent Suppress recorder console output
|
|
119
229
|
--out-dir <dir> Output directory (overrides the script's config)
|
|
@@ -195,8 +305,9 @@ new Recordable()
|
|
|
195
305
|
```
|
|
196
306
|
|
|
197
307
|
No `pause()`/`resume()` needed — `insert` seals the current segment and recording
|
|
198
|
-
resumes into a fresh one on the next action automatically. (Audio on the
|
|
199
|
-
currently dropped
|
|
308
|
+
resumes into a fresh one on the next action automatically. (Audio on the inserted
|
|
309
|
+
clip itself is currently dropped — narration voiceover is a separate, supported
|
|
310
|
+
feature, authored in [Markdown](#declarative-scripts-markdown).)
|
|
200
311
|
|
|
201
312
|
**Cross-fades.** Pass `fadeIn` / `fadeOut` (ms) to dissolve rather than hard-cut.
|
|
202
313
|
A fade blends the clip with the **neighbouring recorded footage** (a true
|
|
@@ -206,6 +317,39 @@ on `fadeOut`, while an outro's `fadeOut` dissolves down to black. Omit them for
|
|
|
206
317
|
hard cut. A cross-fade of _d_ ms overlaps the two pieces by _d_, shortening the
|
|
207
318
|
timeline by that much at each faded boundary.
|
|
208
319
|
|
|
320
|
+
## Multiple output files (`start` / `end` / `split`)
|
|
321
|
+
|
|
322
|
+
`pause()`/`resume()` carve off-camera gaps **within one file**. To produce
|
|
323
|
+
**separate files**, move the file boundaries with `start()` / `end()` / `split()`:
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
await new Recordable({ outputName: "demo" })
|
|
327
|
+
.start("intro") // open the first file (content before it is off-camera)
|
|
328
|
+
.visit("https://example.com")
|
|
329
|
+
.click("text:Get started")
|
|
330
|
+
.split("checkout") // close "intro", open the next — camera keeps rolling
|
|
331
|
+
.click("text:Buy")
|
|
332
|
+
.end() // close "checkout"; the teardown below runs off-camera
|
|
333
|
+
.click("text:Sign out")
|
|
334
|
+
.run(); // → demo-intro.mp4, demo-checkout.mp4
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
- **Boundaries default to the script edges.** With no `start()`, recording opens
|
|
338
|
+
at the top; with no `end()`, it closes at the bottom — so a plain script is one
|
|
339
|
+
file, exactly as before. Add only the bookend you need.
|
|
340
|
+
- **`pause`/`resume` ≠ `start`/`end`.** `resume()` continues the _same_ file (the
|
|
341
|
+
gap is stitched out); `start()`/`split()` open a _new_ file. `split() ≡ end() +
|
|
342
|
+
start()` fused with no gap; for two files _with_ an off-camera gap between them,
|
|
343
|
+
use `end()` … `start()`.
|
|
344
|
+
- **Naming.** Each file is `${outputName}-${label ?? index}.mp4`; a label always
|
|
345
|
+
wins. A single unlabelled file stays `${outputName}.mp4`.
|
|
346
|
+
- **Audio is per-file** — each output is standalone with its own zero-based
|
|
347
|
+
timeline; a clip is assigned to the file containing its start.
|
|
348
|
+
|
|
349
|
+
`run()` resolves to a `RecordableResult` — `{ status, files: [{ path, label,
|
|
350
|
+
index, durationMs, bytes }], outputDir, durationMs, elapsedMs, warnings }` — so
|
|
351
|
+
you can find every file that was written. Hard failures throw instead.
|
|
352
|
+
|
|
209
353
|
## API
|
|
210
354
|
|
|
211
355
|
Create an instance with optional [config](#configuration), chain actions, then
|
|
@@ -213,16 +357,22 @@ Create an instance with optional [config](#configuration), chain actions, then
|
|
|
213
357
|
|
|
214
358
|
### Recording
|
|
215
359
|
|
|
216
|
-
Recording is on by default and finalises automatically on `.run()
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
|
222
|
-
|
|
|
223
|
-
| `
|
|
224
|
-
| `
|
|
225
|
-
| `
|
|
360
|
+
Recording is on by default and finalises automatically on `.run()`, which resolves
|
|
361
|
+
to a [`RecordableResult`](#multiple-output-files-start--end--split). `pause`/`resume`
|
|
362
|
+
control what lands on camera _within_ a file; `start`/`end`/`split` move the file
|
|
363
|
+
boundaries to produce [separate files](#multiple-output-files-start--end--split):
|
|
364
|
+
|
|
365
|
+
| Method | Description |
|
|
366
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
367
|
+
| `pause()` | Stop capturing; the chain keeps running off-camera. |
|
|
368
|
+
| `resume()` | Resume capturing in a fresh segment, immediately. |
|
|
369
|
+
| `start(name?)` | Open an output file (opening boundary); content before the first `start()` is off-camera. `name` labels the file. |
|
|
370
|
+
| `end()` | Close the current output file (closing boundary); content after it runs off-camera. |
|
|
371
|
+
| `split(name?)` | Close the current file and open the next in one move, camera still rolling — `end()` + `start()` with no gap. |
|
|
372
|
+
| `waitForPlay(message?)` | Block until the user clicks the in-page ▶ Play button (or presses Enter); leaves recording state untouched. |
|
|
373
|
+
| `resumeOnPlay(message?)` | Wait for ▶ Play, then resume capturing — `waitForPlay().resume()`. |
|
|
374
|
+
| `insert(path, opts?)` | Splice an external clip (intro / outro / mid-roll) into the timeline; `opts.fadeIn`/`fadeOut` (ms) cross-fade it. |
|
|
375
|
+
| `audio(path, opts?)` | Lay an existing audio file (mp3/wav) onto the timeline here — narration, music bed, SFX. Blocks until the clip ends by default (`opts.wait: false` plays it over following actions); `opts.volume` gains it. |
|
|
226
376
|
|
|
227
377
|
### Navigation & waiting
|
|
228
378
|
|
|
@@ -305,11 +455,13 @@ new Recordable({
|
|
|
305
455
|
viewport: { width: 1920, height: 1080 },
|
|
306
456
|
pageZoom: 1, // browser page zoom (Ctrl +/−); <1 reflows to fit more on screen
|
|
307
457
|
fps: 30,
|
|
308
|
-
outputDir: "
|
|
458
|
+
outputDir: "output", // relative paths resolve against baseDir
|
|
309
459
|
outputName: "recordable",
|
|
310
460
|
outputTimestamp: true, // prepend an ISO timestamp to the filename
|
|
461
|
+
assetsDir: "assets", // where generated voiceover audio is written (relative to baseDir)
|
|
311
462
|
headless: false,
|
|
312
|
-
|
|
463
|
+
launchArgs: [], // extra Chromium flags, e.g. ["--no-sandbox"] for CI/containers
|
|
464
|
+
language: "", // BCP-47 locale, e.g. "fr-FR" (--lang + --accept-lang + Accept-Language); "" = system
|
|
313
465
|
typingSpeed: 7, // characters per second
|
|
314
466
|
videoCrf: 18, // lower = better quality, larger file
|
|
315
467
|
videoCodec: "libx264",
|
|
@@ -323,6 +475,7 @@ new Recordable({
|
|
|
323
475
|
scrollDuration: 1200, // ms for the scroll action's transition
|
|
324
476
|
cursor: true, // show the animated cursor overlay
|
|
325
477
|
visitTimeout: 30_000, // ms for navigation / waitFor
|
|
478
|
+
baseDir: "", // dir that relative visit URLs, outputDir & assetsDir resolve against; "" = cwd
|
|
326
479
|
});
|
|
327
480
|
```
|
|
328
481
|
|
|
@@ -336,6 +489,7 @@ npm test # unit + ffmpeg I/O tests
|
|
|
336
489
|
npm run test:e2e # opt-in end-to-end pipeline run (launches a browser)
|
|
337
490
|
npx tsx my-script.ts # run a recording script directly
|
|
338
491
|
node dist/cli.js demo.json # run a JSON script through the CLI locally
|
|
492
|
+
node dist/cli.js demo.md # run a Markdown script through the CLI locally
|
|
339
493
|
```
|
|
340
494
|
|
|
341
495
|
The JSON action set and its schema are both generated from one manifest in
|
package/dist/actions.d.ts
CHANGED
|
@@ -4,6 +4,13 @@ import * as z from "zod";
|
|
|
4
4
|
* discriminator). strictObject so an unknown key (a typo) fails validation.
|
|
5
5
|
*/
|
|
6
6
|
declare const ACTIONS: {
|
|
7
|
+
start: z.ZodObject<{
|
|
8
|
+
name: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strict>;
|
|
10
|
+
end: z.ZodObject<{}, z.core.$strict>;
|
|
11
|
+
split: z.ZodObject<{
|
|
12
|
+
name: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, z.core.$strict>;
|
|
7
14
|
pause: z.ZodObject<{}, z.core.$strict>;
|
|
8
15
|
resume: z.ZodObject<{}, z.core.$strict>;
|
|
9
16
|
waitForPlay: z.ZodObject<{
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAezB;;;GAGG;AACH,QAAA,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAezB;;;GAGG;AACH,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmE0B,CAAC;AAcxC,sEAAsE;AACtE,MAAM,MAAM,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAuChE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBjD;AAED;;;;;;GAMG;AACH,iBAAS,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAcxD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAkD3E;AAED,wEAAwE;AACxE,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB,iFAAiF;AACjF,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/actions.js
CHANGED
|
@@ -16,6 +16,9 @@ const XY = z.strictObject({ x: z.number(), y: z.number() });
|
|
|
16
16
|
*/
|
|
17
17
|
const ACTIONS = {
|
|
18
18
|
// Recording control
|
|
19
|
+
start: z.strictObject({ name: z.string().optional() }),
|
|
20
|
+
end: z.strictObject({}),
|
|
21
|
+
split: z.strictObject({ name: z.string().optional() }),
|
|
19
22
|
pause: z.strictObject({}),
|
|
20
23
|
resume: z.strictObject({}),
|
|
21
24
|
waitForPlay: z.strictObject({ message: z.string().optional() }),
|
|
@@ -81,6 +84,8 @@ const ACTIONS = {
|
|
|
81
84
|
* fact not derivable from the schema.
|
|
82
85
|
*/
|
|
83
86
|
const POSITIONAL_OPTIONAL = {
|
|
87
|
+
start: ["name"],
|
|
88
|
+
split: ["name"],
|
|
84
89
|
waitForPlay: ["message"],
|
|
85
90
|
resumeOnPlay: ["message"],
|
|
86
91
|
};
|
package/dist/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
|
package/dist/audio/track.d.ts
CHANGED
|
@@ -24,6 +24,16 @@ export declare class AudioTrack {
|
|
|
24
24
|
durationMs: number;
|
|
25
25
|
}>;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Partition clips across a run's output files (ROADMAP §6: per-file audio). A
|
|
29
|
+
* clip is assigned to the file *containing its start* — the last file whose
|
|
30
|
+
* global `startMs` is at or before the clip — then rebased to that file's own
|
|
31
|
+
* zero-based timeline. A clip overrunning its file's end is left for the mixer
|
|
32
|
+
* to trim (and warn). Returns one clip list per file, aligned to `files`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function partitionAudioByFiles(clips: readonly AudioClip[], files: readonly {
|
|
35
|
+
startMs: number;
|
|
36
|
+
}[]): AudioClip[][];
|
|
27
37
|
/**
|
|
28
38
|
* Build the `filter_complex` chain that delays each clip to its `startMs`,
|
|
29
39
|
* applies volume, and mixes them. Input index `i+1` (input 0 is the video).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/audio/track.ts"],"names":[],"mappings":"AAYA,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;uEACuE;AACvE,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IAEzC,oCAAoC;IACpC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,kEAAkE;IAClE,IAAI,IAAI,SAAS,SAAS,EAAE;IAI5B;;;OAGG;IACG,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAChC,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAUpD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG;IAC7D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAeA;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,OAAO,EAAE,MAAM,EACf,KAAK,SAAK,GACT;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAOpC"}
|
|
1
|
+
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/audio/track.ts"],"names":[],"mappings":"AAYA,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;uEACuE;AACvE,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IAEzC,oCAAoC;IACpC,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,kEAAkE;IAClE,IAAI,IAAI,SAAS,SAAS,EAAE;IAI5B;;;OAGG;IACG,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAChC,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAUpD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,KAAK,EAAE,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,GACpC,SAAS,EAAE,EAAE,CAUf;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG;IAC7D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAeA;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,OAAO,EAAE,MAAM,EACf,KAAK,SAAK,GACT;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAOpC"}
|
package/dist/audio/track.js
CHANGED
|
@@ -25,6 +25,25 @@ export class AudioTrack {
|
|
|
25
25
|
return { startMs, durationMs };
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Partition clips across a run's output files (ROADMAP §6: per-file audio). A
|
|
30
|
+
* clip is assigned to the file *containing its start* — the last file whose
|
|
31
|
+
* global `startMs` is at or before the clip — then rebased to that file's own
|
|
32
|
+
* zero-based timeline. A clip overrunning its file's end is left for the mixer
|
|
33
|
+
* to trim (and warn). Returns one clip list per file, aligned to `files`.
|
|
34
|
+
*/
|
|
35
|
+
export function partitionAudioByFiles(clips, files) {
|
|
36
|
+
const groups = files.map(() => []);
|
|
37
|
+
for (const c of clips) {
|
|
38
|
+
let idx = 0;
|
|
39
|
+
for (let i = 0; i < files.length; i++)
|
|
40
|
+
if (files[i].startMs <= c.startMs)
|
|
41
|
+
idx = i;
|
|
42
|
+
if (groups[idx])
|
|
43
|
+
groups[idx].push({ ...c, startMs: c.startMs - files[idx].startMs });
|
|
44
|
+
}
|
|
45
|
+
return groups;
|
|
46
|
+
}
|
|
28
47
|
/**
|
|
29
48
|
* Build the `filter_complex` chain that delays each clip to its `startMs`,
|
|
30
49
|
* applies volume, and mixes them. Input index `i+1` (input 0 is the video).
|
package/dist/audio/track.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track.js","sourceRoot":"","sources":["../../src/audio/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAkB/C;uEACuE;AACvE,MAAM,OAAO,UAAU;IACJ,KAAK,GAAgB,EAAE,CAAC;IAEzC,oCAAoC;IACpC,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,kEAAkE;IAClE,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CACP,IAAY,EACZ,OAAe,EACf,UAA+B,EAAE;QAEjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,MAAM,IAAI,eAAe,CACvB,gBAAgB,EAChB,0BAA0B,IAAI,EAAE,CACjC,CAAC;QACJ,MAAM,UAAU,GAAG,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACjC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA2B;IAI1D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxD,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAE3D,OAAO,CAAC,IAAI,CACV,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,KAAK,CAAC,MAAM,oBAAoB,CAClE,CAAC;IACF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,KAA2B,EAC3B,OAAe,EACf,KAAK,GAAG,EAAE;IAEV,MAAM,IAAI,GAAuC,EAAE,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC;QAC9D,IAAI,MAAM,GAAG,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"track.js","sourceRoot":"","sources":["../../src/audio/track.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Control actions whose ordering the state machine cares about. Plain actions
|
|
2
|
+
* (click, type, visit, …) are legal anywhere and aren't tracked. */
|
|
3
|
+
export type QueueKind = "start" | "end" | "split" | "pause" | "resume" | "insert" | "audio";
|
|
4
|
+
/**
|
|
5
|
+
* Walk the ordered control `kinds` and throw on the first illegal transition.
|
|
6
|
+
*
|
|
7
|
+
* Boundaries default to the script edges: with no explicit `start()` the file is
|
|
8
|
+
* open from the top (records top-to-bottom as before); an explicit `start()`
|
|
9
|
+
* means content before it is off-camera, so the file opens closed. An unmatched
|
|
10
|
+
* `start()` gets an implicit end at the bottom — finalisation closes it, no error.
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateBoundaries(kinds: readonly QueueKind[]): void;
|
|
13
|
+
//# sourceMappingURL=boundaries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundaries.d.ts","sourceRoot":"","sources":["../../src/compose/boundaries.ts"],"names":[],"mappings":"AAWA;qEACqE;AACrE,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,KAAK,GACL,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,CAAC;AAIZ;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAwCpE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RecordableError } from "../errors.js";
|
|
2
|
+
const err = (message) => new RecordableError("CONFIG_INVALID", message);
|
|
3
|
+
/**
|
|
4
|
+
* Walk the ordered control `kinds` and throw on the first illegal transition.
|
|
5
|
+
*
|
|
6
|
+
* Boundaries default to the script edges: with no explicit `start()` the file is
|
|
7
|
+
* open from the top (records top-to-bottom as before); an explicit `start()`
|
|
8
|
+
* means content before it is off-camera, so the file opens closed. An unmatched
|
|
9
|
+
* `start()` gets an implicit end at the bottom — finalisation closes it, no error.
|
|
10
|
+
*/
|
|
11
|
+
export function validateBoundaries(kinds) {
|
|
12
|
+
// The only state that gates legality is whether a file is open. pause/resume
|
|
13
|
+
// toggle the camera *within* an open file, so they never change it; split/end
|
|
14
|
+
// are allowed even while paused — so paused-ness needs no separate tracking.
|
|
15
|
+
let fileOpen = !kinds.includes("start"); // implicit start at top when none given
|
|
16
|
+
for (const k of kinds) {
|
|
17
|
+
switch (k) {
|
|
18
|
+
case "start":
|
|
19
|
+
if (fileOpen)
|
|
20
|
+
throw err("start() while a recording is already open — call end() or split() first");
|
|
21
|
+
fileOpen = true;
|
|
22
|
+
break;
|
|
23
|
+
case "end":
|
|
24
|
+
if (!fileOpen)
|
|
25
|
+
throw err("end() with no open recording — call start() first");
|
|
26
|
+
fileOpen = false; // sealed; allowed while paused
|
|
27
|
+
break;
|
|
28
|
+
case "split":
|
|
29
|
+
if (!fileOpen)
|
|
30
|
+
throw err("split() with no open recording — call start() first");
|
|
31
|
+
break; // end+start fused: stays open, new file rolls (allowed while paused)
|
|
32
|
+
case "pause":
|
|
33
|
+
if (!fileOpen)
|
|
34
|
+
throw err("pause() with no open recording to pause");
|
|
35
|
+
break; // redundant pause is a no-op, not an error
|
|
36
|
+
case "resume":
|
|
37
|
+
if (!fileOpen)
|
|
38
|
+
throw err("resume() with no open recording to resume");
|
|
39
|
+
break; // redundant resume is a no-op, not an error
|
|
40
|
+
case "insert":
|
|
41
|
+
case "audio":
|
|
42
|
+
if (!fileOpen)
|
|
43
|
+
throw err(`${k}() needs an open recording — it can't run in an off-camera gap; ` +
|
|
44
|
+
`call start() first`);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=boundaries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../../src/compose/boundaries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAsB/C,MAAM,GAAG,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,eAAe,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;AAEhF;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA2B;IAC5D,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,IAAI,QAAQ,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwC;IAEjF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,QAAQ,CAAC,EAAE,CAAC;YACV,KAAK,OAAO;gBACV,IAAI,QAAQ;oBACV,MAAM,GAAG,CACP,yEAAyE,CAC1E,CAAC;gBACJ,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,QAAQ;oBACX,MAAM,GAAG,CAAC,mDAAmD,CAAC,CAAC;gBACjE,QAAQ,GAAG,KAAK,CAAC,CAAC,+BAA+B;gBACjD,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,QAAQ;oBACX,MAAM,GAAG,CAAC,qDAAqD,CAAC,CAAC;gBACnE,MAAM,CAAC,qEAAqE;YAC9E,KAAK,OAAO;gBACV,IAAI,CAAC,QAAQ;oBAAE,MAAM,GAAG,CAAC,yCAAyC,CAAC,CAAC;gBACpE,MAAM,CAAC,2CAA2C;YACpD,KAAK,QAAQ;gBACX,IAAI,CAAC,QAAQ;oBAAE,MAAM,GAAG,CAAC,2CAA2C,CAAC,CAAC;gBACtE,MAAM,CAAC,4CAA4C;YACrD,KAAK,QAAQ,CAAC;YACd,KAAK,OAAO;gBACV,IAAI,CAAC,QAAQ;oBACX,MAAM,GAAG,CACP,GAAG,CAAC,kEAAkE;wBACpE,oBAAoB,CACvB,CAAC;gBACJ,MAAM;QACV,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/compose/mix.d.ts
CHANGED
|
@@ -7,7 +7,8 @@ import type { Logger } from "../logger.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Per the timing contract the video defines the length: a clip that runs past
|
|
9
9
|
* the end is the author's cue to add a trailing `wait()`, so we warn and let
|
|
10
|
-
* `-t` truncate it rather than padding the video.
|
|
10
|
+
* `-t` truncate it rather than padding the video. Returns the overrun warnings
|
|
11
|
+
* (also logged) so the caller can surface them on the run result.
|
|
11
12
|
*/
|
|
12
|
-
export declare function addAudio(videoPath: string, clips: readonly AudioClip[], out: string, log: Logger): Promise<
|
|
13
|
+
export declare function addAudio(videoPath: string, clips: readonly AudioClip[], out: string, log: Logger): Promise<string[]>;
|
|
13
14
|
//# sourceMappingURL=mix.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mix.d.ts","sourceRoot":"","sources":["../../src/compose/mix.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAU3C
|
|
1
|
+
{"version":3,"file":"mix.d.ts","sourceRoot":"","sources":["../../src/compose/mix.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAU3C;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,EAAE,CAAC,CAoCnB"}
|
package/dist/compose/mix.js
CHANGED
|
@@ -14,13 +14,17 @@ import { audioFilterGraph, audioOverruns, } from "../audio/track.js";
|
|
|
14
14
|
*
|
|
15
15
|
* Per the timing contract the video defines the length: a clip that runs past
|
|
16
16
|
* the end is the author's cue to add a trailing `wait()`, so we warn and let
|
|
17
|
-
* `-t` truncate it rather than padding the video.
|
|
17
|
+
* `-t` truncate it rather than padding the video. Returns the overrun warnings
|
|
18
|
+
* (also logged) so the caller can surface them on the run result.
|
|
18
19
|
*/
|
|
19
20
|
export async function addAudio(videoPath, clips, out, log) {
|
|
20
21
|
const videoMs = (await getDuration(videoPath)) * 1000;
|
|
22
|
+
const warnings = [];
|
|
21
23
|
for (const { path, overMs } of audioOverruns(clips, videoMs)) {
|
|
22
|
-
|
|
23
|
-
`add a trailing wait() to give it room
|
|
24
|
+
const msg = `"${path}" runs ${overMs}ms past the video end and will be cut — ` +
|
|
25
|
+
`add a trailing wait() to give it room`;
|
|
26
|
+
warnings.push(msg);
|
|
27
|
+
log("Audio", `warning: ${msg}`);
|
|
24
28
|
}
|
|
25
29
|
const { filters, mapLabel } = audioFilterGraph(clips);
|
|
26
30
|
await runFfmpeg([
|
|
@@ -46,5 +50,6 @@ export async function addAudio(videoPath, clips, out, log) {
|
|
|
46
50
|
out,
|
|
47
51
|
]);
|
|
48
52
|
log("Audio", `mixed ${clips.length} audio clip(s)`);
|
|
53
|
+
return warnings;
|
|
49
54
|
}
|
|
50
55
|
//# sourceMappingURL=mix.js.map
|
package/dist/compose/mix.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mix.js","sourceRoot":"","sources":["../../src/compose/mix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EACL,gBAAgB,EAChB,aAAa,GAEd,MAAM,mBAAmB,CAAC;AAG3B,gFAAgF;AAChF,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,+EAA+E;AAC/E,aAAa;AAEb
|
|
1
|
+
{"version":3,"file":"mix.js","sourceRoot":"","sources":["../../src/compose/mix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EACL,gBAAgB,EAChB,aAAa,GAEd,MAAM,mBAAmB,CAAC;AAG3B,gFAAgF;AAChF,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,+EAA+E;AAC/E,aAAa;AAEb;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAiB,EACjB,KAA2B,EAC3B,GAAW,EACX,GAAW;IAEX,MAAM,OAAO,GAAG,CAAC,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;QAC7D,MAAM,GAAG,GACP,IAAI,IAAI,UAAU,MAAM,0CAA0C;YAClE,uCAAuC,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,SAAS,CAAC;QACd,IAAI;QACJ,IAAI;QACJ,SAAS;QACT,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACvC,iBAAiB;QACjB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;QACjB,MAAM;QACN,KAAK;QACL,MAAM;QACN,IAAI,QAAQ,GAAG;QACf,MAAM;QACN,MAAM;QACN,MAAM;QACN,KAAK;QACL,6EAA6E;QAC7E,2EAA2E;QAC3E,+DAA+D;QAC/D,IAAI;QACJ,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3B,GAAG;KACJ,CAAC,CAAC;IACH,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACpD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type GoToOptions } from "puppeteer";
|
|
2
2
|
import { type AudioOptions, type ClickOptions, type InsertOptions, type RecordableConfig, type WaitForOptions } from "../config.js";
|
|
3
3
|
import { type Script } from "../script.js";
|
|
4
|
+
import { type RecordableResult } from "../result.js";
|
|
4
5
|
export declare class Recordable {
|
|
5
6
|
private cfg;
|
|
6
7
|
private readonly userConfig;
|
|
@@ -28,6 +29,26 @@ export declare class Recordable {
|
|
|
28
29
|
private _stageVoiceover;
|
|
29
30
|
/** Merge config mid-sequence — enqueued so it takes effect at this point. */
|
|
30
31
|
setConfig(config: RecordableConfig): this;
|
|
32
|
+
/**
|
|
33
|
+
* Open an output file (the opening boundary). Content *before* the first
|
|
34
|
+
* `start()` runs off-camera; absent, recording opens at the top. Pass an
|
|
35
|
+
* optional `name` to label the file (`start("intro")` → `…-intro.mp4`).
|
|
36
|
+
* Pair with `end()`, or leave it to close implicitly at the bottom.
|
|
37
|
+
*/
|
|
38
|
+
start(name?: string): this;
|
|
39
|
+
/**
|
|
40
|
+
* Close the current output file (the closing boundary). Content *after* `end()`
|
|
41
|
+
* runs off-camera (cleanup is common, so no warning); absent, recording closes
|
|
42
|
+
* at the bottom. Open another file with `start()` for a second output.
|
|
43
|
+
*/
|
|
44
|
+
end(): this;
|
|
45
|
+
/**
|
|
46
|
+
* Split the output here: close the current file and open the next in one move,
|
|
47
|
+
* camera still rolling (`split() ≡ end() + start()` fused, no gap). Pass an
|
|
48
|
+
* optional `name` to label the new file. For two files with an off-camera gap
|
|
49
|
+
* between them, use `end()` … `start()` instead.
|
|
50
|
+
*/
|
|
51
|
+
split(name?: string): this;
|
|
31
52
|
/**
|
|
32
53
|
* Stop capturing. The chain keeps running — anything between `pause()` and the
|
|
33
54
|
* next resume executes off-camera (page loads, logins, data setup) and is
|
|
@@ -151,8 +172,9 @@ export declare class Recordable {
|
|
|
151
172
|
}): this;
|
|
152
173
|
/** Pause the sequence for `ms` milliseconds. */
|
|
153
174
|
wait(ms: number): this;
|
|
154
|
-
/** Execute the queued action sequence, then finalise the recording.
|
|
155
|
-
|
|
175
|
+
/** Execute the queued action sequence, then finalise the recording. Resolves to
|
|
176
|
+
* a {@link RecordableResult} describing the written file(s). */
|
|
177
|
+
run(): Promise<RecordableResult>;
|
|
156
178
|
/** Resolve a local asset path (insert/audio clip) against `baseDir` so a
|
|
157
179
|
* Markdown/JSON script and its clips travel together; absolute paths pass
|
|
158
180
|
* through. `baseDir` empty → resolve against cwd (the programmatic default). */
|