@smoove/renderer 0.1.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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/dist/audio-mix.d.ts +14 -0
  4. package/dist/audio-mix.d.ts.map +1 -0
  5. package/dist/audio-mix.js +127 -0
  6. package/dist/audio-mix.js.map +1 -0
  7. package/dist/audio-source-null.d.ts +25 -0
  8. package/dist/audio-source-null.d.ts.map +1 -0
  9. package/dist/audio-source-null.js +26 -0
  10. package/dist/audio-source-null.js.map +1 -0
  11. package/dist/audio-track.d.ts +17 -0
  12. package/dist/audio-track.d.ts.map +1 -0
  13. package/dist/audio-track.js +91 -0
  14. package/dist/audio-track.js.map +1 -0
  15. package/dist/encode.d.ts +45 -0
  16. package/dist/encode.d.ts.map +1 -0
  17. package/dist/encode.js +105 -0
  18. package/dist/encode.js.map +1 -0
  19. package/dist/font-loader.d.ts +11 -0
  20. package/dist/font-loader.d.ts.map +1 -0
  21. package/dist/font-loader.js +52 -0
  22. package/dist/font-loader.js.map +1 -0
  23. package/dist/gl-node.d.ts +10 -0
  24. package/dist/gl-node.d.ts.map +1 -0
  25. package/dist/gl-node.js +61 -0
  26. package/dist/gl-node.js.map +1 -0
  27. package/dist/gl.d.ts +12 -0
  28. package/dist/gl.d.ts.map +1 -0
  29. package/dist/gl.js +28 -0
  30. package/dist/gl.js.map +1 -0
  31. package/dist/image-loader.d.ts +9 -0
  32. package/dist/image-loader.d.ts.map +1 -0
  33. package/dist/image-loader.js +20 -0
  34. package/dist/image-loader.js.map +1 -0
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +16 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/media-input-source.d.ts +8 -0
  40. package/dist/media-input-source.d.ts.map +1 -0
  41. package/dist/media-input-source.js +22 -0
  42. package/dist/media-input-source.js.map +1 -0
  43. package/dist/media-server.d.ts +7 -0
  44. package/dist/media-server.d.ts.map +1 -0
  45. package/dist/media-server.js +14 -0
  46. package/dist/media-server.js.map +1 -0
  47. package/dist/probe.d.ts +5 -0
  48. package/dist/probe.d.ts.map +1 -0
  49. package/dist/probe.js +13 -0
  50. package/dist/probe.js.map +1 -0
  51. package/dist/register.d.ts +2 -0
  52. package/dist/register.d.ts.map +1 -0
  53. package/dist/register.js +6 -0
  54. package/dist/register.js.map +1 -0
  55. package/dist/render.d.ts +18 -0
  56. package/dist/render.d.ts.map +1 -0
  57. package/dist/render.js +190 -0
  58. package/dist/render.js.map +1 -0
  59. package/dist/setup.d.ts +12 -0
  60. package/dist/setup.d.ts.map +1 -0
  61. package/dist/setup.js +46 -0
  62. package/dist/setup.js.map +1 -0
  63. package/dist/skia.d.ts +8 -0
  64. package/dist/skia.d.ts.map +1 -0
  65. package/dist/skia.js +15 -0
  66. package/dist/skia.js.map +1 -0
  67. package/dist/types.d.ts +153 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +8 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/video-source-mediabunny.d.ts +63 -0
  72. package/dist/video-source-mediabunny.d.ts.map +1 -0
  73. package/dist/video-source-mediabunny.js +239 -0
  74. package/dist/video-source-mediabunny.js.map +1 -0
  75. package/package.json +67 -0
