{"_id":"@boundsvg/video","_rev":"4-8add6f66d740e7278c5518ecc550e819","name":"@boundsvg/video","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"@boundsvg/video","version":"0.1.0","keywords":["mp4","webcodecs","svg","video","animation"],"author":{"name":"zakideee"},"license":"MIT OR Apache-2.0","_id":"@boundsvg/video@0.1.0","maintainers":[{"name":"zakideee","email":"zakideee.dev@gmail.com"}],"homepage":"https://github.com/zakideee/boundsvg/tree/main/packages/video","bugs":{"url":"https://github.com/zakideee/boundsvg/issues"},"dist":{"shasum":"4bf36a7a031b4a594960e689f64eea5e0ea23cea","tarball":"https://registry.npmjs.org/@boundsvg/video/-/video-0.1.0.tgz","fileCount":9,"integrity":"sha512-+zDMoNP4m9sSdfJR52p8pnwMeOWKYqmAYr0SuUWWJUOPBok0LRDwExTqvYYqiNPXrGV5g3BfTVREvRsvpiwR/Q==","signatures":[{"sig":"MEYCIQDD2ltTu1+bUCVRVSNBAAqW9E4cUzQaG+eYevXIhtAVNgIhAOy2lbXzHPKio0IUXBm0Zjd2zJE7YIObr79QFqy7k3bB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@boundsvg%2fvideo@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":227155},"type":"module","_from":"file:boundsvg-video-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json","./dist/boundmp4_bg.wasm":"./dist/boundmp4_bg.wasm"},"scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"zakideee","email":"zakideee.dev@gmail.com"},"_resolved":"/tmp/3b48a6ce6ee80be904a25d5ea0e08c28/boundsvg-video-0.1.0.tgz","_integrity":"sha512-+zDMoNP4m9sSdfJR52p8pnwMeOWKYqmAYr0SuUWWJUOPBok0LRDwExTqvYYqiNPXrGV5g3BfTVREvRsvpiwR/Q==","repository":{"url":"git+https://github.com/zakideee/boundsvg.git","type":"git","directory":"packages/video"},"_npmVersion":"10.9.8","description":"Browser MP4 export for boundsvg — WebCodecs H.264 encoding with a bundled MP4 muxer","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.0.0","typescript":"^5.7.0","@boundsvg/core":"0.1.0"},"peerDependencies":{"@boundsvg/core":"^0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/video_0.1.0_1787391553606_0.7440195611098079","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@boundsvg/video","version":"0.2.0","keywords":["mp4","webcodecs","svg","video","animation"],"author":{"name":"zakideee"},"license":"MIT OR Apache-2.0","_id":"@boundsvg/video@0.2.0","maintainers":[{"name":"zakideee","email":"zakideee.dev@gmail.com"}],"homepage":"https://github.com/zakideee/boundsvg/tree/main/packages/video","bugs":{"url":"https://github.com/zakideee/boundsvg/issues"},"dist":{"shasum":"6db62acc00f03e177bdf20d81b15e83fe5eb0487","tarball":"https://registry.npmjs.org/@boundsvg/video/-/video-0.2.0.tgz","fileCount":9,"integrity":"sha512-fg0w3D4V+yk5j2W5L3tt5t/zq2MwK/ny08d4XmnZxSJIDi7+l3FjCpctQhdtBA7aiP92drl8rhq5VOjhXWgpIg==","signatures":[{"sig":"MEQCIH15K3et6WzieU504T1WmpnjReKwcxWdn0fmflbXMXD+AiALQ2NjrYXEzJSxubYYbelyiblY3IPj0G9klXMVbOSTHg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@boundsvg%2fvideo@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":227935},"type":"module","_from":"file:boundsvg-video-0.2.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json","./dist/boundmp4_bg.wasm":"./dist/boundmp4_bg.wasm"},"scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e9fb5ce3-385f-4e73-b330-0c13ef4f8cb0"}},"_resolved":"/tmp/e35b0635c807b031cbd21cf2352b5135/boundsvg-video-0.2.0.tgz","_integrity":"sha512-fg0w3D4V+yk5j2W5L3tt5t/zq2MwK/ny08d4XmnZxSJIDi7+l3FjCpctQhdtBA7aiP92drl8rhq5VOjhXWgpIg==","repository":{"url":"git+https://github.com/zakideee/boundsvg.git","type":"git","directory":"packages/video"},"_npmVersion":"11.19.0","description":"Browser MP4 export for boundsvg — WebCodecs H.264 encoding with a bundled MP4 muxer","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.0.0","typescript":"^5.7.0","@boundsvg/core":"0.2.0"},"peerDependencies":{"@boundsvg/core":">=0.2.0 <0.3.0"},"_npmOperationalInternal":{"tmp":"tmp/video_0.2.0_1787798071292_0.15381081343147018","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@boundsvg/video","version":"0.3.0","keywords":["mp4","webcodecs","svg","video","animation"],"author":{"name":"zakideee"},"license":"MIT OR Apache-2.0","_id":"@boundsvg/video@0.3.0","maintainers":[{"name":"zakideee","email":"zakideee.dev@gmail.com"}],"homepage":"https://github.com/zakideee/boundsvg/tree/main/packages/video","bugs":{"url":"https://github.com/zakideee/boundsvg/issues"},"dist":{"shasum":"87c07b2a36113798ea53328392f3bcacbf706209","tarball":"https://registry.npmjs.org/@boundsvg/video/-/video-0.3.0.tgz","fileCount":9,"integrity":"sha512-iRyvY4Z85GtIg/Gpeld4xdFl+QDHvWFCRLHcVIWgxsD0RSztk9f6sCcXkUDHF5YLt9F77h7Wom3IO0Mrf4Xg3g==","signatures":[{"sig":"MEQCICkxPpzBVyJS8G81CMmYBIvpYzwID3/gqAuUaDHVBt/xAiAQ5artU9yaEpiN5cjhN3Cw80gJQTl+xpIN193j8m3G5A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@boundsvg%2fvideo@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":227945},"type":"module","_from":"file:boundsvg-video-0.3.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json","./dist/boundmp4_bg.wasm":"./dist/boundmp4_bg.wasm"},"scripts":{"test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e9fb5ce3-385f-4e73-b330-0c13ef4f8cb0"}},"_resolved":"/tmp/9013213bbc5bfedd32533f89f20d6264/boundsvg-video-0.3.0.tgz","_integrity":"sha512-iRyvY4Z85GtIg/Gpeld4xdFl+QDHvWFCRLHcVIWgxsD0RSztk9f6sCcXkUDHF5YLt9F77h7Wom3IO0Mrf4Xg3g==","repository":{"url":"git+https://github.com/zakideee/boundsvg.git","type":"git","directory":"packages/video"},"_npmVersion":"11.19.0","description":"Browser MP4 export for boundsvg — WebCodecs H.264 encoding with a bundled MP4 muxer","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vitest":"^3.0.0","typescript":"^5.7.0","@boundsvg/core":"0.3.0"},"peerDependencies":{"@boundsvg/core":">=0.3.0 <0.4.0"},"_npmOperationalInternal":{"tmp":"tmp/video_0.3.0_1787910509853_0.9652893271484839","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@boundsvg/video","version":"0.4.0","description":"Browser MP4 export for boundsvg — WebCodecs H.264 encoding with a bundled MP4 muxer","keywords":["mp4","webcodecs","svg","video","animation"],"license":"MIT OR Apache-2.0","repository":{"type":"git","url":"git+https://github.com/zakideee/boundsvg.git","directory":"packages/video"},"homepage":"https://github.com/zakideee/boundsvg/tree/main/packages/video","bugs":{"url":"https://github.com/zakideee/boundsvg/issues"},"author":{"name":"zakideee"},"publishConfig":{"access":"public"},"type":"module","exports":{"./package.json":"./package.json",".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dist/boundmp4_bg.wasm":"./dist/boundmp4_bg.wasm"},"module":"./dist/index.js","types":"./dist/index.d.ts","sideEffects":false,"peerDependencies":{"@boundsvg/core":">=0.4.0 <0.5.0"},"devDependencies":{"tsup":"^8.3.0","typescript":"^5.7.0","vitest":"^3.0.0","@boundsvg/core":"0.4.0"},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit"},"_id":"@boundsvg/video@0.4.0","_integrity":"sha512-9YYXpJNQN4ABjeb7brqNj5vavag07G1Esoz69wOwqdXEGzaP2ARPFuCwXEX2lX/WpdQbcylbFV8jAmrfkL+MAg==","_resolved":"/tmp/de7e6f08e518f6a7ea2633c80dd1a5fc/boundsvg-video-0.4.0.tgz","_from":"file:boundsvg-video-0.4.0.tgz","_nodeVersion":"22.14.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-9YYXpJNQN4ABjeb7brqNj5vavag07G1Esoz69wOwqdXEGzaP2ARPFuCwXEX2lX/WpdQbcylbFV8jAmrfkL+MAg==","shasum":"9ff06a7526d129de320899a553a10947e88a691d","tarball":"https://registry.npmjs.org/@boundsvg/video/-/video-0.4.0.tgz","fileCount":9,"unpackedSize":227955,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@boundsvg%2fvideo@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAgonH/bLFvcmm2q+/F2bOaFNv6+iYbuW7bP/joZ11zIAiBYjj0Tc5bZzoU07VuaJsaD+cmhvoL1wd12phvzRNjswg=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e9fb5ce3-385f-4e73-b330-0c13ef4f8cb0"}},"directories":{},"maintainers":[{"name":"zakideee","email":"zakideee.dev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/video_0.4.0_1788055359128_0.4522808354762313"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-22T09:39:13.436Z","modified":"2026-08-30T02:02:39.642Z","0.1.0":"2026-08-22T09:39:13.768Z","0.2.0":"2026-08-27T02:34:31.449Z","0.3.0":"2026-08-28T09:48:29.990Z","0.4.0":"2026-08-30T02:02:39.319Z"},"bugs":{"url":"https://github.com/zakideee/boundsvg/issues"},"author":{"name":"zakideee"},"license":"MIT OR Apache-2.0","homepage":"https://github.com/zakideee/boundsvg/tree/main/packages/video","keywords":["mp4","webcodecs","svg","video","animation"],"repository":{"type":"git","url":"git+https://github.com/zakideee/boundsvg.git","directory":"packages/video"},"description":"Browser MP4 export for boundsvg — WebCodecs H.264 encoding with a bundled MP4 muxer","maintainers":[{"name":"zakideee","email":"zakideee.dev@gmail.com"}],"readme":"# @boundsvg/video\n\nBrowser MP4 export for boundsvg — WebCodecs H.264 encoding with a bundled MP4 muxer.\n\n## Installation\n\n```bash\nnpm install @boundsvg/video\n```\n\n## Usage\n\n```ts\nimport { renderToMp4 } from \"@boundsvg/video\";\n\nconst mp4 = await renderToMp4(engine, scene, {\n  durationMs: 3000,\n  frameRate: 30,\n});\n```\n\nFractional NTSC rates are given in their exact rational form (or by alias):\n\n```ts\nconst mp4 = await renderToMp4(engine, scene, {\n  durationMs: 3000,\n  frameRate: { numerator: 30000, denominator: 1001 }, // same as 29.97\n});\n```\n\nAn existing PNG frame sequence — from a worker pool, for instance — can be encoded directly:\n\n```ts\nimport { encodePngFramesToMp4 } from \"@boundsvg/video\";\n\nconst mp4 = await encodePngFramesToMp4(frames, {\n  frameRate: 30,\n  frameCount: frames.length,\n});\n```\n\n`frameCount` is optional. Without it the container index is sized for the 3600-frame ceiling,\nwhich leaves roughly 59 KB of padding in the file; passing the real count removes it. A stream\nlonger than the declared count is rejected at that frame.\n\nEvery frame must be the same size — the first one fixes the output dimensions.\n\n## Loading the muxer wasm\n\nThe bundled muxer binary is loaded on first use from `boundmp4_bg.wasm` next to the package's\nown module. When a bundler moves the module without the binary, point the loader at it before\nexporting anything:\n\n```ts\nimport { initVideoWasm } from \"@boundsvg/video\";\nimport wasmUrl from \"@boundsvg/video/dist/boundmp4_bg.wasm?url\";\n\nawait initVideoWasm(new URL(wasmUrl, import.meta.url));\n```\n\n`initVideoWasm` also accepts a `Response`, a `WebAssembly.Module`, or the raw bytes. Calling it\nis optional and idempotent; a failed load can be retried.\n\n## Requirements\n\nBrowsers only. The encoder is the browser's own WebCodecs `VideoEncoder`, which Node.js and\nCloudflare Workers do not provide. Node-side MP4 export through an external ffmpeg lives in\n`@boundsvg/cli` (`--format mp4`).\n\nH.264 in yuv420 carries no alpha and needs even dimensions, so frames are padded to even sizes\nand composited over `background` (default `#ffffff`). A translucent `background` is rejected\nrather than silently composited against black.\n\nThe default codec string is `avc1.640028` — H.264 High profile, level 4.0, which covers 1080p30.\nLarger or faster exports need a higher level, e.g. `codec: \"avc1.640033\"` (5.1) for 1080p60 or\n4K; otherwise the browser rejects the configuration.\n\nOne encoded sample per frame, in order, is required: the container gives every sample the same\nduration, so it cannot express the reordering an encoder emitting B-frames would produce. An\nexport that gets reordered or dropped output fails with `VIDEO_ENCODER_UNSUPPORTED` rather than\nproducing a file that plays wrong. Verified on Chrome 134 (Linux).\n\nA single export is capped at 256 MiB of encoded video.\n\n## Errors\n\nFailures throw `FatalError` from `@boundsvg/core`, with `code` set to one of:\n\n| Code                        | Meaning                                                                                          |\n| --------------------------- | ------------------------------------------------------------------------------------------------ |\n| `VIDEO_INVALID_FRAME_RATE`  | `frameRate` is not a supported integer, alias, or rational                                       |\n| `VIDEO_INVALID_SCHEDULE`    | `durationMs` / `timesMs` do not describe a schedule the container can represent                  |\n| `VIDEO_INVALID_OPTION`      | any other option value — `bitrate`, `background`, `frameCount`                                   |\n| `VIDEO_INVALID_FRAMES`      | the frames themselves — wrong format, inconsistent size, too few, more than declared             |\n| `VIDEO_TOO_MANY_FRAMES`     | the export exceeds the 3600-frame ceiling                                                        |\n| `VIDEO_ENCODER_UNSUPPORTED` | WebCodecs is missing, rejects the configuration, or produces output the container cannot express |\n| `VIDEO_EXPORT_ABORTED`      | the `signal` was aborted                                                                         |\n\nErrors raised by the frame sampler propagate unchanged from `@boundsvg/core` — for example\n`PNG_PIXEL_LIMIT` when `rasterOversizeBehavior: \"error\"` — so a `catch` should not assume the\ncode starts with `VIDEO_`.\n\nEncoded bytes depend on the browser's encoder and are therefore outside the boundsvg byte\ndeterminism contract. What stays deterministic is the input: the PNG frames `renderFrames`\nproduces. Decoding them, compositing them onto a canvas, and encoding them are all the\nbrowser's work.\n\n## Documentation\n\nFull documentation: <https://github.com/zakideee/boundsvg>\n\n## License\n\nMIT OR Apache-2.0\n\nThe bundled MP4 muxer wasm includes [shiguredo_mp4](https://github.com/shiguredo/mp4-rs)\n(Apache-2.0). Video is encoded by the browser's own codec implementation; no codec ships with\nthis package.\n","readmeFilename":"README.md"}