@smoove/core 0.2.0 → 0.3.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.
Files changed (90) hide show
  1. package/dist/engine/composition.d.ts.map +1 -1
  2. package/dist/engine/composition.js +1 -1
  3. package/dist/engine/composition.js.map +1 -1
  4. package/dist/engine/runtime-defaults.d.ts +5 -5
  5. package/dist/engine/runtime-defaults.d.ts.map +1 -1
  6. package/dist/engine/runtime-defaults.js +12 -9
  7. package/dist/engine/runtime-defaults.js.map +1 -1
  8. package/dist/engine/sequence.js +1 -1
  9. package/dist/engine/sequence.js.map +1 -1
  10. package/dist/index.d.ts +4 -10
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +5 -6
  13. package/dist/index.js.map +1 -1
  14. package/dist/layout/group.js +1 -1
  15. package/dist/layout/group.js.map +1 -1
  16. package/dist/layout/image.js +1 -1
  17. package/dist/layout/image.js.map +1 -1
  18. package/dist/layout/text/font.js +1 -1
  19. package/dist/layout/text/font.js.map +1 -1
  20. package/dist/layout/text/text.js +1 -1
  21. package/dist/layout/text/text.js.map +1 -1
  22. package/dist/markers.d.ts +43 -0
  23. package/dist/markers.d.ts.map +1 -0
  24. package/dist/markers.js +46 -0
  25. package/dist/markers.js.map +1 -0
  26. package/package.json +2 -3
  27. package/dist/media/audio/audio-driver.d.ts +0 -34
  28. package/dist/media/audio/audio-driver.d.ts.map +0 -1
  29. package/dist/media/audio/audio-driver.js +0 -2
  30. package/dist/media/audio/audio-driver.js.map +0 -1
  31. package/dist/media/audio/audio-for-preview.d.ts +0 -47
  32. package/dist/media/audio/audio-for-preview.d.ts.map +0 -1
  33. package/dist/media/audio/audio-for-preview.js +0 -232
  34. package/dist/media/audio/audio-for-preview.js.map +0 -1
  35. package/dist/media/audio/audio-for-rendering.d.ts +0 -16
  36. package/dist/media/audio/audio-for-rendering.d.ts.map +0 -1
  37. package/dist/media/audio/audio-for-rendering.js +0 -32
  38. package/dist/media/audio/audio-for-rendering.js.map +0 -1
  39. package/dist/media/audio/audio-source-browser.d.ts +0 -30
  40. package/dist/media/audio/audio-source-browser.d.ts.map +0 -1
  41. package/dist/media/audio/audio-source-browser.js +0 -139
  42. package/dist/media/audio/audio-source-browser.js.map +0 -1
  43. package/dist/media/audio/audio-source-mediabunny.d.ts +0 -45
  44. package/dist/media/audio/audio-source-mediabunny.d.ts.map +0 -1
  45. package/dist/media/audio/audio-source-mediabunny.js +0 -79
  46. package/dist/media/audio/audio-source-mediabunny.js.map +0 -1
  47. package/dist/media/audio/index.d.ts +0 -57
  48. package/dist/media/audio/index.d.ts.map +0 -1
  49. package/dist/media/audio/index.js +0 -176
  50. package/dist/media/audio/index.js.map +0 -1
  51. package/dist/media/audio/shared-audio-context.d.ts +0 -30
  52. package/dist/media/audio/shared-audio-context.d.ts.map +0 -1
  53. package/dist/media/audio/shared-audio-context.js +0 -68
  54. package/dist/media/audio/shared-audio-context.js.map +0 -1
  55. package/dist/media/audio/types.d.ts +0 -48
  56. package/dist/media/audio/types.d.ts.map +0 -1
  57. package/dist/media/audio/types.js +0 -2
  58. package/dist/media/audio/types.js.map +0 -1
  59. package/dist/media/media-marker.d.ts +0 -34
  60. package/dist/media/media-marker.d.ts.map +0 -1
  61. package/dist/media/media-marker.js +0 -34
  62. package/dist/media/media-marker.js.map +0 -1
  63. package/dist/media/video/driver.d.ts +0 -31
  64. package/dist/media/video/driver.d.ts.map +0 -1
  65. package/dist/media/video/driver.js +0 -3
  66. package/dist/media/video/driver.js.map +0 -1
  67. package/dist/media/video/index.d.ts +0 -66
  68. package/dist/media/video/index.d.ts.map +0 -1
  69. package/dist/media/video/index.js +0 -372
  70. package/dist/media/video/index.js.map +0 -1
  71. package/dist/media/video/types.d.ts +0 -36
  72. package/dist/media/video/types.d.ts.map +0 -1
  73. package/dist/media/video/types.js +0 -2
  74. package/dist/media/video/types.js.map +0 -1
  75. package/dist/media/video/video-for-preview.d.ts +0 -17
  76. package/dist/media/video/video-for-preview.d.ts.map +0 -1
  77. package/dist/media/video/video-for-preview.js +0 -30
  78. package/dist/media/video/video-for-preview.js.map +0 -1
  79. package/dist/media/video/video-for-rendering.d.ts +0 -17
  80. package/dist/media/video/video-for-rendering.d.ts.map +0 -1
  81. package/dist/media/video/video-for-rendering.js +0 -59
  82. package/dist/media/video/video-for-rendering.js.map +0 -1
  83. package/dist/media/video/video-source-browser.d.ts +0 -37
  84. package/dist/media/video/video-source-browser.d.ts.map +0 -1
  85. package/dist/media/video/video-source-browser.js +0 -171
  86. package/dist/media/video/video-source-browser.js.map +0 -1
  87. package/dist/media/video/video-source-mediabunny.d.ts +0 -69
  88. package/dist/media/video/video-source-mediabunny.d.ts.map +0 -1
  89. package/dist/media/video/video-source-mediabunny.js +0 -236
  90. package/dist/media/video/video-source-mediabunny.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The engine's general **node-marker contract**: string attrs stamped on Konva
