@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.
Files changed (2) hide show
  1. package/README.md +36 -38
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,60 +1,58 @@
1
1
  # @vosjs/render-core
2
2
 
3
- The orchestration math and Node-side media plumbing for deterministic vos
4
- renders. Pixels never leave the browser — every frame is encoded in-page via
5
- WebCodecs + [mediabunny](https://mediabunny.dev). This package owns everything
6
- around that: how a timeline is sharded into parallel chunks, and how the encoded
7
- chunks are stitched back into one file without re-encoding.
8
-
9
- Pure Node, no browser and no WebGL. Consumed by the `vos` CLI's local render
10
- (`../cli`) and by any host that fans a render out across browser sessions and
11
- stitches the parts back together. MIT.
12
-
13
- What is deliberately NOT here: the pages a hosted fleet runs (a finalize page
14
- that fetches parts from an ingest route, an audio mix page, a digest page) and
15
- any queue, storage or session-pool policy. Those are a host's opinions about its
16
- own infrastructure; this package hands them the plan and the mux and nothing
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
+ [![npm](https://img.shields.io/npm/v/@vosjs/render-core.svg)](https://www.npmjs.com/package/@vosjs/render-core)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](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(total, fps, policy) ──▶ [ {startFrame, endFrame}, … ]
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
- concatEncodedVideo([chunk₀, chunk₁, …]) ──▶ one file, packet-identical to a single-pass render
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 **once** at finalize, so AAC
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 | Purpose |
41
- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
42
- | `planChunks(totalFrames, fps, policy)` | Split a timeline into balanced frame ranges (floor `DEFAULT_MIN_FRAMES_PER_CHUNK` per chunk). Pure math. |
43
- | `concatEncodedVideo(chunks, options)` | Stream-copy encoded chunks into one video (mediabunny demux/mux, no re-encode). |
44
- | `countVideoPackets(bytes)` | Count video packets in an encoded file — used by parity checks. |
45
- | `audioProducerCode()` / `dataHasAudio(data)` | Page-JS mirror of the client audio exporter — produces the mixed audio buffer at finalize from the lowered Voila data. |
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 chunk parts inside a browser page (a fleet's finalize
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 # vitest
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.0",
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",