@vosjs/render-core 0.2.0 → 0.2.1
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 +36 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,60 +1,58 @@
|
|
|
1
1
|
# @vosjs/render-core
|
|
2
2
|
|
|
3
|
-
The
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
else.
|
|
3
|
+
> The render harness for deterministic vos renders: shard a timeline into parallel chunks, then stream-copy the encoded chunks back into one file without re-encoding.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vosjs/render-core)
|
|
6
|
+
[](https://github.com/vosjs/vos/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Part of [vos](https://github.com/vosjs/vos). Pixels never leave the browser: every frame is encoded in-page with WebCodecs and [mediabunny](https://mediabunny.dev). This package owns what happens around that in Node: how a timeline is split into frame ranges that can render concurrently, and how the encoded parts are muxed into a single container. Its one dependency is mediabunny. Consumed by the `vos` CLI's local render and by any host that fans a render out across browser sessions.
|
|
9
|
+
|
|
10
|
+
What is deliberately not here: the pages a hosted fleet runs (a finalize page that fetches parts from an ingest route, an audio mix page), and any queue, storage or session-pool policy. Those are a host's opinions about its own infrastructure; this package hands them the plan and the mux and nothing else.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @vosjs/render-core
|
|
16
|
+
```
|
|
18
17
|
|
|
19
18
|
## Why sharding is correct here
|
|
20
19
|
|
|
21
|
-
A vos render is a pure `seek(t)` function, so a timeline splits cleanly into
|
|
22
|
-
independent frame ranges. Each range is rendered concurrently as its own page,
|
|
23
|
-
encoded with **pinned** encoder params and chunk-local timestamps, then the
|
|
24
|
-
packets are stream-copied into a single container — a plain demux/remux, no
|
|
25
|
-
re-encode, no quality loss. Timestamp offsets come from the plan (frames ÷ fps),
|
|
26
|
-
never from measured durations, so rounding can't drift.
|
|
20
|
+
A vos render is a pure `seek(t)` function, so a timeline splits cleanly into independent frame ranges. Each range renders concurrently as its own page, encoded with pinned encoder params and chunk-local timestamps, and the packets are stream-copied into one container: a plain demux and remux, no re-encode, no quality loss. Timestamp offsets come from the plan (frames divided by fps), never from measured durations, so rounding cannot drift.
|
|
27
21
|
|
|
28
22
|
```
|
|
29
|
-
planChunks(
|
|
30
|
-
│ render each range concurrently (browser, pinned encoder)
|
|
23
|
+
planChunks(totalFrames, fps, { maxParallel }) ──▶ [ { index, startFrame, endFrame, frameCount, startTime, duration }, … ]
|
|
24
|
+
│ render each range concurrently (a browser page each, pinned encoder)
|
|
31
25
|
▼
|
|
32
|
-
|
|
26
|
+
muxEncodedExport({ video: parts, audio?, format }) ──▶ one file, packet-identical to a single-pass render
|
|
33
27
|
```
|
|
34
28
|
|
|
35
|
-
Audio stays out of the chunks by design and is mixed
|
|
36
|
-
priming seams never exist.
|
|
29
|
+
Audio stays out of the chunks by design and is mixed once at finalize, so codec priming seams never exist.
|
|
37
30
|
|
|
38
31
|
## Exports
|
|
39
32
|
|
|
40
|
-
| Export
|
|
41
|
-
|
|
|
42
|
-
| `planChunks(totalFrames, fps, policy)`
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
33
|
+
| Export | Purpose |
|
|
34
|
+
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
35
|
+
| `planChunks(totalFrames, fps, policy)` | Split a timeline into balanced frame ranges. `policy` is `{ maxParallel, minFramesPerChunk? }`; the floor is `DEFAULT_MIN_FRAMES_PER_CHUNK` (24). Pure math. |
|
|
36
|
+
| `muxEncodedExport(options)` | Stream-copy encoded video parts (an iterable or async iterable of `{ data, duration }`, fed one at a time) plus an optional encoded audio part into one `webm` or `mp4`. |
|
|
37
|
+
| `concatEncodedVideo(chunks, options)` | The same for an in-memory list of video chunks; a thin wrapper over `muxEncodedExport`. |
|
|
38
|
+
| `countVideoPackets(bytes)` | Count the video packets in an encoded file; used by parity checks. |
|
|
39
|
+
| `audioProducerCode(options?)` | Page JavaScript that mixes a composition's audio in the browser through `@vosjs/core/audio`, from a host-built plan or from the studio's audio data, for the finalize step. |
|
|
40
|
+
| `dataHasAudio(data, stack?, plan?)` | Whether a lowered composition carries any sound, so a video-only render can skip the audio page. |
|
|
41
|
+
| `studioEntryData(stack)` | Find the studio layer entry's data in a lowered `stack` (array or keyed). |
|
|
42
|
+
|
|
43
|
+
Types: `ChunkPlanPolicy`, `RenderChunk`, `ConcatChunk`, `ConcatOptions` (`{ format, frameRate? }`), `ConcatResult` (`{ bytes, packetCount, codec }`), `MuxExportOptions`, `AudioPlanJson`, `AudioProducerCodeOptions`; plus `CORE_AUDIO_CDN_URL`, the pinned `@vosjs/core/audio` module the producer page imports.
|
|
46
44
|
|
|
47
45
|
## Contract: the concat mirror
|
|
48
46
|
|
|
49
|
-
A host that concatenates
|
|
50
|
-
fallback, where the Node mux cannot run) must stay **packet-identical** to
|
|
51
|
-
`concat.ts`: the CLI uses the Node path, a fleet may use a page, and the two
|
|
52
|
-
must produce the same file. Keep any such page in sync with `concat.ts` and
|
|
53
|
-
assert the parity in the host's own harness.
|
|
47
|
+
A host that concatenates parts inside a browser page (a fleet's fallback, where the Node mux cannot run) must stay packet-identical to `concat.ts`: the CLI uses the Node path, a fleet may use a page, and the two must produce the same file. Keep any such page in sync with `concat.ts` and assert the parity in the host's own harness.
|
|
54
48
|
|
|
55
49
|
## Development
|
|
56
50
|
|
|
57
51
|
```bash
|
|
58
|
-
pnpm --filter @vosjs/render-core test
|
|
52
|
+
pnpm --filter @vosjs/render-core test
|
|
59
53
|
pnpm --filter @vosjs/render-core typecheck
|
|
60
54
|
```
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
[MIT](https://github.com/vosjs/vos/blob/main/LICENSE) © vosso
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vosjs/render-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "The render harness for deterministic vos renders: timeline-sharded chunk planning and stream-copy chunk concat. Pixels stay in the browser; this package owns the orchestration math and the Node-side media plumbing.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vosso",
|