3
+ * nodes so the engine and tooling can discover and classify nodes by string,
4
+ * without importing the node classes (which would create import cycles). A
5
+ * sibling of `layout/contract.ts` (the `KMLayoutNode` contract). Kept
6
+ * dependency-free (type-only Konva import) so `composition.ts`/`sequence.ts`
7
+ * can consume it from any layer.
8
+ */
9
+ import type Konva from "konva";
10
+ /** Set by every tickable media node — drives Sequence discovery + mixer registration. */
11
+ export declare const MEDIA_MARK = "__kmIsMedia";
12
+ /** Additionally set by `Video` — backs {@link isVideoNode}. */
13
+ export declare const VIDEO_MARK = "__kmIsVideo";
14
+ /** Additionally set by `Audio` — backs {@link isAudioNode}. */
15
+ export declare const AUDIO_MARK = "__kmIsAudio";
16
+ /**
17
+ * Set by non-media nodes that still want a per-frame `_kmTick` callback (e.g.
18
+ * `Text`'s typewriter). Discovered by `Sequence` alongside media, but NOT
19
+ * registered with the audio mixer.
20
+ */
21
+ export declare const TICK_MARK = "__kmIsTick";
22
+ /**
23
+ * Set by `Font` nodes. Walked by `Composition.add` so a scene-declared font is
24
+ * loaded (and buffered on) before playback — discovered by string so
25
+ * `composition.ts` need not import `layout/text/`.
26
+ */
27
+ export declare const FONT_MARK = "__kmIsFont";
28
+ /**
29
+ * Set by smoove's `Group` container — distinguishes an author-created grouping
30
+ * node from the internal `Konva.Group`s smoove builds inside `Text`, `Flex`,
31
+ * etc. Backs `isGroupNode`.
32
+ */
33
+ export declare const GROUP_MARK = "__kmIsGroup";
34
+ /**
35
+ * True if `node` is an audio media node. A pure mark check with no dependency
36
+ * on the `Audio` class, so it lives in core even though `Audio` ships in
37
+ * `@smoove/media`. `@smoove/renderer` uses it as a boolean media probe;
38
+ * `@smoove/media` re-exports a typed guard that narrows to its concrete `Audio`.
39
+ */
40
+ export declare function isAudioNode(node: Konva.Node): boolean;
41
+ /** True if `node` is a video media node. See {@link isAudioNode}. */
42
+ export declare function isVideoNode(node: Konva.Node): boolean;
43
+ //# sourceMappingURL=markers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../src/markers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,yFAAyF;AACzF,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC,+DAA+D;AAC/D,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC,+DAA+D;AAC/D,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC;;;;GAIG;AACH,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC;;;;GAIG;AACH,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC;;;;GAIG;AACH,eAAO,MAAM,UAAU,gBAAgB,CAAC;AAExC;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAErD;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAErD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The engine's general **node-marker contract**: string attrs stamped on Konva
3
+ * nodes so the engine and tooling can discover and classify nodes by string,
4
+ * without importing the node classes (which would create import cycles). A
5
+ * sibling of `layout/contract.ts` (the `KMLayoutNode` contract). Kept
6
+ * dependency-free (type-only Konva import) so `composition.ts`/`sequence.ts`
7
+ * can consume it from any layer.
8
+ */
9
+ /** Set by every tickable media node — drives Sequence discovery + mixer registration. */
10
+ export const MEDIA_MARK = "__kmIsMedia";
11
+ /** Additionally set by `Video` — backs {@link isVideoNode}. */
12
+ export const VIDEO_MARK = "__kmIsVideo";
13
+ /** Additionally set by `Audio` — backs {@link isAudioNode}. */
14
+ export const AUDIO_MARK = "__kmIsAudio";
15
+ /**
16
+ * Set by non-media nodes that still want a per-frame `_kmTick` callback (e.g.
17
+ * `Text`'s typewriter). Discovered by `Sequence` alongside media, but NOT
18
+ * registered with the audio mixer.
19
+ */
20
+ export const TICK_MARK = "__kmIsTick";
21
+ /**
22
+ * Set by `Font` nodes. Walked by `Composition.add` so a scene-declared font is
23
+ * loaded (and buffered on) before playback — discovered by string so
24
+ * `composition.ts` need not import `layout/text/`.
25
+ */
26
+ export const FONT_MARK = "__kmIsFont";
27
+ /**
28
+ * Set by smoove's `Group` container — distinguishes an author-created grouping
29
+ * node from the internal `Konva.Group`s smoove builds inside `Text`, `Flex`,
30
+ * etc. Backs `isGroupNode`.
31
+ */
32
+ export const GROUP_MARK = "__kmIsGroup";
33
+ /**
34
+ * True if `node` is an audio media node. A pure mark check with no dependency
35
+ * on the `Audio` class, so it lives in core even though `Audio` ships in
36
+ * `@smoove/media`. `@smoove/renderer` uses it as a boolean media probe;
37
+ * `@smoove/media` re-exports a typed guard that narrows to its concrete `Audio`.
38
+ */
39
+ export function isAudioNode(node) {
40
+ return node.getAttr(AUDIO_MARK) === true;
41
+ }
42
+ /** True if `node` is a video media node. See {@link isAudioNode}. */
43
+ export function isVideoNode(node) {
44
+ return node.getAttr(VIDEO_MARK) === true;
45
+ }
46
+ //# sourceMappingURL=markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.js","sourceRoot":"","sources":["../src/markers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,yFAAyF;AACzF,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AACxC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AACxC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AACxC;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;AACtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;AACtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AAExC;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAgB;IAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;AAC3C,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,WAAW,CAAC,IAAgB;IAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;AAC3C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smoove/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "A timeline-driven animation engine for Konva. Runs in the browser or on the server and renders to any target.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -28,8 +28,7 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "bezier-easing": "^2.1.0",
31
- "flexily": "^0.7.1",
32
- "mediabunny": "^1.49.0"
31
+ "flexily": "^0.7.1"
33
32
  },