package/dist/setup.js ADDED
@@ -0,0 +1,46 @@
1
+ import { setDefaultAudioSourceFactory, setDefaultFontLoader, setDefaultImageLoader, setDefaultVideoSourceFactory, } from "@smoove/core";
2
+ import { FontLibrary } from "skia-canvas";
3
+ import { nullAudioSourceFactory } from "./audio-source-null.js";
4
+ import { makeSkiaFontLoader } from "./font-loader.js";
5
+ import { loadImageNode } from "./image-loader.js";
6
+ import { registerServerMedia } from "./media-server.js";
7
+ import { installSkiaBackend } from "./skia.js";
8
+ import { nodeVideoSourceFactory, setVideoDecodeCap } from "./video-source-mediabunny.js";
9
+ const RENDERING_FLAG = "__KONVA_MOTION_RENDERING__";
10
+ let factoriesRegistered = false;
11
+ /** Register fonts with skia-canvas so `Text` nodes can use them (no DOM `@font-face`). */
12
+ export function registerFonts(fonts) {
13
+ if (!fonts)
14
+ return;
15
+ if (Array.isArray(fonts))
16
+ FontLibrary.use(fonts);
17
+ else
18
+ FontLibrary.use(fonts);
19
+ }
20
+ /**
21
+ * Install everything needed to render a `Composition` headlessly in Node:
22
+ * the konva skia backend, the global rendering flag, and Node-safe default
23
+ * video/audio source factories + image loader (so media nodes construct without
24
+ * a DOM). Idempotent — call it (or import `@smoove/renderer/register`)
25
+ * **before** constructing any composition.
26
+ */
27
+ export function setupServerRendering(opts = {}) {
28
+ installSkiaBackend();
29
+ registerServerMedia();
30
+ globalThis[RENDERING_FLAG] = true;
31
+ if (!factoriesRegistered) {
32
+ setDefaultVideoSourceFactory(opts.video ?? nodeVideoSourceFactory);
33
+ setDefaultAudioSourceFactory(nullAudioSourceFactory);
34
+ setDefaultImageLoader(loadImageNode);
35
+ setDefaultFontLoader(makeSkiaFontLoader(opts.fontCacheDir));
36
+ factoriesRegistered = true;
37
+ }
38
+ else if (opts.video) {
39
+ setDefaultVideoSourceFactory(opts.video);
40
+ }
41
+ if (opts.videoDecodeCap) {
42
+ setVideoDecodeCap(opts.videoDecodeCap.width, opts.videoDecodeCap.height);
43
+ }
44
+ registerFonts(opts.fonts);
45
+ }
46
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEzF,MAAM,cAAc,GAAG,4BAA4B,CAAC;AACpD,IAAI,mBAAmB,GAAG,KAAK,CAAC;AAEhC,0FAA0F;AAC1F,MAAM,UAAU,aAAa,CAAC,KAAmB;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;;QAC5C,WAAW,CAAC,GAAG,CAAC,KAAmD,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAqB,EAAE;IAC1D,kBAAkB,EAAE,CAAC;IACrB,mBAAmB,EAAE,CAAC;IACrB,UAAsC,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,4BAA4B,CAAC,IAAI,CAAC,KAAK,IAAI,sBAAsB,CAAC,CAAC;QACnE,4BAA4B,CAAC,sBAAsB,CAAC,CAAC;QACrD,qBAAqB,CAAC,aAAa,CAAC,CAAC;QACrC,oBAAoB,CAAC,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAC5D,mBAAmB,GAAG,IAAI,CAAC;IAC7B,CAAC;SAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3E,CAAC;IACD,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC"}
package/dist/skia.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import "konva/skia-backend";
2
+ /**
3
+ * Ensure the konva skia backend is installed. The install happens as a side
4
+ * effect of importing this module, so calling this is a no-op marker that
5
+ * guarantees the import ran. Idempotent and cheap.
6
+ */
7
+ export declare function installSkiaBackend(): void;
8
+ //# sourceMappingURL=skia.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skia.d.ts","sourceRoot":"","sources":["../src/skia.ts"],"names":[],"mappings":"AAKA,OAAO,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
package/dist/skia.js ADDED
@@ -0,0 +1,15 @@
1
+ // Side-effecting import: konva's skia backend monkey-patches
2
+ // `Konva.Util.createCanvasElement`/`createImageElement` to return skia-canvas
3
+ // objects, installs `global.DOMMatrix`/`Path2D`, and fixes the weak `ctx.canvas`
4
+ // reference. Importing this module installs the backend; it must run before any
5
+ // Konva canvas is created (i.e. before constructing a Composition).
6
+ import "konva/skia-backend";
7
+ /**
8
+ * Ensure the konva skia backend is installed. The install happens as a side
9
+ * effect of importing this module, so calling this is a no-op marker that
10
+ * guarantees the import ran. Idempotent and cheap.
11
+ */
12
+ export function installSkiaBackend() {
13
+ /* installed at import time */
14
+ }
15
+ //# sourceMappingURL=skia.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skia.js","sourceRoot":"","sources":["../src/skia.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,iFAAiF;AACjF,gFAAgF;AAChF,oEAAoE;AACpE,OAAO,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,8BAA8B;AAChC,CAAC"}
@@ -0,0 +1,153 @@
1
+ import type { Composition, VideoSourceFactory } from "@smoove/core";
2
+ import { type Quality } from "mediabunny";
3
+ /**
4
+ * Encode tuning. Mediabunny encoders are bitrate-oriented (no CRF): a value is
5
+ * either a target bitrate in bits/second or one of Mediabunny's resolution-aware
6
+ * {@link Quality} constants (`QUALITY_LOW` … `QUALITY_VERY_HIGH`).
7
+ */
8
+ export interface QualityConfig {
9
+ /** Target video bitrate (bits/second) or a Mediabunny quality constant. */
10
+ videoBitrate: number | Quality;
11
+ /** Target audio bitrate (bits/second) or a Mediabunny quality constant. */
12
+ audioBitrate: number | Quality;
13
+ }
14
+ export type QualityPreset = "low" | "medium" | "high" | "max";
15
+ export declare const QUALITY_PRESETS: Record<QualityPreset, QualityConfig>;
16
+ /** How a native-size frame is fitted into a different target resolution. */
17
+ export type Fit = "contain" | "cover";
18
+ export interface Resolution {
19
+ width: number;
20
+ height: number;
21
+ }
22
+ /** Fonts to register with skia-canvas before drawing text (no DOM `@font-face`). */
23
+ export type FontsOption = readonly string[] | Record<string, string | readonly string[]>;
24
+ /** Inclusive frame range `[from, to]`. */
25
+ export interface FrameRange {
26
+ from: number;
27
+ to: number;
28
+ }
29
+ export interface RenderProgress {
30
+ /** Frames encoded so far. */
31
+ frame: number;
32
+ /** Total frames in the render. */
33
+ total: number;
34
+ /** Throughput in encoded frames per second. */
35
+ fps: number;
36
+ etaSeconds?: number;
37
+ }
38
+ export interface RenderOptions {
39
+ /** Output file path. */
40
+ output: string;
41
+ /** Target resolution; defaults to the composition's native size. */
42
+ resolution?: Resolution;
43
+ /** Fit mode when `resolution` differs from native aspect. Default `"contain"`. */
44
+ fit?: Fit;
45
+ quality?: QualityPreset | QualityConfig;
46
+ /** Frame rate of the output; defaults to the composition's fps. */
47
+ fps?: number;
48
+ range?: FrameRange;
49
+ /** Output container. `"mp4"` (H.264 + AAC, default) or `"webm"` (VP9 + Opus). */
50
+ format?: "mp4" | "webm";
51
+ fonts?: FontsOption;
52
+ /** Drop all audio. */
53
+ mute?: boolean;
54
+ signal?: AbortSignal;
55
+ onProgress?: (progress: RenderProgress) => void;
56
+ }
57
+ export interface StreamOptions extends Omit<RenderOptions, "output"> {
58
+ /** Fragmented container for piping. Default `"mp4"`. */
59
+ format?: "mp4" | "webm";
60
+ }
61
+ export interface StillOptions {
62
+ frame: number;
63
+ /** Optional file to write; the PNG/JPEG buffer is always returned. */
64
+ output?: string;
65
+ resolution?: Resolution;
66
+ fit?: Fit;
67
+ type?: "png" | "jpeg";
68
+ /** JPEG quality 0..1. */
69
+ quality?: number;
70
+ fonts?: FontsOption;
71
+ }
72
+ export interface FrameOptions {
73
+ range?: FrameRange;
74
+ /** Reserved — frames are yielded at native size; resampling happens in the encoder. */
75
+ resolution?: Resolution;
76
+ fit?: Fit;
77
+ fonts?: FontsOption;
78
+ signal?: AbortSignal;
79
+ }
80
+ export interface RenderedFrame {
81
+ /** 0-based index within the render. */
82
+ index: number;
83
+ /** Absolute composition frame. */
84
+ frame: number;
85
+ /** Raw RGBA pixels, `width * height * 4` bytes. */
86
+ data: Buffer;
87
+ width: number;
88
+ height: number;
89
+ }
90
+ export interface RenderResult {
91
+ output: string;
92
+ width: number;
93
+ height: number;
94
+ frames: number;
95
+ durationInSeconds: number;
96
+ hasAudio: boolean;
97
+ }
98
+ export interface CompositionInfo {
99
+ fps: number;
100
+ durationInFrames: number;
101
+ width: number;
102
+ height: number;
103
+ durationInSeconds: number;
104
+ isRendering: boolean;
105
+ }
106
+ /** A point in a per-clip volume envelope; `time` is clip-relative seconds. */
107
+ export interface VolumeKeyframe {
108
+ time: number;
109
+ volume: number;
110
+ }
111
+ /** A coalesced run of per-frame audio samples for one source. */
112
+ export interface AudioClip {
113
+ id: string;
114
+ src: string;
115
+ /** First composition frame of the run (inclusive). */
116
+ startFrame: number;
117
+ /** Last composition frame of the run (inclusive). */
118
+ endFrame: number;
119
+ /** Source in-point in seconds (first sample's mediaTime). */
120
+ mediaInSeconds: number;
121
+ playbackRate: number;
122
+ /** Constant level, or a time-keyed envelope when the volume varies. */
123
+ volume: number | VolumeKeyframe[];
124
+ }
125
+ export interface SetupOptions {
126
+ /** Override the default server VideoSource factory. */
127
+ video?: VideoSourceFactory;
128
+ /** Fonts to register via skia-canvas `FontLibrary.use`. */
129
+ fonts?: FontsOption;
130
+ /**
131
+ * Directory for caching fonts that scene `Font` nodes load from remote URLs.
132
+ * Downloaded once and reused across frames and process runs. Defaults to
133
+ * `os.tmpdir()/smoove-fonts`.
134
+ */
135
+ fontCacheDir?: string;
136
+ /**
137
+ * Cap the decode/blit resolution of node video sources (clips larger are
138
+ * scaled down, preserving aspect; Konva upscales to the display box). An
139
+ * optional throughput/size knob for large background clips — Mediabunny decode
140
+ * is already memory-bounded. Omit for full-resolution decode.
141
+ */
142
+ videoDecodeCap?: {
143
+ width: number;
144
+ height: number;
145
+ };
146
+ }
147
+ export interface RenderToStreamResult {
148
+ stream: import("node:stream").Readable;
149
+ done: Promise<RenderResult>;
150
+ }
151
+ /** Internal helper alias. */
152
+ export type Comp = Composition;
153
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ import { QUALITY_HIGH, QUALITY_LOW, QUALITY_MEDIUM, QUALITY_VERY_HIGH, } from "mediabunny";
2
+ export const QUALITY_PRESETS = {
3
+ low: { videoBitrate: QUALITY_LOW, audioBitrate: 96_000 },
4
+ medium: { videoBitrate: QUALITY_MEDIUM, audioBitrate: 128_000 },
5
+ high: { videoBitrate: QUALITY_HIGH, audioBitrate: 192_000 },
6
+ max: { videoBitrate: QUALITY_VERY_HIGH, audioBitrate: 256_000 },
7
+ };
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,WAAW,EACX,cAAc,EACd,iBAAiB,GAElB,MAAM,YAAY,CAAC;AAgBpB,MAAM,CAAC,MAAM,eAAe,GAAyC;IACnE,GAAG,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE;IACxD,MAAM,EAAE,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE;IAC/D,IAAI,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE;IAC3D,GAAG,EAAE,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE;CAChE,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { VideoSource, VideoSourceFactory } from "@smoove/core";
2
+ type SeekMode = "precise" | "fast";
3
+ /** Cap the decode/blit resolution of node video sources (0,0 = uncapped). */
4
+ export declare function setVideoDecodeCap(maxWidth: number, maxHeight: number): void;
5
+ /**
6
+ * Server-side {@link VideoSource} backed by Mediabunny + node-av (FFmpeg C API).
7
+ * The Node analogue of core's browser `MediabunnyVideoSource`: a forward-only
8
+ * {@link VideoSampleSink} iterator decodes frames for the exact timestamp the
9
+ * frame clock asks for; each decoded {@link VideoSample} is copied (RGBA) onto a
10
+ * reused skia `Canvas` that serves as the drawable {@link element} for
11
+ * `Konva.Image`. Replaces the old `FfmpegVideoSource` (one ffmpeg child process
12
+ * per clip, raw-RGBA pipe, manual frame reassembly).
13
+ */
14
+ export declare class MediabunnyVideoSource implements VideoSource {
15
+ private _canvas;
16
+ private _ctx;
17
+ private _scratch;
18
+ private _scratchCtx;
19
+ private _imageData;
20
+ private _input;
21
+ private _sink;
22
+ private _ready;
23
+ private _disposed;
24
+ private readonly _readyCbs;
25
+ private readonly _frameCbs;
26
+ private _w;
27
+ private _h;
28
+ private _codedW;
29
+ private _codedH;
30
+ private _duration;
31
+ private _firstTs;
32
+ private _iter;
33
+ private _next;
34
+ private _curTs;
35
+ private _seeking;
36
+ private _pending;
37
+ load(src: string): Promise<void>;
38
+ get element(): CanvasImageSource | null;
39
+ get naturalWidth(): number;
40
+ get naturalHeight(): number;
41
+ get duration(): number;
42
+ get currentTime(): number;
43
+ get isReady(): boolean;
44
+ seek(timeSeconds: number, _mode?: SeekMode): Promise<void>;
45
+ private _drainSeek;
46
+ /** Land the owned canvas on the last frame whose start timestamp is <= `t`. */
47
+ private _satisfy;
48
+ private _restartIterator;
49
+ private _pull;
50
+ /** Copy a decoded frame (RGBA) onto the owned canvas and notify listeners. */
51
+ private _draw;
52
+ play(): Promise<void>;
53
+ pause(): void;
54
+ setMuted(_muted: boolean): void;
55
+ setVolume(_volume: number): void;
56
+ setPlaybackRate(_rate: number): void;
57
+ onReady(cb: () => void): () => void;
58
+ onFrame(cb: () => void): () => void;
59
+ destroy(): void;
60
+ }
61
+ export declare const nodeVideoSourceFactory: VideoSourceFactory;
62
+ export {};
63
+ //# sourceMappingURL=video-source-mediabunny.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-source-mediabunny.d.ts","sourceRoot":"","sources":["../src/video-source-mediabunny.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAKjF,KAAK,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAanC,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAG3E;AAED;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACvD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,UAAU,CAA0B;IAE5C,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO,CAAC,KAAK,CAAgC;IAE7C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAK;IAErB,OAAO,CAAC,KAAK,CAA2D;IACxE,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAA4B;IAE1C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAA+D;IAEzE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCtC,IAAI,OAAO,IAAI,iBAAiB,GAAG,IAAI,CAEtC;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,GAAE,QAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBvD,UAAU;IAgBxB,+EAA+E;YACjE,QAAQ;YAgBR,gBAAgB;YAUhB,KAAK;IAMnB,8EAA8E;YAChE,KAAK;IA0BnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAGrB,KAAK,IAAI,IAAI;IACb,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAC/B,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAChC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAEpC,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IASnC,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKnC,OAAO,IAAI,IAAI;CAmBhB;AAED,eAAO,MAAM,sBAAsB,EAAE,kBACR,CAAC"}
@@ -0,0 +1,239 @@
1
+ import { ALL_FORMATS, Input, VideoSampleSink } from "mediabunny";
2
+ import { Canvas, ImageData } from "skia-canvas";
3
+ import { makeInputSource } from "./media-input-source.js";
4
+ /** Reuse the current frame within a quarter of a 60fps tick before seeking. */
5
+ const SAME_FRAME_EPS = 1 / 240;
6
+ /** Forward jumps larger than this restart the decode iterator instead of decoding through. */
7
+ const BIGGEST_FORWARD_JUMP = 3;
8
+ // Optional decode-resolution cap (0 = uncapped). Mediabunny decode is memory-
9
+ // bounded (one reused canvas, cleared each frame), so this is now purely a
10
+ // throughput/size knob for large background clips, not a leak workaround.
11
+ let DECODE_MAX_W = 0;
12
+ let DECODE_MAX_H = 0;
13
+ /** Cap the decode/blit resolution of node video sources (0,0 = uncapped). */
14
+ export function setVideoDecodeCap(maxWidth, maxHeight) {
15
+ DECODE_MAX_W = Math.max(0, Math.floor(maxWidth));
16
+ DECODE_MAX_H = Math.max(0, Math.floor(maxHeight));
17
+ }
18
+ /**
19
+ * Server-side {@link VideoSource} backed by Mediabunny + node-av (FFmpeg C API).
20
+ * The Node analogue of core's browser `MediabunnyVideoSource`: a forward-only
21
+ * {@link VideoSampleSink} iterator decodes frames for the exact timestamp the
22
+ * frame clock asks for; each decoded {@link VideoSample} is copied (RGBA) onto a
23
+ * reused skia `Canvas` that serves as the drawable {@link element} for
24
+ * `Konva.Image`. Replaces the old `FfmpegVideoSource` (one ffmpeg child process
25
+ * per clip, raw-RGBA pipe, manual frame reassembly).
26
+ */
27
+ export class MediabunnyVideoSource {
28
+ _canvas = null;
29
+ _ctx = null;
30
+ _scratch = null;
31
+ _scratchCtx = null;
32
+ _imageData = null;
33
+ _input = null;
34
+ _sink = null;
35
+ _ready = false;
36
+ _disposed = false;
37
+ _readyCbs = new Set();
38
+ _frameCbs = new Set();
39
+ _w = 0; // blit (display) size
40
+ _h = 0;
41
+ _codedW = 0;
42
+ _codedH = 0;
43
+ _duration = 0;
44
+ _firstTs = 0;
45
+ _iter = null;
46
+ _next = null;
47
+ _curTs = Number.NEGATIVE_INFINITY;
48
+ _seeking = false;
49
+ _pending = null;
50
+ async load(src) {
51
+ const input = new Input({ formats: ALL_FORMATS, source: makeInputSource(src) });
52
+ this._input = input;
53
+ const track = await input.getPrimaryVideoTrack();
54
+ if (!track)
55
+ throw new Error(`[smoove] no video track in: ${src}`);
56
+ if (!(await track.canDecode())) {
57
+ throw new Error(`[smoove] cannot decode video track in: ${src}`);
58
+ }
59
+ if (this._disposed)
60
+ return;
61
+ const dw = await track.getDisplayWidth();
62
+ const dh = await track.getDisplayHeight();
63
+ let w = dw;
64
+ let h = dh;
65
+ if (DECODE_MAX_W > 0 && DECODE_MAX_H > 0 && (dw > DECODE_MAX_W || dh > DECODE_MAX_H)) {
66
+ const scale = Math.min(DECODE_MAX_W / dw, DECODE_MAX_H / dh);
67
+ w = Math.max(2, Math.round((dw * scale) / 2) * 2);
68
+ h = Math.max(2, Math.round((dh * scale) / 2) * 2);
69
+ }
70
+ this._w = w;
71
+ this._h = h;
72
+ this._duration = await track.computeDuration();
73
+ this._firstTs = await track.getFirstTimestamp();
74
+ this._canvas = new Canvas(w, h);
75
+ this._ctx = this._canvas.getContext("2d");
76
+ this._sink = new VideoSampleSink(track);
77
+ await this._satisfy(this._firstTs);
78
+ if (this._disposed)
79
+ return;
80
+ this._ready = true;
81
+ for (const cb of this._readyCbs)
82
+ cb();
83
+ }
84
+ get element() {
85
+ return this._ready ? this._canvas : null;
86
+ }
87
+ get naturalWidth() {
88
+ return this._w;
89
+ }
90
+ get naturalHeight() {
91
+ return this._h;
92
+ }
93
+ get duration() {
94
+ return this._duration;
95
+ }
96
+ get currentTime() {
97
+ return this._curTs === Number.NEGATIVE_INFINITY ? 0 : this._curTs;
98
+ }
99
+ get isReady() {
100
+ return this._ready;
101
+ }
102
+ seek(timeSeconds, _mode = "precise") {
103
+ const clamped = Math.max(this._firstTs, this._duration > 0 ? Math.min(this._duration, timeSeconds) : timeSeconds);
104
+ if (!this._seeking && Math.abs(this._curTs - clamped) <= SAME_FRAME_EPS) {
105
+ return Promise.resolve();
106
+ }
107
+ return new Promise((resolve) => {
108
+ if (this._pending) {
109
+ this._pending.time = clamped;
110
+ this._pending.resolvers.push(resolve);
111
+ }
112
+ else {
113
+ this._pending = { time: clamped, resolvers: [resolve] };
114
+ }
115
+ void this._drainSeek();
116
+ });
117
+ }
118
+ async _drainSeek() {
119
+ if (this._seeking || !this._pending)
120
+ return;
121
+ this._seeking = true;
122
+ while (this._pending) {
123
+ const { time, resolvers } = this._pending;
124
+ this._pending = null;
125
+ try {
126
+ await this._satisfy(time);
127
+ }
128
+ catch (err) {
129
+ if (!this._disposed)
130
+ console.error("[smoove] video seek failed:", err);
131
+ }
132
+ for (const r of resolvers)
133
+ r();
134
+ }
135
+ this._seeking = false;
136
+ }
137
+ /** Land the owned canvas on the last frame whose start timestamp is <= `t`. */
138
+ async _satisfy(t) {
139
+ if (!this._sink)
140
+ return;
141
+ if (t < this._curTs - SAME_FRAME_EPS || t > this._curTs + BIGGEST_FORWARD_JUMP || !this._iter) {
142
+ await this._restartIterator(t);
143
+ }
144
+ while (true) {
145
+ if (!this._next)
146
+ this._next = await this._pull();
147
+ if (this._next && this._next.timestamp <= t + SAME_FRAME_EPS) {
148
+ await this._draw(this._next);
149
+ this._next = null;
150
+ }
151
+ else {
152
+ break;
153
+ }
154
+ }
155
+ }
156
+ async _restartIterator(t) {
157
+ await this._iter?.return();
158
+ this._iter = this._sink?.samples(Math.max(0, t)) ?? null;
159
+ this._next?.close();
160
+ this._next = null;
161
+ this._curTs = Number.NEGATIVE_INFINITY;
162
+ const first = await this._pull();
163
+ if (first)
164
+ await this._draw(first);
165
+ }
166
+ async _pull() {
167
+ if (!this._iter)
168
+ return null;
169
+ const r = await this._iter.next();
170
+ return r.done ? null : r.value;
171
+ }
172
+ /** Copy a decoded frame (RGBA) onto the owned canvas and notify listeners. */
173
+ async _draw(sample) {
174
+ this._curTs = sample.timestamp;
175
+ const cw = sample.codedWidth;
176
+ const ch = sample.codedHeight;
177
+ if (!this._imageData || this._codedW !== cw || this._codedH !== ch) {
178
+ this._codedW = cw;
179
+ this._codedH = ch;
180
+ this._scratch = new Canvas(cw, ch);
181
+ this._scratchCtx = this._scratch.getContext("2d");
182
+ this._imageData = new ImageData(cw, ch);
183
+ }
184
+ await sample.copyTo(this._imageData.data, { format: "RGBA" });
185
+ sample.close();
186
+ const sctx = this._scratchCtx;
187
+ const ctx = this._ctx;
188
+ if (!sctx || !ctx)
189
+ return;
190
+ sctx.putImageData(this._imageData, 0, 0);
191
+ // Clear before blit: skia retains a native snapshot of prior content, so an
192
+ // uncleared draw leaks ~1 frame of RSS per frame for the process lifetime.
193
+ ctx.clearRect(0, 0, this._w, this._h);
194
+ if (this._scratch)
195
+ ctx.drawImage(this._scratch, 0, 0, this._w, this._h);
196
+ for (const cb of this._frameCbs)
197
+ cb();
198
+ }
199
+ // Pull-based: nothing self-plays. The frame clock drives `seek()` each tick.
200
+ play() {
201
+ return Promise.resolve();
202
+ }
203
+ pause() { }
204
+ setMuted(_muted) { }
205
+ setVolume(_volume) { }
206
+ setPlaybackRate(_rate) { }
207
+ onReady(cb) {
208
+ if (this._ready) {
209
+ cb();
210
+ return () => { };
211
+ }
212
+ this._readyCbs.add(cb);
213
+ return () => this._readyCbs.delete(cb);
214
+ }
215
+ onFrame(cb) {
216
+ this._frameCbs.add(cb);
217
+ return () => this._frameCbs.delete(cb);
218
+ }
219
+ destroy() {
220
+ this._disposed = true;
221
+ void this._iter?.return();
222
+ this._iter = null;
223
+ this._next?.close();
224
+ this._next = null;
225
+ this._input?.dispose();
226
+ this._input = null;
227
+ this._sink = null;
228
+ this._canvas = null;
229
+ this._ctx = null;
230
+ this._scratch = null;
231
+ this._scratchCtx = null;
232
+ this._imageData = null;
233
+ this._readyCbs.clear();
234
+ this._frameCbs.clear();
235
+ this._pending = null;
236
+ }
237
+ }
238
+ export const nodeVideoSourceFactory = (_env) => new MediabunnyVideoSource();
239
+ //# sourceMappingURL=video-source-mediabunny.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-source-mediabunny.js","sourceRoot":"","sources":["../src/video-source-mediabunny.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@smoove/renderer",
3
+ "version": "0.1.1",
4
+ "description": "Headless server renderer for smoove — rasterizes a Composition with skia-canvas and encodes to video via Mediabunny (node-av / FFmpeg C API).",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/smoove-dev/smoove.git",
9
+ "directory": "packages/renderer"
10
+ },
11
+ "homepage": "https://smoove.dev",
12
+ "bugs": "https://github.com/smoove-dev/smoove/issues",
13
+ "type": "module",
14
+ "main": "./dist/index.js",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ },
22
+ "./register": {
23
+ "types": "./dist/register.d.ts",
24
+ "import": "./dist/register.js"
25
+ },
26
+ "./gl": {
27
+ "types": "./dist/gl.d.ts",
28
+ "import": "./dist/gl.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "dependencies": {
35
+ "@mediabunny/server": "^1.49.0",
36
+ "mediabunny": "^1.49.0",
37
+ "skia-canvas": "^3.0.8"
38
+ },
39
+ "optionalDependencies": {
40
+ "gl": "^8.1.6"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^22.10.0",
44
+ "tsx": "^4.19.2",
45
+ "@smoove/transitions": "0.1.1"
46
+ },
47
+ "peerDependencies": {
48
+ "konva": ">=10",
49
+ "@smoove/core": "^0.1.1",
50
+ "@smoove/transitions": "^0.1.1"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@smoove/transitions": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "scripts": {
61
+ "build": "tsc -b",
62
+ "dev": "tsc -b --watch",
63
+ "clean": "rm -rf dist *.tsbuildinfo",
64
+ "example": "tsx examples/render-demo.ts",
65
+ "example:mixer": "tsx examples/audio-mixer.ts"
66
+ }
67
+ }