@cutcraft/player 0.0.0-stage → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +61 -2
- package/dist/engine.d.mts +2 -0
- package/dist/engine.mjs +1 -0
- package/dist/index.d.mts +327 -0
- package/dist/index.mjs +3301 -0
- package/dist/render-DA1KFyei.mjs +3176 -0
- package/dist/warn-GHM3SBI2.d.mts +892 -0
- package/fonts.css +23 -0
- package/package.json +74 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bohdan Snisar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center"><img src="https://raw.githubusercontent.com/prefix-tree/cutcraft/main/docs/public/logo.svg" width="64" alt="CutCraft"></p>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# @cutcraft/player
|
|
4
|
+
|
|
5
|
+
Plays a [CutCraft](https://prefix-tree.github.io/cutcraft/) video file in the browser. Footage is decoded with
|
|
6
|
+
WebCodecs through [mediabunny](https://mediabunny.dev) and drawn on one canvas, overlays are React DOM on top of it,
|
|
7
|
+
and Web Audio mixes the sound and keeps the time.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @cutcraft/player @cutcraft/kit react react-dom
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { collectModule, resolve } from "@cutcraft/kit";
|
|
15
|
+
import { Player } from "@cutcraft/player";
|
|
16
|
+
import "@cutcraft/player/fonts.css";
|
|
17
|
+
import * as file from "./video";
|
|
18
|
+
|
|
19
|
+
const state = resolve(collectModule(file), manifest);
|
|
20
|
+
|
|
21
|
+
<Player state={state} element={file.default(file.defaults)} media={{ interview: blob, bed: "/bed.ogg" }} controls />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`media` maps asset ids to Blobs or URLs, or you can pass your own `MediaResolver`. `element` is the rendered file; the
|
|
25
|
+
player needs it to draw what is inside each `<Layer>`.
|
|
26
|
+
|
|
27
|
+
## What you get
|
|
28
|
+
|
|
29
|
+
- Frame-exact seeking. `seekTo(t)` draws the frame for `t` whether the player is paused or playing.
|
|
30
|
+
- Smooth scrubbing and trimming. A drag repaints from frames already decoded, then fetches the exact frame once the
|
|
31
|
+
pointer rests.
|
|
32
|
+
- Playback from 0.25× to 4× and looped, with speed ramps and freeze frames and their sound.
|
|
33
|
+
- A clock that does not drift: time comes from `AudioContext.currentTime`.
|
|
34
|
+
- Every overlay carries `data-el` and `data-kind`, and the root carries `data-time` and `data-frame`, so tests and
|
|
35
|
+
agents can find things on screen.
|
|
36
|
+
- `captureSheet(times, { columns })` returns a labelled contact sheet of frames, a quick way to check a cut without
|
|
37
|
+
exporting it.
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
`<Player>` takes `state`, `element`, `media`, `controls`, `loop`, `autoPlay`, `initiallyMuted`, `playbackRate`, `fit`,
|
|
42
|
+
`onError` and `onFrame`, and exposes a `PlayerRef`. Hooks: `usePlayer`, `useCompositionTime`, `useCompositionFrame`, `useLayerT`.
|
|
43
|
+
Mounting a player makes the kit's `useT()` and `useLayer()` return the current time.
|
|
44
|
+
|
|
45
|
+
`PlayerCore` is the same player without React: `play`, `pause`, `toggle`, `seekTo`, `seekToFrame`, `renderFrame`,
|
|
46
|
+
`captureSheet`, `getCurrentTime`, `getCurrentFrame`, `isPlaying`, `duration`, `playbackRate`, `loop`, `muted`,
|
|
47
|
+
`volume`, `setState`, `attachCanvas`, `subscribeTime`, `dispose`, and the events `frameupdate`, `play`, `pause`,
|
|
48
|
+
`seeked`, `ended`, `ratechange`, `volumechange` and `error`. Every browser dependency (clock, audio output, canvas,
|
|
49
|
+
decoders) can be swapped out, which is how its tests run in jsdom.
|
|
50
|
+
|
|
51
|
+
## What it draws
|
|
52
|
+
|
|
53
|
+
Every transition, effect and animation preset the kit accepts: a type the player does not draw is not offered. The few
|
|
54
|
+
remaining limits are in [What renders](https://prefix-tree.github.io/cutcraft/reference/rendering), and the kit's lint
|
|
55
|
+
flags them in the file.
|
|
56
|
+
|
|
57
|
+
## Docs
|
|
58
|
+
|
|
59
|
+
- [Player](https://prefix-tree.github.io/cutcraft/guide/player) and the [API reference](https://prefix-tree.github.io/cutcraft/reference/api)
|
|
60
|
+
- [Free code](https://prefix-tree.github.io/cutcraft/guide/free-code)
|
|
61
|
+
|
|
62
|
+
MIT licensed.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { $ as motionAt, $t as MAX_OPEN_INPUTS, A as GainPoint, An as PlayerErrorEvent, At as ErrorFrameSource, B as buildFramePlan, Bt as DecodeMode, C as EASING_FN, Cn as EnvelopePoint, Ct as MediabunnyFrameSource, D as OVERLAY_KINDS, Dn as FrameSourceInfo, Dt as mediabunnyAudioSourceFactory, E as keyframedValue, En as FrameSourceFactory, Et as MediabunnyAudioSource, F as DrawOp, Ft as FontFaceSource, G as trackItems, Gt as AUDIO_PRIME_S, H as TransitionRole, Ht as AssetSources, I as FramePlan, It as addFontFaces, J as GraphicAnimation, Jt as ENVELOPE_STEP_S, K as visiblePlacements, Kt as DUCK_ATTACK_S, L as MaskSpec, Lt as loadFileFonts, M as buildGainEnvelope, Mn as ScheduledSource, Mt as ImageFrameSource, N as duckIntervals, Nt as copyFrame, O as backdropTracks, On as MediaHandle, Ot as MediabunnyInputs, P as BackgroundGradient, Pt as defaultCreateCanvas, Q as effect, Qt as LOOKAHEAD_S, R as ResolveNested, Rt as DecoderPool, S as timecode, Sn as Ctx2D, St as toResolver, T as hasKeyframes, Tn as FrameSource, Tt as mediabunnyFrameSourceFactory, U as VisibleItem, Ut as AUDIO_CACHE_S, V as compositionBackground, Vt as AssetSourceDeps, W as isVisibleAt, Wt as AUDIO_CHUNK_S, X as STILL, Xt as FRAME_WAIT_MS, Y as Motion, Yt as FRAME_EPS, Z as combine, Zt as INPUT_IDLE_CLOSE_S, _ as frameTime, _n as AudioSource, _t as PostEffect, a as backgroundCss, an as QUEUE_MAX, at as animatedTransform, b as nestedSourceTime, bn as Clock, bt as postEffects, c as paintBackground, cn as REVERSE_WINDOW_S, ct as fitRect, d as traceMask, dn as SETTLE_MS, dt as multiply, en as MAX_RATE, et as Box, f as Compositor, fn as UNMOUNT_BEHIND_S, ft as rotate, g as frameIndex, gn as AudioOutput, gt as FilterResult, h as makeNestedResolver, hn as AnyCanvas, ht as translate, i as PaintInputs, in as PLAY_PRIME_TIMEOUT_MS, it as Matrix2D, j as buildAudioPlan, jn as PlayerEvents, jt as ImageFrame, k as AudioOccurrence, kn as MediaResolver, kt as ErrorFrame, l as setMatrix, ln as SCHEDULER_MS, lt as layoutRect, m as TickOptions, mn as PerformanceClock, mt as transformMatrix, n as devWarn, nn as MOUNT_AHEAD_S, nt as IDENTITY, o as backgroundFill, on as QUEUE_TARGET, ot as boundsOf, p as CompositorDeps, pn as ManualClock, pt as scaleM, q as ClipRect, qt as DUCK_RELEASE_S, r as CanvasPainter, rn as PICK_EPS, rt as Layout, s as coversCanvas, sn as REVERSE_WINDOW_FRAMES, st as cssTransform, t as captureWarnings, tn as MIN_RATE, tt as DrawRect, u as roundedRect, un as SEEK_MODE_SPEED, ut as matrixToCss, v as layerClock, vn as AudioSourceFactory, vt as filterString, w as ease, wn as Frame, wt as SampleFrame, x as placementSourceTime, xn as CreateCanvas, xt as fromMap, y as localT, yn as AudioSourceInfo, yt as paramsAt, z as blendOf, zt as ClipDecoder } from "./warn-GHM3SBI2.mjs";
|
|
2
|
+
export { AUDIO_CACHE_S, AUDIO_CHUNK_S, AUDIO_PRIME_S, AnyCanvas, AssetSourceDeps, AssetSources, AudioOccurrence, AudioOutput, AudioSource, AudioSourceFactory, AudioSourceInfo, BackgroundGradient, Box, CanvasPainter, ClipDecoder, ClipRect, Clock, Compositor, CompositorDeps, CreateCanvas, Ctx2D, DUCK_ATTACK_S, DUCK_RELEASE_S, DecodeMode, DecoderPool, DrawOp, DrawRect, EASING_FN, ENVELOPE_STEP_S, EnvelopePoint, ErrorFrame, ErrorFrameSource, FRAME_EPS, FRAME_WAIT_MS, FilterResult, FontFaceSource, Frame, FramePlan, FrameSource, FrameSourceFactory, FrameSourceInfo, GainPoint, GraphicAnimation, IDENTITY, INPUT_IDLE_CLOSE_S, ImageFrame, ImageFrameSource, LOOKAHEAD_S, Layout, MAX_OPEN_INPUTS, MAX_RATE, MIN_RATE, MOUNT_AHEAD_S, ManualClock, MaskSpec, Matrix2D, MediaHandle, MediaResolver, MediabunnyAudioSource, MediabunnyFrameSource, MediabunnyInputs, Motion, OVERLAY_KINDS, PICK_EPS, PLAY_PRIME_TIMEOUT_MS, PaintInputs, PerformanceClock, PlayerErrorEvent, PlayerEvents, PostEffect, QUEUE_MAX, QUEUE_TARGET, REVERSE_WINDOW_FRAMES, REVERSE_WINDOW_S, ResolveNested, SCHEDULER_MS, SEEK_MODE_SPEED, SETTLE_MS, STILL, SampleFrame, ScheduledSource, TickOptions, TransitionRole, UNMOUNT_BEHIND_S, VisibleItem, addFontFaces, animatedTransform, backdropTracks, backgroundCss, backgroundFill, blendOf, boundsOf, buildAudioPlan, buildFramePlan, buildGainEnvelope, captureWarnings, combine, compositionBackground, copyFrame, coversCanvas, cssTransform, defaultCreateCanvas, devWarn, duckIntervals, ease, effect, filterString, fitRect, frameIndex, frameTime, fromMap, hasKeyframes, isVisibleAt, keyframedValue, layerClock, layoutRect, loadFileFonts, localT, makeNestedResolver, matrixToCss, mediabunnyAudioSourceFactory, mediabunnyFrameSourceFactory, motionAt, multiply, nestedSourceTime, paintBackground, paramsAt, placementSourceTime, postEffects, rotate, roundedRect, scaleM, setMatrix, timecode, toResolver, traceMask, trackItems, transformMatrix, translate, visiblePlacements };
|
package/dist/engine.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Tt as AUDIO_CACHE_S, Et as AUDIO_CHUNK_S, Dt as AUDIO_PRIME_S, st as AssetSources, n as CanvasPainter, $ as ClipDecoder, t as Compositor, Ot as DUCK_ATTACK_S, kt as DUCK_RELEASE_S, Y as DecoderPool, yt as EASING_FN, At as ENVELOPE_STEP_S, ct as ErrorFrame, lt as ErrorFrameSource, jt as FRAME_EPS, Mt as FRAME_WAIT_MS, b as IDENTITY, Nt as INPUT_IDLE_CLOSE_S, ut as ImageFrame, dt as ImageFrameSource, Pt as LOOKAHEAD_S, Ft as MAX_OPEN_INPUTS, It as MAX_RATE, Lt as MIN_RATE, Rt as MOUNT_AHEAD_S, mt as ManualClock, G as MediabunnyAudioSource, H as MediabunnyFrameSource, V as MediabunnyInputs, L as OVERLAY_KINDS, zt as PICK_EPS, Bt as PLAY_PRIME_TIMEOUT_MS, ht as PerformanceClock, Vt as QUEUE_MAX, Ht as QUEUE_TARGET, Ut as REVERSE_WINDOW_FRAMES, Wt as REVERSE_WINDOW_S, Gt as SCHEDULER_MS, Kt as SEEK_MODE_SPEED, qt as SETTLE_MS, g as STILL, U as SampleFrame, Jt as UNMOUNT_BEHIND_S, q as addFontFaces, x as animatedTransform, R as backdropTracks, r as backgroundCss, i as backgroundFill, f as blendOf, S as boundsOf, gt as buildAudioPlan, p as buildFramePlan, _t as buildGainEnvelope, Ct as captureWarnings, _ as combine, m as compositionBackground, ft as copyFrame, a as coversCanvas, C as cssTransform, pt as defaultCreateCanvas, wt as devWarn, vt as duckIntervals, bt as ease, v as effect, P as filterString, w as fitRect, et as frameIndex, tt as frameTime, z as fromMap, xt as hasKeyframes, X as isVisibleAt, St as keyframedValue, nt as layerClock, T as layoutRect, J as loadFileFonts, rt as localT, d as makeNestedResolver, E as matrixToCss, K as mediabunnyAudioSourceFactory, W as mediabunnyFrameSourceFactory, y as motionAt, D as multiply, it as nestedSourceTime, o as paintBackground, F as paramsAt, at as placementSourceTime, I as postEffects, O as rotate, l as roundedRect, k as scaleM, s as setMatrix, ot as timecode, B as toResolver, u as traceMask, Z as trackItems, A as transformMatrix, j as translate, Q as visiblePlacements } from "./render-DA1KFyei.mjs";
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { $ as motionAt, $t as MAX_OPEN_INPUTS, A as GainPoint, An as PlayerErrorEvent, At as ErrorFrameSource, B as buildFramePlan, Bt as DecodeMode, C as EASING_FN, Cn as EnvelopePoint, Ct as MediabunnyFrameSource, D as OVERLAY_KINDS, Dn as FrameSourceInfo, Dt as mediabunnyAudioSourceFactory, E as keyframedValue, En as FrameSourceFactory, Et as MediabunnyAudioSource, F as DrawOp, Ft as FontFaceSource, G as trackItems, Gt as AUDIO_PRIME_S, H as TransitionRole, Ht as AssetSources, I as FramePlan, It as addFontFaces, J as GraphicAnimation, Jt as ENVELOPE_STEP_S, K as visiblePlacements, Kt as DUCK_ATTACK_S, L as MaskSpec, Lt as loadFileFonts, M as buildGainEnvelope, Mn as ScheduledSource, Mt as ImageFrameSource, N as duckIntervals, Nt as copyFrame, O as backdropTracks, On as MediaHandle, Ot as MediabunnyInputs, P as BackgroundGradient, Pt as defaultCreateCanvas, Q as effect, Qt as LOOKAHEAD_S, R as ResolveNested, Rt as DecoderPool, S as timecode, Sn as Ctx2D, St as toResolver, T as hasKeyframes, Tn as FrameSource, Tt as mediabunnyFrameSourceFactory, U as VisibleItem, Ut as AUDIO_CACHE_S, V as compositionBackground, Vt as AssetSourceDeps, W as isVisibleAt, Wt as AUDIO_CHUNK_S, X as STILL, Xt as FRAME_WAIT_MS, Y as Motion, Yt as FRAME_EPS, Z as combine, Zt as INPUT_IDLE_CLOSE_S, _ as frameTime, _n as AudioSource, _t as PostEffect, a as backgroundCss, an as QUEUE_MAX, at as animatedTransform, b as nestedSourceTime, bn as Clock, bt as postEffects, c as paintBackground, cn as REVERSE_WINDOW_S, ct as fitRect, d as traceMask, dn as SETTLE_MS, dt as multiply, en as MAX_RATE, et as Box, f as Compositor, fn as UNMOUNT_BEHIND_S, ft as rotate, g as frameIndex, gn as AudioOutput, gt as FilterResult, h as makeNestedResolver, hn as AnyCanvas, ht as translate, i as PaintInputs, in as PLAY_PRIME_TIMEOUT_MS, it as Matrix2D, j as buildAudioPlan, jn as PlayerEvents, jt as ImageFrame, k as AudioOccurrence, kn as MediaResolver, kt as ErrorFrame, l as setMatrix, ln as SCHEDULER_MS, lt as layoutRect, m as TickOptions, mn as PerformanceClock, mt as transformMatrix, n as devWarn, nn as MOUNT_AHEAD_S, nt as IDENTITY, o as backgroundFill, on as QUEUE_TARGET, ot as boundsOf, p as CompositorDeps, pn as ManualClock, pt as scaleM, q as ClipRect, qt as DUCK_RELEASE_S, r as CanvasPainter, rn as PICK_EPS, rt as Layout, s as coversCanvas, sn as REVERSE_WINDOW_FRAMES, st as cssTransform, t as captureWarnings, tn as MIN_RATE, tt as DrawRect, u as roundedRect, un as SEEK_MODE_SPEED, ut as matrixToCss, v as layerClock, vn as AudioSourceFactory, vt as filterString, w as ease, wn as Frame, wt as SampleFrame, x as placementSourceTime, xn as CreateCanvas, xt as fromMap, y as localT, yn as AudioSourceInfo, yt as paramsAt, z as blendOf, zt as ClipDecoder } from "./warn-GHM3SBI2.mjs";
|
|
2
|
+
import { LayerClock, ResolvedState } from "@cutcraft/kit";
|
|
3
|
+
import { CSSProperties, ReactNode } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Composition time as an anchor on the clock: `anchorTime + (now − anchorClock) × rate`.
|
|
6
|
+
* Every play, pause, seek and rate change re-anchors, so time is always derived from
|
|
7
|
+
* the clock and never accumulates drift.
|
|
8
|
+
*/
|
|
9
|
+
export declare class Transport {
|
|
10
|
+
private readonly clock;
|
|
11
|
+
duration: number;
|
|
12
|
+
private anchorTime;
|
|
13
|
+
private anchorClock;
|
|
14
|
+
private _rate;
|
|
15
|
+
private _playing;
|
|
16
|
+
loop: boolean;
|
|
17
|
+
constructor(clock: Clock, duration: number);
|
|
18
|
+
get playing(): boolean;
|
|
19
|
+
get rate(): number;
|
|
20
|
+
time(): number;
|
|
21
|
+
timeAt(clockTime: number): number;
|
|
22
|
+
/** Clock time at which composition time `t` plays; the inverse of `timeAt` while playing. */
|
|
23
|
+
clockTimeFor(t: number): number;
|
|
24
|
+
play(): void;
|
|
25
|
+
pause(): void;
|
|
26
|
+
seek(t: number): void;
|
|
27
|
+
setRate(rate: number): void;
|
|
28
|
+
/** Advance bookkeeping at the end: loops wrap, otherwise playback stops on the last time. */
|
|
29
|
+
check(): "ended" | "looped" | null;
|
|
30
|
+
private clamp;
|
|
31
|
+
}
|
|
32
|
+
export interface AudioEngineDeps {
|
|
33
|
+
readonly output: AudioOutput;
|
|
34
|
+
readonly transport: Transport;
|
|
35
|
+
/** Clock seconds (the transport's clock) → audio context seconds. */
|
|
36
|
+
readonly toContextTime: (clockTime: number) => number;
|
|
37
|
+
readonly audioSource: (assetId: string) => Promise<AudioSource>;
|
|
38
|
+
readonly state: () => ResolvedState;
|
|
39
|
+
readonly resolveNested?: ResolveNested | undefined;
|
|
40
|
+
readonly setInterval: (fn: () => void, ms: number) => unknown;
|
|
41
|
+
readonly clearInterval: (id: unknown) => void;
|
|
42
|
+
readonly onError?: ((e: PlayerErrorEvent) => void) | undefined;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Schedules audio chunks on the output ahead of the transport. Every play
|
|
46
|
+
* starts a session; a scheduler tick plans the window since the last tick
|
|
47
|
+
* up to the lookahead and schedules each new chunk once, with offset,
|
|
48
|
+
* duration and playback rate derived from the transport. Pause cancels
|
|
49
|
+
* everything; seek and rate changes restart the session.
|
|
50
|
+
*/
|
|
51
|
+
export declare class AudioEngine {
|
|
52
|
+
private readonly deps;
|
|
53
|
+
private session;
|
|
54
|
+
private timer;
|
|
55
|
+
private scheduled;
|
|
56
|
+
private scheduledUpTo;
|
|
57
|
+
private running;
|
|
58
|
+
private cache;
|
|
59
|
+
private cacheSeconds;
|
|
60
|
+
private _muted;
|
|
61
|
+
private _volume;
|
|
62
|
+
constructor(deps: AudioEngineDeps);
|
|
63
|
+
get muted(): boolean;
|
|
64
|
+
get volume(): number;
|
|
65
|
+
get active(): boolean;
|
|
66
|
+
setMaster(volume: number, muted: boolean): void;
|
|
67
|
+
/** Decode what plays in the first moments after `t`, bounded by a timeout, so play starts on time. */
|
|
68
|
+
prime(t: number): Promise<void>;
|
|
69
|
+
start(): void;
|
|
70
|
+
stop(): void;
|
|
71
|
+
/** After a seek, a rate change or a loop: reschedule from the new position. */
|
|
72
|
+
reseek(): void;
|
|
73
|
+
tick(): void;
|
|
74
|
+
dispose(): void;
|
|
75
|
+
private schedule;
|
|
76
|
+
private buffer;
|
|
77
|
+
}
|
|
78
|
+
/** Web Audio graph: per scheduled chunk `source → gain(envelope) → [pan] → master → destination`. */
|
|
79
|
+
export declare class WebAudioOutput implements AudioOutput {
|
|
80
|
+
private readonly ctx;
|
|
81
|
+
private readonly master;
|
|
82
|
+
private readonly live;
|
|
83
|
+
constructor(ctx: AudioContext);
|
|
84
|
+
get contextTime(): number;
|
|
85
|
+
get running(): boolean;
|
|
86
|
+
schedule(src: ScheduledSource): void;
|
|
87
|
+
cancel(keyPrefix: string): void;
|
|
88
|
+
cancelAll(): void;
|
|
89
|
+
setMaster(gain: number): void;
|
|
90
|
+
resume(): Promise<void>;
|
|
91
|
+
private drop;
|
|
92
|
+
private stop;
|
|
93
|
+
private disconnect;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* `AudioContext.currentTime` while the context runs, the performance clock
|
|
97
|
+
* otherwise, with an offset captured at every state change so `now()` never
|
|
98
|
+
* jumps. Audio scheduling converts back with `toContextTime`.
|
|
99
|
+
*/
|
|
100
|
+
export declare class AudioContextClock implements Clock {
|
|
101
|
+
private readonly ctx;
|
|
102
|
+
private offset;
|
|
103
|
+
private wasRunning;
|
|
104
|
+
private lastNow;
|
|
105
|
+
constructor(ctx: BaseAudioContext);
|
|
106
|
+
get running(): boolean;
|
|
107
|
+
now(): number;
|
|
108
|
+
/** Audio context seconds for a clock time; exact while the context runs. */
|
|
109
|
+
toContextTime(clockTime: number): number;
|
|
110
|
+
}
|
|
111
|
+
export interface CaptureSheetOptions {
|
|
112
|
+
/** Cells per row; default 4, never more than the number of times. */
|
|
113
|
+
readonly columns?: number;
|
|
114
|
+
/** Cell width in pixels; default the composition width capped at 320. Height follows the aspect ratio. */
|
|
115
|
+
readonly cellWidth?: number;
|
|
116
|
+
/** Draw a `mm:ss:ff` label in each cell; default true. */
|
|
117
|
+
readonly labels?: boolean;
|
|
118
|
+
}
|
|
119
|
+
export interface PlayerOptions {
|
|
120
|
+
readonly state: ResolvedState;
|
|
121
|
+
readonly media: MediaResolver | Readonly<Record<string, Blob | string>>;
|
|
122
|
+
readonly audioContext?: AudioContext | undefined;
|
|
123
|
+
readonly loop?: boolean | undefined;
|
|
124
|
+
readonly initiallyMuted?: boolean | undefined;
|
|
125
|
+
readonly playbackRate?: number | undefined;
|
|
126
|
+
/** Load the file's fonts (`state.fonts`) into the page; default true. The export page loads them itself. */
|
|
127
|
+
readonly loadFonts?: boolean | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Re-render overlays for every change of time, not once per frame; default false. The export sets it to draw the
|
|
130
|
+
* moments inside a frame that motion blur averages.
|
|
131
|
+
*/
|
|
132
|
+
readonly exactTime?: boolean | undefined;
|
|
133
|
+
readonly resolveNested?: ResolveNested | undefined;
|
|
134
|
+
/** Test seams; the browser defaults are the audio-context clock, Web Audio and mediabunny. */
|
|
135
|
+
readonly clock?: Clock | undefined;
|
|
136
|
+
readonly audioOutput?: AudioOutput | undefined;
|
|
137
|
+
readonly toContextTime?: ((clockTime: number) => number) | undefined;
|
|
138
|
+
readonly frameSourceFactory?: FrameSourceFactory | undefined;
|
|
139
|
+
readonly audioSourceFactory?: AudioSourceFactory | undefined;
|
|
140
|
+
readonly createCanvas?: CreateCanvas | undefined;
|
|
141
|
+
readonly raf?: ((cb: () => void) => number) | undefined;
|
|
142
|
+
readonly cancelRaf?: ((id: number) => void) | undefined;
|
|
143
|
+
readonly setInterval?: ((fn: () => void, ms: number) => unknown) | undefined;
|
|
144
|
+
readonly clearInterval?: ((id: unknown) => void) | undefined;
|
|
145
|
+
readonly setTimeout?: ((fn: () => void, ms: number) => unknown) | undefined;
|
|
146
|
+
readonly clearTimeout?: ((id: unknown) => void) | undefined;
|
|
147
|
+
}
|
|
148
|
+
export interface TimeSnapshot {
|
|
149
|
+
readonly time: number;
|
|
150
|
+
readonly frame: number;
|
|
151
|
+
}
|
|
152
|
+
type Listener<K extends keyof PlayerEvents> = (e: PlayerEvents[K]) => void;
|
|
153
|
+
/**
|
|
154
|
+
* The framework-free player: owns the transport, the compositor (canvas),
|
|
155
|
+
* the audio engine and the media sources. React's `<Player>` is a thin
|
|
156
|
+
* wrapper over it; a headless exporter can drive `renderFrame` directly.
|
|
157
|
+
*/
|
|
158
|
+
export declare class PlayerCore {
|
|
159
|
+
private _state;
|
|
160
|
+
private readonly media;
|
|
161
|
+
private readonly clock;
|
|
162
|
+
private readonly transport;
|
|
163
|
+
readonly compositor: Compositor;
|
|
164
|
+
private readonly engine;
|
|
165
|
+
private readonly sources;
|
|
166
|
+
private readonly inputs;
|
|
167
|
+
private readonly audioContext;
|
|
168
|
+
private readonly audioSources;
|
|
169
|
+
private readonly listeners;
|
|
170
|
+
private readonly timeListeners;
|
|
171
|
+
private readonly createCanvas;
|
|
172
|
+
private readonly raf;
|
|
173
|
+
private readonly cancelRaf;
|
|
174
|
+
private rafId;
|
|
175
|
+
private readonly setTimeoutFn;
|
|
176
|
+
private readonly clearTimeoutFn;
|
|
177
|
+
private settleTimer;
|
|
178
|
+
private seekGeneration;
|
|
179
|
+
private snapshot;
|
|
180
|
+
private _muted;
|
|
181
|
+
private _volume;
|
|
182
|
+
private disposed;
|
|
183
|
+
private fonts;
|
|
184
|
+
private fontsOf;
|
|
185
|
+
private readonly fontsWanted;
|
|
186
|
+
constructor(options: PlayerOptions);
|
|
187
|
+
/** Resolves once the file's fonts (`state.fonts`) have loaded; a face that fails is reported as an error event. */
|
|
188
|
+
/** Overlays follow every change of time, not each frame (`exactTime`). */
|
|
189
|
+
readonly exactTime: boolean;
|
|
190
|
+
get fontsReady(): Promise<void>;
|
|
191
|
+
private loadFonts;
|
|
192
|
+
get state(): ResolvedState;
|
|
193
|
+
get duration(): number;
|
|
194
|
+
get playbackRate(): number;
|
|
195
|
+
set playbackRate(rate: number);
|
|
196
|
+
get loop(): boolean;
|
|
197
|
+
set loop(v: boolean);
|
|
198
|
+
get muted(): boolean;
|
|
199
|
+
set muted(v: boolean);
|
|
200
|
+
get volume(): number;
|
|
201
|
+
set volume(v: number);
|
|
202
|
+
/** The media handle for an asset id, for DOM elements that show images. */
|
|
203
|
+
resolveMedia(assetId: string): Promise<MediaHandle>;
|
|
204
|
+
getCurrentTime(): number;
|
|
205
|
+
getCurrentFrame(): number;
|
|
206
|
+
isPlaying(): boolean;
|
|
207
|
+
getTime(): TimeSnapshot;
|
|
208
|
+
play(): Promise<void>;
|
|
209
|
+
pause(): void;
|
|
210
|
+
toggle(): Promise<void>;
|
|
211
|
+
/** Jump to `time` and draw its exact frame before resolving, playing or not. */
|
|
212
|
+
seekTo(time: number): Promise<void>;
|
|
213
|
+
seekToFrame(frame: number): Promise<void>;
|
|
214
|
+
/** Draw `time` without moving the transport; decoders return to the play head afterwards. */
|
|
215
|
+
renderFrame(time: number): Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* A contact sheet of the canvas plane at `times`: each cell is `renderFrame`
|
|
218
|
+
* of that time with a timecode label, laid out `columns` wide. The way an
|
|
219
|
+
* agent or a test looks at the result without exporting. DOM overlays
|
|
220
|
+
* (titles, shapes, Layer interiors) are not on the canvas and do not appear.
|
|
221
|
+
*/
|
|
222
|
+
captureSheet(times: readonly number[], options?: CaptureSheetOptions): Promise<AnyCanvas>;
|
|
223
|
+
/**
|
|
224
|
+
* The editor pushes a new resolve on every drag step. Decoders of the same
|
|
225
|
+
* asset keep their frames and take the new trim; a paused preview paints at
|
|
226
|
+
* once with what is decoded and fetches the exact frame after the gesture
|
|
227
|
+
* has been quiet for `SETTLE_MS`.
|
|
228
|
+
*/
|
|
229
|
+
setState(state: ResolvedState): void;
|
|
230
|
+
attachCanvas(canvas: HTMLCanvasElement | OffscreenCanvas | null): void;
|
|
231
|
+
addEventListener<K extends keyof PlayerEvents>(type: K, fn: Listener<K>): () => void;
|
|
232
|
+
removeEventListener<K extends keyof PlayerEvents>(type: K, fn: Listener<K>): void;
|
|
233
|
+
/** For `useSyncExternalStore`: notified once per painted frame and on every seek. */
|
|
234
|
+
subscribeTime(fn: () => void): () => void;
|
|
235
|
+
dispose(): void;
|
|
236
|
+
private startLoop;
|
|
237
|
+
private stopLoop;
|
|
238
|
+
private publish;
|
|
239
|
+
private emit;
|
|
240
|
+
private audioSource;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Walk the file's element tree the way the kit's `collect` does (fragments,
|
|
244
|
+
* vocabulary elements, pure helpers expanded by calling them) and record the
|
|
245
|
+
* children of every `<Layer id>`: the resolver drops them, the Player renders them.
|
|
246
|
+
*/
|
|
247
|
+
export declare function indexLayerInteriors(element: ReactNode): Map<string, ReactNode>;
|
|
248
|
+
/** Play/pause, scrubber, time readout, mute and rate. */
|
|
249
|
+
export declare function Controls(): import("react").JSX.Element;
|
|
250
|
+
export declare const PlayerContext: import("react").Context<PlayerCore | null>;
|
|
251
|
+
/** The layer's clock inside a `<Layer>`; null outside one. */
|
|
252
|
+
export declare const LayerContext: import("react").Context<LayerClock | null>;
|
|
253
|
+
export interface DomLayerProps {
|
|
254
|
+
readonly state: ResolvedState;
|
|
255
|
+
readonly interiors: ReadonlyMap<string, ReactNode>;
|
|
256
|
+
/** Which overlays: those beneath the footage (`backdropTracks`), or the rest and the captions (default). */
|
|
257
|
+
readonly layer?: "backdrop" | "front";
|
|
258
|
+
}
|
|
259
|
+
/** Overlay elements as DOM, one absolutely positioned group per track in compositing order, above the canvas (or, for the backdrop, below it). */
|
|
260
|
+
export declare function DomLayer({ state, interiors, layer }: DomLayerProps): import("react").JSX.Element;
|
|
261
|
+
export interface ElementCellProps {
|
|
262
|
+
item: VisibleItem;
|
|
263
|
+
state: ResolvedState;
|
|
264
|
+
time: number;
|
|
265
|
+
interior: ReactNode;
|
|
266
|
+
/** Re-render for any change of time, not only a new frame (the player's `exactTime`). */
|
|
267
|
+
exact?: boolean;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Whether two renders of an overlay would produce the same DOM. Placements
|
|
271
|
+
* are new objects on every resolve, so compare what matters: timing, the
|
|
272
|
+
* parsed props (referentially stable while untouched), children, the
|
|
273
|
+
* element-relative frame, the transition progress, the text and the
|
|
274
|
+
* composition box.
|
|
275
|
+
*/
|
|
276
|
+
export declare function sameElement(a: ElementCellProps, b: ElementCellProps): boolean;
|
|
277
|
+
/**
|
|
278
|
+
* Holds the CSS animations under `root` at `seconds` past the layer's start: paused, and seeked there. They then
|
|
279
|
+
* follow the video's clock (play, pause, scrub both ways) and an export captures the same frame twice.
|
|
280
|
+
*
|
|
281
|
+
* Only CSS animations: their zero is the moment their element got the style, which inside a Layer is the layer's
|
|
282
|
+
* start. A Web Animation made with `element.animate()` or by a library keeps its own start and its owner's clock.
|
|
283
|
+
*/
|
|
284
|
+
export declare function holdCssAnimations(root: Element | null, seconds: number): void;
|
|
285
|
+
export declare function usePlayer(): PlayerCore;
|
|
286
|
+
export declare function useCompositionTime(): number;
|
|
287
|
+
export declare function useCompositionFrame(): number;
|
|
288
|
+
/** What the kit's `useLayer()` and `useT()` delegate to while a Player is mounted. */
|
|
289
|
+
export declare function useLayerClock(): LayerClock;
|
|
290
|
+
/** 0..1 progress through the enclosing Layer. */
|
|
291
|
+
export declare function useLayerT(): number;
|
|
292
|
+
/** Installs the kit's layer hooks for the first mounted Player and removes them after the last unmounts. */
|
|
293
|
+
export declare function retainUseT(): () => void;
|
|
294
|
+
export interface PlayerProps {
|
|
295
|
+
readonly state: ResolvedState;
|
|
296
|
+
readonly media: MediaResolver | Readonly<Record<string, Blob | string>>;
|
|
297
|
+
/** The evaluated file element (`mod.default(props)`); needed only to render `<Layer>` interiors. */
|
|
298
|
+
readonly element?: ReactNode;
|
|
299
|
+
readonly controls?: boolean;
|
|
300
|
+
readonly loop?: boolean;
|
|
301
|
+
readonly autoPlay?: boolean;
|
|
302
|
+
readonly initiallyMuted?: boolean;
|
|
303
|
+
readonly playbackRate?: number;
|
|
304
|
+
/** `contain` scales the composition into the box; `none` renders at composition pixels. */
|
|
305
|
+
readonly fit?: "contain" | "none";
|
|
306
|
+
readonly style?: CSSProperties;
|
|
307
|
+
readonly className?: string;
|
|
308
|
+
readonly audioContext?: AudioContext;
|
|
309
|
+
readonly onError?: (e: PlayerEvents["error"]) => void;
|
|
310
|
+
readonly onFrame?: (e: PlayerEvents["frameupdate"]) => void;
|
|
311
|
+
/** Test seams forwarded to PlayerCore. */
|
|
312
|
+
readonly coreOptions?: Partial<PlayerOptions>;
|
|
313
|
+
}
|
|
314
|
+
export type PlayerRef = Pick<PlayerCore, "play" | "pause" | "toggle" | "seekTo" | "seekToFrame" | "getCurrentTime" | "getCurrentFrame" | "isPlaying" | "addEventListener" | "removeEventListener" | "renderFrame" | "captureSheet" | "duration" | "state"> & {
|
|
315
|
+
playbackRate: number;
|
|
316
|
+
loop: boolean;
|
|
317
|
+
muted: boolean;
|
|
318
|
+
volume: number;
|
|
319
|
+
readonly core: PlayerCore;
|
|
320
|
+
readonly canvas: HTMLCanvasElement | null;
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Canvas for media, DOM for overlays, controls below. The root carries
|
|
324
|
+
* `data-time` and `data-frame`; every element carries `data-el`/`data-kind`.
|
|
325
|
+
*/
|
|
326
|
+
export declare const Player: import("react").ForwardRefExoticComponent<PlayerProps & import("react").RefAttributes<PlayerRef>>;
|
|
327
|
+
export { AUDIO_CACHE_S, AUDIO_CHUNK_S, AUDIO_PRIME_S, AnyCanvas, AssetSourceDeps, AssetSources, AudioOccurrence, AudioOutput, AudioSource, AudioSourceFactory, AudioSourceInfo, BackgroundGradient, Box, CanvasPainter, ClipDecoder, ClipRect, Clock, Compositor, CompositorDeps, CreateCanvas, Ctx2D, DUCK_ATTACK_S, DUCK_RELEASE_S, DecodeMode, DecoderPool, DrawOp, DrawRect, EASING_FN, ENVELOPE_STEP_S, EnvelopePoint, ErrorFrame, ErrorFrameSource, FRAME_EPS, FRAME_WAIT_MS, FilterResult, FontFaceSource, Frame, FramePlan, FrameSource, FrameSourceFactory, FrameSourceInfo, GainPoint, GraphicAnimation, IDENTITY, INPUT_IDLE_CLOSE_S, ImageFrame, ImageFrameSource, LOOKAHEAD_S, Layout, MAX_OPEN_INPUTS, MAX_RATE, MIN_RATE, MOUNT_AHEAD_S, ManualClock, MaskSpec, Matrix2D, MediaHandle, MediaResolver, MediabunnyAudioSource, MediabunnyFrameSource, MediabunnyInputs, Motion, OVERLAY_KINDS, PICK_EPS, PLAY_PRIME_TIMEOUT_MS, PaintInputs, PerformanceClock, PlayerErrorEvent, PlayerEvents, PostEffect, QUEUE_MAX, QUEUE_TARGET, REVERSE_WINDOW_FRAMES, REVERSE_WINDOW_S, ResolveNested, SCHEDULER_MS, SEEK_MODE_SPEED, SETTLE_MS, STILL, SampleFrame, ScheduledSource, TickOptions, TransitionRole, UNMOUNT_BEHIND_S, VisibleItem, addFontFaces, animatedTransform, backdropTracks, backgroundCss, backgroundFill, blendOf, boundsOf, buildAudioPlan, buildFramePlan, buildGainEnvelope, captureWarnings, combine, compositionBackground, copyFrame, coversCanvas, cssTransform, defaultCreateCanvas, devWarn, duckIntervals, ease, effect, filterString, fitRect, frameIndex, frameTime, fromMap, hasKeyframes, isVisibleAt, keyframedValue, layerClock, layoutRect, loadFileFonts, localT, makeNestedResolver, matrixToCss, mediabunnyAudioSourceFactory, mediabunnyFrameSourceFactory, motionAt, multiply, nestedSourceTime, paintBackground, paramsAt, placementSourceTime, postEffects, rotate, roundedRect, scaleM, setMatrix, timecode, toResolver, traceMask, trackItems, transformMatrix, translate, visiblePlacements };
|