34
33
  "peerDependencies": {
35
34
  "konva": ">=10"
@@ -1,34 +0,0 @@
1
- import type { Composition } from "../../engine/composition.js";
2
- import type { MediaTiming } from "../media-time.js";
3
- import type { AudioSource } from "./audio-source.js";
4
- /**
5
- * What an audio driver needs from the host {@link Audio}: the media source, the
6
- * resolved timing, the owning composition (for play state + asset collection),
7
- * the source identity, and getters for the effective audio level so a render
8
- * driver can record it. No `redraw` — audio paints nothing.
9
- */
10
- export type AudioDriverContext = {
11
- readonly source: AudioSource;
12
- readonly timing: MediaTiming;
13
- readonly comp: Composition;
14
- readonly id: string;
15
- readonly src: string;
16
- /** Effective level (master × intrinsic), 0..1, at the current frame. */
17
- effectiveVolume(): number;
18
- /** Effective mute (masterMuted || intrinsicMuted) at the current frame. */
19
- effectiveMuted(): boolean;
20
- };
21
- /**
22
- * Strategy that maps the composition's current frame onto the audio. Mirrors
23
- * {@link VideoDriver}: a realtime preview driver and a deterministic render
24
- * driver (which collects assets rather than playing).
25
- */
26
- export interface AudioDriver {
27
- /** Called by Sequence each tick while the audio is on-stage (`localFrame` = frame - sequence.from). */
28
- tick(localFrame: number): void;
29
- /** Called by Sequence when the audio leaves range. */
30
- deactivate(): void;
31
- /** Release any subscriptions; called on `Audio.destroy()`. */
32
- dispose(): void;
33
- }
34
- //# sourceMappingURL=audio-driver.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-driver.d.ts","sourceRoot":"","sources":["../../../src/media/audio/audio-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,eAAe,IAAI,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,cAAc,IAAI,OAAO,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,uGAAuG;IACvG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,sDAAsD;IACtD,UAAU,IAAI,IAAI,CAAC;IACnB,8DAA8D;IAC9D,OAAO,IAAI,IAAI,CAAC;CACjB"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=audio-driver.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-driver.js","sourceRoot":"","sources":["../../../src/media/audio/audio-driver.ts"],"names":[],"mappings":""}
@@ -1,47 +0,0 @@
1
- import type { AudioDriver, AudioDriverContext } from "./audio-driver.js";
2
- /**
3
- * Realtime preview driver for a **pull-based** audio source (Mediabunny +
4
- * WebCodecs). Nothing self-plays: while the composition is playing, a pump
5
- * decodes buffers from the source's {@link AudioBufferSink} and schedules them on
6
- * the shared {@link AudioContext}, anchoring the timeline clock to the context
7
- * clock so audio stays locked to the frame clock. Pausing or scrubbing stops the
8
- * pump (no audio while paused). A seek mid-playback re-anchors and reschedules.
9
- *
10
- * The clock works in **unwrapped** media time (monotonic, ignoring loop wrap), so
11
- * a looping clip schedules iteration after iteration seamlessly and seek
12
- * detection stays correct across the loop boundary.
13
- */
14
- export declare class PreviewAudioDriver implements AudioDriver {
15
- private readonly ctx;
16
- private readonly _shared;
17
- private _gain;
18
- private readonly _nodes;
19
- private _wasActive;
20
- private _lastLocalFrame;
21
- private _pumpToken;
22
- private _anchored;
23
- private _anchorCtxTime;
24
- private _anchorUnwrapped;
25
- private _effectiveRate;
26
- private readonly _unsubs;
27
- constructor(ctx: AudioDriverContext);
28
- tick(localFrame: number): void;
29
- deactivate(): void;
30
- dispose(): void;
31
- private _maybeStart;
32
- /** True if the audio clock has drifted from the playhead — i.e. a seek happened. */
33
- private _seekDetected;
34
- private _ensureGain;
35
- private _applyGain;
36
- private _startPump;
37
- /**
38
- * Decoded buffers tagged with unwrapped media time, from `anchorUnwrapped`
39
- * onward. Non-looping clips stream once to the trim end; looping clips replay
40
- * the `[trimBefore, trimAfter)` segment forever (offsetting each iteration), so
41
- * the consumer just keeps scheduling. Back-pressured by the consumer's awaits.
42
- */
43
- private _stream;
44
- private _stop;
45
- private _stopNodes;
46
- }
47
- //# sourceMappingURL=audio-for-preview.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-for-preview.d.ts","sourceRoot":"","sources":["../../../src/media/audio/audio-for-preview.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAqBzE;;;;;;;;;;;GAWG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IAiBxC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAhBhC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAE3D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAK;IAG5B,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAE3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAEpB,GAAG,EAAE,kBAAkB;IAgBpD,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAiB9B,UAAU,IAAI,IAAI;IAKlB,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,WAAW;IAOnB,oFAAoF;IACpF,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,UAAU;YAMJ,UAAU;IAgExB;;;;;OAKG;YACY,OAAO;IAsCtB,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,UAAU;CAYnB"}
@@ -1,232 +0,0 @@
1
- import { isSchedulable } from "./audio-source-mediabunny.js";
2
- import { getSharedAudioContext } from "./shared-audio-context.js";
3
- /** Keep roughly this many seconds of audio scheduled ahead of the context clock. */
4
- const SCHEDULE_AHEAD = 1.0;
5
- /** Decode this much lead-in before the start point so the decoder is primed. */
6
- const PRIMING = 0.25;
7
- /** Re-anchor (restart the pump) when the playhead diverges from the audio clock by more than this. */
8
- const SEEK_THRESHOLD = 0.15;
9
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
10
- /** Unwrapped media time (seconds) for a local frame — monotonic, ignores loop wrap. */
11
- function unwrappedMedia(localFrame, timing) {
12
- return (timing.trimBefore + localFrame * timing.playbackRate) / timing.fps;
13
- }
14
- /**
15
- * Realtime preview driver for a **pull-based** audio source (Mediabunny +
16
- * WebCodecs). Nothing self-plays: while the composition is playing, a pump
17
- * decodes buffers from the source's {@link AudioBufferSink} and schedules them on
18
- * the shared {@link AudioContext}, anchoring the timeline clock to the context
19
- * clock so audio stays locked to the frame clock. Pausing or scrubbing stops the
20
- * pump (no audio while paused). A seek mid-playback re-anchors and reschedules.
21
- *
22
- * The clock works in **unwrapped** media time (monotonic, ignoring loop wrap), so
23
- * a looping clip schedules iteration after iteration seamlessly and seek
24
- * detection stays correct across the loop boundary.
25
- */
26
- export class PreviewAudioDriver {
27
- ctx;
28
- _shared;
29
- _gain = null;
30
- _nodes = new Set();
31
- _wasActive = false;
32
- _lastLocalFrame = 0;
33
- // Pump identity (cancels a superseded pump) + the timeline↔context clock anchor.
34
- _pumpToken = null;
35
- _anchored = false;
36
- _anchorCtxTime = 0;
37
- _anchorUnwrapped = 0;
38
- _effectiveRate = 1;
39
- _unsubs = [];
40
- constructor(ctx) {
41
- this.ctx = ctx;
42
- this._shared = getSharedAudioContext(ctx.comp);
43
- this._unsubs.push(ctx.comp.isPlaying.subscribe((playing) => {
44
- if (playing)
45
- this._maybeStart(this._lastLocalFrame);
46
- else
47
- this._stop();
48
- }));
49
- // A rate change re-anchors so the new speed takes effect from here on.
50
- this._unsubs.push(ctx.comp.playbackRate.subscribe(() => {
51
- if (ctx.comp.isPlaying.get())
52
- this._maybeStart(this._lastLocalFrame);
53
- }));
54
- }
55
- tick(localFrame) {
56
- this._lastLocalFrame = localFrame;
57
- const { source, comp } = this.ctx;
58
- if (!source.isReady || !isSchedulable(source))
59
- return;
60
- const wasActive = this._wasActive;
61
- this._wasActive = true;
62
- if (comp.isPlaying.get()) {
63
- this._applyGain();
64
- if (this._pumpToken === null || !wasActive || this._seekDetected(localFrame)) {
65
- this._startPump(source, localFrame);
66
- }
67
- }
68
- else {
69
- this._stop();
70
- }
71
- }
72
- deactivate() {
73
- this._wasActive = false;
74
- this._stop();
75
- }
76
- dispose() {
77
- for (const u of this._unsubs)
78
- u();
79
- this._unsubs.length = 0;
80
- this._stop();
81
- this._gain?.disconnect();
82
- this._gain = null;
83
- }
84
- _maybeStart(localFrame) {
85
- const { source } = this.ctx;
86
- if (this._wasActive && source.isReady && isSchedulable(source)) {
87
- this._startPump(source, localFrame);
88
- }
89
- }
90
- /** True if the audio clock has drifted from the playhead — i.e. a seek happened. */
91
- _seekDetected(localFrame) {
92
- if (!this._anchored)
93
- return false;
94
- const predicted = this._anchorUnwrapped + (this._shared.now() - this._anchorCtxTime) * this._effectiveRate;
95
- const actual = unwrappedMedia(localFrame, this.ctx.timing);
96
- return Math.abs(predicted - actual) > SEEK_THRESHOLD;
97
- }
98
- _ensureGain() {
99
- if (!this._gain)
100
- this._gain = this._shared.createChannelGain();
101
- return this._gain;
102
- }
103
- _applyGain() {
104
- const gain = this._ensureGain();
105
- if (!gain)
106
- return;
107
- gain.gain.value = this.ctx.effectiveMuted() ? 0 : this.ctx.effectiveVolume();
108
- }
109
- async _startPump(source, fromLocalFrame) {
110
- const token = {};
111
- this._pumpToken = token;
112
- this._anchored = false;
113
- this._stopNodes();
114
- const sink = source.sink;
115
- if (!sink)
116
- return;
117
- await this._shared.resume();
118
- if (token !== this._pumpToken)
119
- return;
120
- const ac = this._shared.context;
121
- if (!ac)
122
- return;
123
- const gain = this._ensureGain();
124
- if (!gain)
125
- return;
126
- this._applyGain();
127
- const effRate = this.ctx.timing.playbackRate * this.ctx.comp.playbackRate.get();
128
- if (effRate <= 0)
129
- return; // reverse playback has no meaningful audio (documented)
130
- const anchorUnwrapped = unwrappedMedia(fromLocalFrame, this.ctx.timing);
131
- this._anchorCtxTime = ac.currentTime;
132
- this._anchorUnwrapped = anchorUnwrapped;
133
- this._effectiveRate = effRate;
134
- this._anchored = true;
135
- try {
136
- for await (const { buffer, startUnwrapped } of this._stream(sink, anchorUnwrapped)) {
137
- if (token !== this._pumpToken)
138
- break;
139
- const desiredUnwrapped = Math.max(startUnwrapped, anchorUnwrapped);
140
- let when = this._anchorCtxTime + (desiredUnwrapped - anchorUnwrapped) / effRate;
141
- // Throttle: stay ~SCHEDULE_AHEAD seconds ahead so we don't queue the file.
142
- while (when - ac.currentTime > SCHEDULE_AHEAD) {
143
- await sleep(120);
144
- if (token !== this._pumpToken)
145
- return;
146
- }
147
- let offset = desiredUnwrapped - startUnwrapped;
148
- if (when < ac.currentTime) {
149
- // Slightly late — start immediately and advance into the buffer.
150
- offset += (ac.currentTime - when) * effRate;
151
- when = ac.currentTime;
152
- }
153
- if (offset >= buffer.duration)
154
- continue; // fully behind the playhead — skip
155
- const node = ac.createBufferSource();
156
- node.buffer = buffer;
157
- node.playbackRate.value = effRate;
158
- node.connect(gain);
159
- node.onended = () => {
160
- this._nodes.delete(node);
161
- try {
162
- node.disconnect();
163
- }
164
- catch { }
165
- };
166
- node.start(when, offset);
167
- this._nodes.add(node);
168
- }
169
- }
170
- catch (err) {
171
- if (token === this._pumpToken)
172
- console.warn("[smoove] audio pump error:", err);
173
- }
174
- }
175
- /**
176
- * Decoded buffers tagged with unwrapped media time, from `anchorUnwrapped`
177
- * onward. Non-looping clips stream once to the trim end; looping clips replay
178
- * the `[trimBefore, trimAfter)` segment forever (offsetting each iteration), so
179
- * the consumer just keeps scheduling. Back-pressured by the consumer's awaits.
180
- */
181
- async *_stream(sink, anchorUnwrapped) {
182
- const t = this.ctx.timing;
183
- const wrap = (item, startUnwrapped) => ({
184
- buffer: item.buffer,
185
- startUnwrapped,
186
- });
187
- const loopLenFrames = t.trimAfter !== undefined ? t.trimAfter - t.trimBefore : 0;
188
- if (!t.loop || t.trimAfter === undefined || loopLenFrames <= 0) {
189
- // Single pass to the trim end (or natural end).
190
- const endMedia = t.trimAfter !== undefined ? t.trimAfter / t.fps : undefined;
191
- const start = Math.max(0, anchorUnwrapped - PRIMING);
192
- for await (const item of sink.buffers(start, endMedia)) {
193
- yield wrap(item, item.timestamp);
194
- }
195
- return;
196
- }
197
- // Looping: segment [segStart, segEnd) in source seconds.
198
- const segStart = t.trimBefore / t.fps;
199
- const segEnd = t.trimAfter / t.fps;
200
- const loopDur = segEnd - segStart;
201
- const kStart = Math.floor((anchorUnwrapped - segStart) / loopDur);
202
- const posInSeg = anchorUnwrapped - (segStart + kStart * loopDur);
203
- for (let k = kStart;; k++) {
204
- const base = segStart + k * loopDur;
205
- const fetchFrom = k === kStart ? segStart + posInSeg : segStart;
206
- for await (const item of sink.buffers(Math.max(0, fetchFrom - PRIMING), segEnd)) {
207
- // unwrapped start of this buffer within iteration k
208
- yield wrap(item, base + (item.timestamp - segStart));
209
- }
210
- }
211
- }
212
- _stop() {
213
- this._pumpToken = null;
214
- this._anchored = false;
215
- this._stopNodes();
216
- }
217
- _stopNodes() {
218
- for (const node of this._nodes) {
219
- node.onended = null;
220
- try {
221
- node.stop();
222
- }
223
- catch { }
224
- try {
225
- node.disconnect();
226
- }
227
- catch { }
228
- }
229
- this._nodes.clear();
230
- }
231
- }
232
- //# sourceMappingURL=audio-for-preview.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-for-preview.js","sourceRoot":"","sources":["../../../src/media/audio/audio-for-preview.ts"],"names":[],"mappings":"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"}
@@ -1,16 +0,0 @@
1
- import type { AudioDriver, AudioDriverContext } from "./audio-driver.js";
2
- /**
3
- * Deterministic, non-playing audio driver for offline rendering. The engine
4
- * captures canvas pixels frame-by-frame and has no in-engine audio encoder, so
5
- * decoding/playing audio during render buys nothing. Instead each tick records
6
- * an {@link AudioAsset} on the composition — the seam where a future ffmpeg
7
- * audio-mux pass reads `comp.getAudioAssets()` to assemble the audio track.
8
- */
9
- export declare class RenderingAudioDriver implements AudioDriver {
10
- private readonly ctx;
11
- constructor(ctx: AudioDriverContext);
12
- tick(localFrame: number): void;
13
- deactivate(): void;
14
- dispose(): void;
15
- }
16
- //# sourceMappingURL=audio-for-rendering.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-for-rendering.d.ts","sourceRoot":"","sources":["../../../src/media/audio/audio-for-rendering.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEzE;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,WAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,kBAAkB;IAKpD,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAc9B,UAAU,IAAI,IAAI;IAElB,OAAO,IAAI,IAAI;CAChB"}
@@ -1,32 +0,0 @@
1
- import { getMediaTime } from "../media-time.js";
2
- /**
3
- * Deterministic, non-playing audio driver for offline rendering. The engine
4
- * captures canvas pixels frame-by-frame and has no in-engine audio encoder, so
5
- * decoding/playing audio during render buys nothing. Instead each tick records
6
- * an {@link AudioAsset} on the composition — the seam where a future ffmpeg
7
- * audio-mux pass reads `comp.getAudioAssets()` to assemble the audio track.
8
- */
9
- export class RenderingAudioDriver {
10
- ctx;
11
- constructor(ctx) {
12
- this.ctx = ctx;
13
- // Never audible during render.
14
- ctx.source.setMuted(true);
15
- }
16
- tick(localFrame) {
17
- const { comp, timing } = this.ctx;
18
- const mediaTime = getMediaTime(localFrame, timing);
19
- comp._collectAudioAsset({
20
- id: this.ctx.id,
21
- src: this.ctx.src,
22
- frame: comp.frame.get(),
23
- mediaTime,
24
- volume: this.ctx.effectiveVolume(),
25
- muted: this.ctx.effectiveMuted(),
26
- playbackRate: timing.playbackRate,
27
- });
28
- }
29
- deactivate() { }
30
- dispose() { }
31
- }
32
- //# sourceMappingURL=audio-for-rendering.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-for-rendering.js","sourceRoot":"","sources":["../../../src/media/audio/audio-for-rendering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD;;;;;;GAMG;AACH,MAAM,OAAO,oBAAoB;IACF;IAA7B,YAA6B,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;QAClD,+BAA+B;QAC/B,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,UAAkB;QACrB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;QAClC,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,kBAAkB,CAAC;YACtB,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE;YACf,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACvB,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE;YAClC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE;YAChC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC;IACL,CAAC;IAED,UAAU,KAAU,CAAC;IAErB,OAAO,KAAU,CAAC;CACnB"}
@@ -1,30 +0,0 @@
1
- import type { AudioSource, SeekMode } from "./audio-source.js";
2
- /**
3
- * Preview-mode {@link AudioSource}: wraps an `HTMLAudioElement` and drives it in
4
- * realtime. Ported from {@link BrowserVideoSource} minus the drawable/rvfc bits
5
- * (audio produces no frames). A server renderer injects a different source via
6
- * `AudioConfig.sourceFactory`.
7
- */
8
- export declare class BrowserAudioSource implements AudioSource {
9
- private readonly _el;
10
- private _ready;
11
- private readonly _readyCbs;
12
- private _seeking;
13
- private _pending;
14
- constructor();
15
- load(src: string): Promise<void>;
16
- get duration(): number;
17
- get currentTime(): number;
18
- get isReady(): boolean;
19
- seek(timeSeconds: number, mode?: SeekMode): Promise<void>;
20
- /** Issue the pending seek if none is in flight; chains the latest target after each completes. */
21
- private _drainSeek;
22
- play(): Promise<void>;
23
- pause(): void;
24
- setMuted(muted: boolean): void;
25
- setVolume(volume: number): void;
26
- setPlaybackRate(rate: number): void;
27
- onReady(cb: () => void): () => void;
28
- destroy(): void;
29
- }
30
- //# sourceMappingURL=audio-source-browser.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"audio-source-browser.d.ts","sourceRoot":"","sources":["../../../src/media/audio/audio-source-browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAM/D;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAKnD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAA+E;;IAa/F,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBhC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,QAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpE,kGAAkG;IAClG,OAAO,CAAC,UAAU;IA6BlB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,KAAK,IAAI,IAAI;IAIb,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAInC,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IASnC,OAAO,IAAI,IAAI;CAQhB"}