supervision 0.1.7 → 0.2.0-next.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 (215) hide show
  1. package/dist/detections/chunked-detection-frame-source.d.ts.map +1 -1
  2. package/dist/index.d.ts +11 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +8856 -4559
  5. package/dist/index.js.map +1 -1
  6. package/dist/mask-preparation.worker.js +310 -164
  7. package/dist/mask-preparation.worker.js.map +1 -1
  8. package/dist/media/display-pixel-ratio.d.ts +15 -0
  9. package/dist/media/display-pixel-ratio.d.ts.map +1 -0
  10. package/dist/media/engine-import-failure.d.ts +16 -0
  11. package/dist/media/engine-import-failure.d.ts.map +1 -0
  12. package/dist/media/media-condition-probe.d.ts +51 -0
  13. package/dist/media/media-condition-probe.d.ts.map +1 -0
  14. package/dist/media/media-conditions.d.ts +28 -0
  15. package/dist/media/media-conditions.d.ts.map +1 -0
  16. package/dist/media/media-errors.d.ts +6 -0
  17. package/dist/media/media-errors.d.ts.map +1 -1
  18. package/dist/media/media-normalization.d.ts.map +1 -1
  19. package/dist/media/media-probe.d.ts.map +1 -1
  20. package/dist/media/media-source.d.ts +17 -0
  21. package/dist/media/media-source.d.ts.map +1 -1
  22. package/dist/media/mediabunny-media-source.d.ts.map +1 -1
  23. package/dist/media/video-engine-media-source.d.ts +44 -0
  24. package/dist/media/video-engine-media-source.d.ts.map +1 -0
  25. package/dist/render-preparation/mask-frame-artifact.d.ts +46 -12
  26. package/dist/render-preparation/mask-frame-artifact.d.ts.map +1 -1
  27. package/dist/render-preparation/mask-frame-compositor.d.ts +5 -5
  28. package/dist/render-preparation/mask-frame-compositor.d.ts.map +1 -1
  29. package/dist/render-preparation/mask-frame-preparer.d.ts.map +1 -1
  30. package/dist/render-preparation/mask-preparation-worker-count.d.ts +4 -4
  31. package/dist/render-preparation/mask-preparation-worker-protocol.d.ts +12 -3
  32. package/dist/render-preparation/mask-preparation-worker-protocol.d.ts.map +1 -1
  33. package/dist/render-preparation/prepared-render-window.d.ts +23 -0
  34. package/dist/render-preparation/prepared-render-window.d.ts.map +1 -1
  35. package/dist/render-preparation/prepared-window-timeline.d.ts +2 -6
  36. package/dist/render-preparation/prepared-window-timeline.d.ts.map +1 -1
  37. package/dist/renderers/mask-palette.d.ts +14 -0
  38. package/dist/renderers/mask-palette.d.ts.map +1 -0
  39. package/dist/renderers/mask-vertex.d.ts +14 -0
  40. package/dist/renderers/mask-vertex.d.ts.map +1 -0
  41. package/dist/renderers/media-renderer-core.d.ts.map +1 -1
  42. package/dist/renderers/media-renderer-scene.d.ts +37 -0
  43. package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
  44. package/dist/renderers/media-renderer-state.d.ts +11 -1
  45. package/dist/renderers/media-renderer-state.d.ts.map +1 -1
  46. package/dist/renderers/media-renderer-transport.d.ts +59 -0
  47. package/dist/renderers/media-renderer-transport.d.ts.map +1 -0
  48. package/dist/renderers/pixi-box-layer.d.ts +5 -0
  49. package/dist/renderers/pixi-box-layer.d.ts.map +1 -1
  50. package/dist/renderers/pixi-focus-layer.d.ts +18 -2
  51. package/dist/renderers/pixi-focus-layer.d.ts.map +1 -1
  52. package/dist/renderers/pixi-frame-present.d.ts +77 -0
  53. package/dist/renderers/pixi-frame-present.d.ts.map +1 -0
  54. package/dist/renderers/pixi-id-mask-shader.d.ts +12 -2
  55. package/dist/renderers/pixi-id-mask-shader.d.ts.map +1 -1
  56. package/dist/renderers/pixi-interaction-layer.d.ts.map +1 -1
  57. package/dist/renderers/pixi-interaction-presentation-layer.d.ts +13 -2
  58. package/dist/renderers/pixi-interaction-presentation-layer.d.ts.map +1 -1
  59. package/dist/renderers/pixi-mask-halo.d.ts +24 -0
  60. package/dist/renderers/pixi-mask-halo.d.ts.map +1 -1
  61. package/dist/renderers/pixi-mask-layer.d.ts +71 -8
  62. package/dist/renderers/pixi-mask-layer.d.ts.map +1 -1
  63. package/dist/renderers/pixi-media-scene.d.ts +67 -0
  64. package/dist/renderers/pixi-media-scene.d.ts.map +1 -1
  65. package/dist/renderers/pixi-polygon-layer.d.ts +7 -2
  66. package/dist/renderers/pixi-polygon-layer.d.ts.map +1 -1
  67. package/dist/renderers/pixi-region-coverage-mask.d.ts +91 -0
  68. package/dist/renderers/pixi-region-coverage-mask.d.ts.map +1 -0
  69. package/dist/renderers/pixi-region-effect.d.ts +42 -0
  70. package/dist/renderers/pixi-region-effect.d.ts.map +1 -0
  71. package/dist/renderers/pixi-region-layer.d.ts +68 -2
  72. package/dist/renderers/pixi-region-layer.d.ts.map +1 -1
  73. package/dist/renderers/pixi-vector-layer.d.ts.map +1 -1
  74. package/dist/renderers/prepared-annotation-window.d.ts +47 -0
  75. package/dist/renderers/prepared-annotation-window.d.ts.map +1 -0
  76. package/dist/renderers/presented-frame-channel.d.ts +107 -0
  77. package/dist/renderers/presented-frame-channel.d.ts.map +1 -0
  78. package/dist/renderers/scene-render-scheduler.d.ts +20 -0
  79. package/dist/renderers/scene-render-scheduler.d.ts.map +1 -0
  80. package/dist/sessions/media-session-defaults.d.ts +10 -6
  81. package/dist/sessions/media-session-defaults.d.ts.map +1 -1
  82. package/dist/sessions/media-session-media.d.ts.map +1 -1
  83. package/dist/sessions/media-session-state.d.ts.map +1 -1
  84. package/dist/sessions/media-session.d.ts.map +1 -1
  85. package/dist/tracking.worker.js +58 -3
  86. package/dist/tracking.worker.js.map +1 -1
  87. package/dist/types/media-conditions.d.ts +149 -0
  88. package/dist/types/media-conditions.d.ts.map +1 -0
  89. package/dist/types/media-normalization.d.ts +34 -0
  90. package/dist/types/media-normalization.d.ts.map +1 -1
  91. package/dist/types/media-renderer.d.ts +31 -1
  92. package/dist/types/media-renderer.d.ts.map +1 -1
  93. package/dist/types/media-session.d.ts +89 -8
  94. package/dist/types/media-session.d.ts.map +1 -1
  95. package/dist/types/render-preparation.d.ts +101 -4
  96. package/dist/types/render-preparation.d.ts.map +1 -1
  97. package/dist/web-video-engine/analysis-session.d.ts +76 -0
  98. package/dist/web-video-engine/analysis-session.d.ts.map +1 -0
  99. package/dist/web-video-engine/analysis.d.ts +7 -0
  100. package/dist/web-video-engine/analysis.d.ts.map +1 -0
  101. package/dist/web-video-engine/analysis.js +1678 -0
  102. package/dist/web-video-engine/analysis.js.map +1 -0
  103. package/dist/web-video-engine/cache-budget.d.ts +19 -0
  104. package/dist/web-video-engine/cache-budget.d.ts.map +1 -0
  105. package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts +90 -0
  106. package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts.map +1 -0
  107. package/dist/web-video-engine/clock.d.ts +83 -0
  108. package/dist/web-video-engine/clock.d.ts.map +1 -0
  109. package/dist/web-video-engine/constants.d.ts +253 -0
  110. package/dist/web-video-engine/constants.d.ts.map +1 -0
  111. package/dist/web-video-engine/create-scrub-cursor.d.ts +62 -0
  112. package/dist/web-video-engine/create-scrub-cursor.d.ts.map +1 -0
  113. package/dist/web-video-engine/decode-resolution.d.ts +115 -0
  114. package/dist/web-video-engine/decode-resolution.d.ts.map +1 -0
  115. package/dist/web-video-engine/decode-scheduler.d.ts +356 -0
  116. package/dist/web-video-engine/decode-scheduler.d.ts.map +1 -0
  117. package/dist/web-video-engine/decode-session.d.ts +276 -0
  118. package/dist/web-video-engine/decode-session.d.ts.map +1 -0
  119. package/dist/web-video-engine/decode-source.d.ts +250 -0
  120. package/dist/web-video-engine/decode-source.d.ts.map +1 -0
  121. package/dist/web-video-engine/diagnostics-store.d.ts +18 -0
  122. package/dist/web-video-engine/diagnostics-store.d.ts.map +1 -0
  123. package/dist/web-video-engine/diagnostics.d.ts +316 -0
  124. package/dist/web-video-engine/diagnostics.d.ts.map +1 -0
  125. package/dist/web-video-engine/embedded-engine-worker.d.ts +2 -0
  126. package/dist/web-video-engine/embedded-engine-worker.d.ts.map +1 -0
  127. package/dist/web-video-engine/engine-core.d.ts +258 -0
  128. package/dist/web-video-engine/engine-core.d.ts.map +1 -0
  129. package/dist/web-video-engine/engine.d.ts +26 -0
  130. package/dist/web-video-engine/engine.d.ts.map +1 -0
  131. package/dist/web-video-engine/engine.js +873 -0
  132. package/dist/web-video-engine/engine.js.map +1 -0
  133. package/dist/web-video-engine/engine.worker.d.ts +2 -0
  134. package/dist/web-video-engine/engine.worker.d.ts.map +1 -0
  135. package/dist/web-video-engine/engine.worker.js +31320 -0
  136. package/dist/web-video-engine/engine.worker.js.map +1 -0
  137. package/dist/web-video-engine/frame-cache.d.ts +129 -0
  138. package/dist/web-video-engine/frame-cache.d.ts.map +1 -0
  139. package/dist/web-video-engine/frame-extractor.d.ts +28 -0
  140. package/dist/web-video-engine/frame-extractor.d.ts.map +1 -0
  141. package/dist/web-video-engine/frame-timeline-GINI8Gum.js +560 -0
  142. package/dist/web-video-engine/frame-timeline-GINI8Gum.js.map +1 -0
  143. package/dist/web-video-engine/frame-timeline.d.ts +71 -0
  144. package/dist/web-video-engine/frame-timeline.d.ts.map +1 -0
  145. package/dist/web-video-engine/frame-walker.d.ts +74 -0
  146. package/dist/web-video-engine/frame-walker.d.ts.map +1 -0
  147. package/dist/web-video-engine/index.d.ts +3 -0
  148. package/dist/web-video-engine/index.d.ts.map +1 -0
  149. package/dist/web-video-engine/index.js +3 -0
  150. package/dist/web-video-engine/index.js.map +1 -0
  151. package/dist/web-video-engine/key-packet.d.ts +65 -0
  152. package/dist/web-video-engine/key-packet.d.ts.map +1 -0
  153. package/dist/web-video-engine/keyframe-index.d.ts +91 -0
  154. package/dist/web-video-engine/keyframe-index.d.ts.map +1 -0
  155. package/dist/web-video-engine/mirror-store.d.ts +56 -0
  156. package/dist/web-video-engine/mirror-store.d.ts.map +1 -0
  157. package/dist/web-video-engine/renderer.d.ts +94 -0
  158. package/dist/web-video-engine/renderer.d.ts.map +1 -0
  159. package/dist/web-video-engine/rotation.d.ts +35 -0
  160. package/dist/web-video-engine/rotation.d.ts.map +1 -0
  161. package/dist/web-video-engine/scrub-controller.d.ts +376 -0
  162. package/dist/web-video-engine/scrub-controller.d.ts.map +1 -0
  163. package/dist/web-video-engine/scrub-cursor.d.ts +342 -0
  164. package/dist/web-video-engine/scrub-cursor.d.ts.map +1 -0
  165. package/dist/web-video-engine/scrub-trajectory.d.ts +30 -0
  166. package/dist/web-video-engine/scrub-trajectory.d.ts.map +1 -0
  167. package/dist/web-video-engine/source-residency.d.ts +57 -0
  168. package/dist/web-video-engine/source-residency.d.ts.map +1 -0
  169. package/dist/web-video-engine/trace-recorder.d.ts +164 -0
  170. package/dist/web-video-engine/trace-recorder.d.ts.map +1 -0
  171. package/dist/web-video-engine/types.d.ts +204 -0
  172. package/dist/web-video-engine/types.d.ts.map +1 -0
  173. package/dist/web-video-engine/video-engine.d.ts +426 -0
  174. package/dist/web-video-engine/video-engine.d.ts.map +1 -0
  175. package/dist/web-video-engine/webgpu-renderer.d.ts +62 -0
  176. package/dist/web-video-engine/webgpu-renderer.d.ts.map +1 -0
  177. package/dist/web-video-engine/worker-bridge.d.ts +12 -0
  178. package/dist/web-video-engine/worker-bridge.d.ts.map +1 -0
  179. package/dist/web-video-engine/worker-dispatch.d.ts +17 -0
  180. package/dist/web-video-engine/worker-dispatch.d.ts.map +1 -0
  181. package/dist/web-video-engine/worker-protocol.d.ts +267 -0
  182. package/dist/web-video-engine/worker-protocol.d.ts.map +1 -0
  183. package/node_modules/supervision-js-core/dist/detections/buffered-detection-timeline.d.ts.map +1 -1
  184. package/node_modules/supervision-js-core/dist/detections/composite-detection-frame-source.d.ts.map +1 -1
  185. package/node_modules/supervision-js-core/dist/index.d.ts +4 -3
  186. package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
  187. package/node_modules/supervision-js-core/dist/index.js +1075 -266
  188. package/node_modules/supervision-js-core/dist/index.js.map +1 -1
  189. package/node_modules/supervision-js-core/dist/styles/default-annotation-presentation.d.ts.map +1 -1
  190. package/node_modules/supervision-js-core/dist/styles/interaction-style.d.ts +4 -36
  191. package/node_modules/supervision-js-core/dist/styles/interaction-style.d.ts.map +1 -1
  192. package/node_modules/supervision-js-core/dist/styles/polyline-style.d.ts +5 -0
  193. package/node_modules/supervision-js-core/dist/styles/polyline-style.d.ts.map +1 -1
  194. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts +92 -7
  195. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts.map +1 -1
  196. package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts +179 -17
  197. package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts.map +1 -1
  198. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts +78 -2
  199. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts.map +1 -1
  200. package/node_modules/supervision-js-core/dist/types/polyline-style.d.ts +2 -0
  201. package/node_modules/supervision-js-core/dist/types/polyline-style.d.ts.map +1 -1
  202. package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts +16 -0
  203. package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts.map +1 -1
  204. package/node_modules/supervision-js-core/dist/utils/detection-conversions.d.ts.map +1 -1
  205. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts +5 -0
  206. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts.map +1 -1
  207. package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts +9 -0
  208. package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts.map +1 -1
  209. package/node_modules/supervision-js-core/dist/utils/detection-ranges.d.ts +18 -0
  210. package/node_modules/supervision-js-core/dist/utils/detection-ranges.d.ts.map +1 -0
  211. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts +15 -2
  212. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts.map +1 -1
  213. package/node_modules/supervision-js-core/dist/utils/wait-bound.d.ts +7 -0
  214. package/node_modules/supervision-js-core/dist/utils/wait-bound.d.ts.map +1 -0
  215. package/package.json +22 -1
@@ -0,0 +1,204 @@
1
+ import type { FrameTimelineData } from "./frame-timeline";
2
+ /**
3
+ * Seconds, as a branded float. Promoted out of `number` so a duration
4
+ * cannot accidentally be passed where a frame index is expected.
5
+ */
6
+ export type Sec = number & {
7
+ readonly __sec: unique symbol;
8
+ };
9
+ /** Frames per second. Branded for the same reason as Sec. */
10
+ export type Fps = number & {
11
+ readonly __fps: unique symbol;
12
+ };
13
+ /**
14
+ * Paints since the source loaded, monotonic within it and reset on source swap.
15
+ * It counts paints, not frames of the source: two paints of the same media
16
+ * position (a coarse stand-in then the crisp decode) take two numbers, and
17
+ * nothing here identifies which frame of the source is on screen. That identity
18
+ * travels only as the media timestamp on the paint event.
19
+ */
20
+ export type PaintSeq = number & {
21
+ readonly __paintSeq: unique symbol;
22
+ };
23
+ export declare const asSec: (n: number) => Sec;
24
+ export declare const asFps: (n: number) => Fps;
25
+ export declare const asPaintSeq: (n: number) => PaintSeq;
26
+ export declare enum SourceKind {
27
+ Url = "url",
28
+ Blob = "blob",
29
+ Stream = "stream"
30
+ }
31
+ export interface UrlVideoSource {
32
+ kind: SourceKind.Url;
33
+ url: string;
34
+ /** The engine fetches rather than building an element, so these reach the
35
+ * request as the CORS fetch they stand for. Undeclared leaves the request at
36
+ * the demuxer's own same-origin default. */
37
+ crossOrigin?: "anonymous" | "use-credentials";
38
+ }
39
+ /**
40
+ * Mediabunny's own read tuning for a URL source, passed straight through to its
41
+ * `UrlSource`. Every field absent leaves mediabunny's defaults in place.
42
+ */
43
+ export interface UrlSourceReadConfig {
44
+ /** Range requests the demuxer may have in flight at once. */
45
+ readonly parallelism?: number;
46
+ /** Ceiling on the bytes mediabunny's own read cache holds. */
47
+ readonly maxCacheSize?: number;
48
+ }
49
+ export interface BlobVideoSource {
50
+ kind: SourceKind.Blob;
51
+ blob: Blob;
52
+ }
53
+ export interface StreamVideoSource {
54
+ kind: SourceKind.Stream;
55
+ stream: ReadableStream<Uint8Array>;
56
+ /** Declared container type. The demuxer sniffs the bytes and never reads
57
+ * this; it travels so a host can report what the media is. */
58
+ mimeType: string;
59
+ }
60
+ /**
61
+ * Source descriptor. Discriminated so each backend can route without runtime
62
+ * sniffing and so the future mediabunny v2 StreamSource slots in as a new
63
+ * variant rather than a refactor.
64
+ */
65
+ export type VideoSource = UrlVideoSource | BlobVideoSource | StreamVideoSource;
66
+ /**
67
+ * Which decode machinery a source was opened through: mediabunny's CanvasSink,
68
+ * mediabunny's VideoSampleSink, or the runtime's own long-lived DecodeSession.
69
+ * Resolved per source at open time from what the track and the realm support.
70
+ */
71
+ export type DecodePath = "canvas" | "sample" | "session";
72
+ /**
73
+ * Who owns the pixels. "canvas" is the engine: it holds a display canvas and
74
+ * paints every frame that earns the screen. "frames" is the host: the engine
75
+ * holds no canvas, paints nothing, and hands each of those frames out as a
76
+ * VideoFrame instead, so an external compositor can own the only canvas.
77
+ */
78
+ export type PresentationMode = "canvas" | "frames";
79
+ /**
80
+ * Coarse-grained engine status. Updates rarely (load, play, pause, end,
81
+ * error). Sits on its own emit channel so subscribers do not wake up on
82
+ * 60Hz time ticks.
83
+ */
84
+ export declare enum PlaybackStatus {
85
+ Idle = "IDLE",
86
+ Loading = "LOADING",
87
+ Ready = "READY",
88
+ Playing = "PLAYING",
89
+ Paused = "PAUSED",
90
+ Seeking = "SEEKING",
91
+ Ended = "ENDED",
92
+ Errored = "ERRORED"
93
+ }
94
+ export declare enum VideoEngineErrorCode {
95
+ DecodeUnsupported = "DECODE_UNSUPPORTED",
96
+ SourceUnreadable = "SOURCE_UNREADABLE",
97
+ /**
98
+ * The demuxer refused the file outright: its container is not one this build
99
+ * reads, so no track was ever listed and no decoder was ever asked.
100
+ */
101
+ ContainerUnreadable = "CONTAINER_UNREADABLE",
102
+ /**
103
+ * The container opened and the demuxer parsed no track at all out of it. The
104
+ * file's streams are in formats it does not carry, so their video cannot be
105
+ * reached even though it is there.
106
+ */
107
+ VideoTrackUnreadable = "VIDEO_TRACK_UNREADABLE",
108
+ /**
109
+ * The container opened, its tracks listed, and none of them is video. This
110
+ * is the only case where the file itself is what lacks video.
111
+ */
112
+ NoVideoTrack = "NO_VIDEO_TRACK",
113
+ BackendCrashed = "BACKEND_CRASHED",
114
+ Aborted = "ABORTED",
115
+ /** A canvas was offered to an engine loaded in "frames" presentation mode,
116
+ * where the host owns the only canvas. */
117
+ PresentationMismatch = "PRESENTATION_MISMATCH",
118
+ /**
119
+ * The decoder cannot decode this source at all: it refused to configure, it
120
+ * errored, or it acknowledged decode requests and never produced a frame.
121
+ * Distinct from BackendCrashed, which a rebuild can recover; this one
122
+ * survives every rebuild, so the runtime stops rebuilding and says so. The
123
+ * usual cause is outside the page: another tab holding every hardware
124
+ * decoder session the machine has.
125
+ */
126
+ DecoderStalled = "DECODER_STALLED",
127
+ /** A playback rate outside the forward range the engine supports. */
128
+ RateUnsupported = "RATE_UNSUPPORTED"
129
+ }
130
+ /**
131
+ * Thrown by createScrubCursor / VideoEngine.load when decode is unsupported
132
+ * or the source is unreadable. Branch on `error.code` (VideoEngineErrorCode)
133
+ * to differentiate decode failures from network failures.
134
+ */
135
+ export declare class VideoEngineError extends Error {
136
+ readonly code: VideoEngineErrorCode;
137
+ readonly cause?: unknown;
138
+ constructor(code: VideoEngineErrorCode, message: string, cause?: unknown);
139
+ }
140
+ /** Shared by the facade and the core so a host gets the same refusal wherever
141
+ * its canvas is caught. */
142
+ export declare function canvasBindingRefused(): VideoEngineError;
143
+ /**
144
+ * Validates a requested playback rate and returns it. The facade and the core
145
+ * both call it, so a rate is refused at whichever boundary it arrives at and
146
+ * with the same message: the facade posts fire-and-forget, so a refusal raised
147
+ * only in the worker would reach nobody.
148
+ *
149
+ * Reverse is rejected, not clamped: backwards playback is a different decode
150
+ * problem, and a -1 quietly serviced as +0.25 plays the wrong direction while
151
+ * reporting success.
152
+ */
153
+ export declare function resolvePlaybackRate(rate: number): number;
154
+ export interface PlaybackState {
155
+ status: PlaybackStatus;
156
+ error: VideoEngineError | null;
157
+ }
158
+ export interface VideoMetadata {
159
+ durationMs: number;
160
+ nativeFps: Fps | null;
161
+ naturalWidth: number;
162
+ naturalHeight: number;
163
+ /** Media time of the first sample, ms. Non-zero on trimmed/offset sources,
164
+ * where an annotation timeline that assumes 0 drifts by exactly this. */
165
+ firstTimestampMs: number;
166
+ codec: string | null;
167
+ canDecode: boolean;
168
+ }
169
+ /**
170
+ * Snapshot delivered through the `onReady` lifecycle callback exactly once
171
+ * per loaded source after metadata resolves.
172
+ */
173
+ export interface EngineReadySnapshot extends VideoMetadata {
174
+ /**
175
+ * Every real frame of the source, by its container tick timestamp. A host
176
+ * holding this can name any position the engine publishes, and can resolve
177
+ * one of its own pointer positions to a frame without asking.
178
+ */
179
+ readonly timeline: FrameTimelineData;
180
+ /**
181
+ * The kind of reader the demuxer was opened over, recorded once the open
182
+ * succeeded. A host knows what it asked for; only the engine knows what it
183
+ * got, and the three kinds differ in what they can do afterwards — a stream
184
+ * cannot be rewound or reopened, and only a URL is fetched.
185
+ *
186
+ * Optional so a host holding a snapshot it built before this field existed
187
+ * still satisfies the type.
188
+ */
189
+ readonly byteSource?: SourceKind;
190
+ }
191
+ /**
192
+ * Channels the engine store emits on. Pick the channel matching the slice
193
+ * cadence so consumers do not wake up on unrelated mutations.
194
+ *
195
+ * - time: emits per paint (raw ms; bucketing lives in hook selectors).
196
+ * - frame: emits per settled cursor frame (frame-index changes).
197
+ * - state: coarse status transitions (load, play, pause, end, error).
198
+ * - duration: once per loaded source.
199
+ * - seeking: cursor scrub-in-flight transitions (opt-in indicator).
200
+ * - rate: playback-rate changes. Rare, and on its own channel so a rate
201
+ * readout does not wake on status and vice versa.
202
+ */
203
+ export type EngineChannel = "time" | "frame" | "state" | "duration" | "seeking" | "rate";
204
+ //# 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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"}
@@ -0,0 +1,426 @@
1
+ import type { DecodeResolutionStrategy } from "./decode-resolution";
2
+ import type { DiagnosticsSnapshot, EngineDiagnostics } from "./diagnostics";
3
+ import { type FrameId, type FrameLanding } from "./frame-timeline";
4
+ import type { SeekIntent } from "./scrub-cursor";
5
+ import type { EngineTrace } from "./trace-recorder";
6
+ import { type EngineChannel, type EngineReadySnapshot, type PaintSeq, type PlaybackState, PlaybackStatus, type PresentationMode, type UrlSourceReadConfig, type VideoSource } from "./types";
7
+ import { type EngineCommand, type EngineEvent, type PresentedFrame, type SourceResidencyConfig } from "./worker-protocol";
8
+ /**
9
+ * Where a caller wants the playhead: a frame of the source, or a position in
10
+ * milliseconds. A pointer only ever has the second kind; anything the engine
11
+ * published carries the first, and handing that back needs no conversion.
12
+ */
13
+ export type SeekTarget = number | FrameId;
14
+ export interface VideoEngineOptions {
15
+ source: VideoSource;
16
+ /**
17
+ * Who owns the pixels, fixed for the life of the engine. Default "canvas":
18
+ * the engine holds the display canvas bindCanvas transfers to it and paints
19
+ * every frame that earns the screen. Under "frames" it holds no canvas,
20
+ * paints nothing, and hands those frames to onPresentedFrame instead, for a
21
+ * host compositor to draw; bindCanvas then throws.
22
+ */
23
+ presentation?: PresentationMode;
24
+ /**
25
+ * Cache strategy for instant scrub feedback. Default "tiered" keeps a
26
+ * downscaled preview history plus a RAM-bounded full-resolution tier;
27
+ * "none" disables caching (the cursor decodes every seek from scratch).
28
+ */
29
+ cacheStrategy?: "tiered" | "none";
30
+ /** Preview-tier capacity (frames). Ignored when cacheStrategy is "none". */
31
+ previewCapacity?: number;
32
+ /** Preview-tier entry width in CSS pixels. Ignored when cacheStrategy is "none". */
33
+ previewWidth?: number;
34
+ /**
35
+ * Cache lookups whose nearest hit lies within this many milliseconds of
36
+ * what the canvas already shows are rejected, forcing a full-res decode.
37
+ * See constants.FRAME_CACHE.SKIP_NEAR_MS for the default and tuning notes.
38
+ */
39
+ cacheSkipNearMs?: number;
40
+ /**
41
+ * Decides the resolution preview frames decode to. Defaults to native, so a
42
+ * consumer that says nothing keeps full source resolution and pays for it in
43
+ * paint work and frame-cache slots. Governs the live preview only; never the
44
+ * timestamps a consumer extracts.
45
+ *
46
+ * Which strategy fits follows from `presentation`. Under "canvas" the engine
47
+ * measures the box it was handed, so viewportResolution() reads it. Under
48
+ * "frames" nothing binds a canvas and there is no box to read, so
49
+ * viewportResolution() resolves to native there and displayBoxResolution()
50
+ * is how that consumer states the size it composites into.
51
+ */
52
+ decodeStrategy?: DecodeResolutionStrategy;
53
+ /**
54
+ * Pin the 2D renderer instead of WebGPU. WebGPU is the default; leaving this
55
+ * unset prefers it and falls back to the 2D renderer only when WebGPU is
56
+ * unavailable, so unset is not a guarantee of WebGPU. Both renderers paint
57
+ * the same already-decoded frames on the same cadence (the render loop draws
58
+ * a frame only when a new one is decoded). The 2D path is one canvas blit
59
+ * per frame, not a re-decode and not a per-tick CPU repaint; the two differ
60
+ * only in where a frame is composited, the GPU versus a 2D context.
61
+ */
62
+ prefer2d?: boolean;
63
+ /**
64
+ * Hold the source's bytes in this process and serve the demuxer's reads from
65
+ * them, so a position read once is read locally ever after. Off by default:
66
+ * it spends memory the host has to be willing to spend, and prefetching
67
+ * spends the viewer's link on bytes they may never watch.
68
+ *
69
+ * Only a `SourceKind.Url` source can use this. A Blob source is already local
70
+ * and a Stream source is consumed once, so neither has anything to hold.
71
+ */
72
+ sourceResidency?: SourceResidencyConfig;
73
+ /**
74
+ * Read tuning handed to mediabunny for a `SourceKind.Url` source: how many
75
+ * range requests it may run at once, and how many bytes its own reader keeps.
76
+ * Nothing here is read for a Blob or Stream source.
77
+ */
78
+ urlSource?: UrlSourceReadConfig;
79
+ }
80
+ /**
81
+ * The slice of a Worker this facade depends on. A real Worker is structurally
82
+ * assignable, so production passes one through createEngineWorker; tests
83
+ * pass a fake port that hosts an EngineCore in-process.
84
+ */
85
+ export interface EngineWorkerPort {
86
+ postMessage(message: EngineCommand, transfer: Transferable[]): void;
87
+ addEventListener(type: "message", listener: (event: MessageEvent<EngineEvent>) => void): void;
88
+ terminate(): void;
89
+ }
90
+ /**
91
+ * Main-thread facade for the worker-hosted video engine. Owns the worker
92
+ * (spawned lazily on the first command), the mirror store React reads through
93
+ * useSyncExternalStore, and the imperative handle. The decode + render loop runs
94
+ * in the worker (EngineCore); this class never touches a cursor or clock directly.
95
+ *
96
+ * Three planes cross the worker boundary (see workerProtocol): commands go out,
97
+ * broadcast state comes back as MirrorEvents fed into the store, and the display
98
+ * canvas is transferred once on bindCanvas. Awaitable commands carry a requestId
99
+ * the worker echoes back so each call settles its own promise.
100
+ *
101
+ * Time has two owners, gated by playback. While playing, the worker emits time;
102
+ * while paused, the main thread owns the position: scrub/commit/step write it
103
+ * optimistically so a late worker paint never yanks it back. Consumers render the
104
+ * playhead by reading getTimeMs/getDurationMs at their own cadence.
105
+ *
106
+ * Engine outlives a single React render. Recreate the engine only when the
107
+ * source identity changes.
108
+ */
109
+ export declare class VideoEngine {
110
+ private readonly options;
111
+ private readonly store;
112
+ private readonly diagnosticsStore;
113
+ private readonly createWorker;
114
+ private port;
115
+ private disposed;
116
+ private lastTrace;
117
+ private traceArmed;
118
+ private readonly pending;
119
+ private nextRequestId;
120
+ private metadata;
121
+ /** The loaded source's frame table, held here so a gesture is resolved to a
122
+ * frame in the tick it arrives, with no worker round trip. */
123
+ private timeline;
124
+ private transferredCanvas;
125
+ private presentedFrameHandler;
126
+ /** Deliveries counted toward the one frame-ownership check, frozen past it,
127
+ * and the frame that check reads. Weak, so watching costs the frame no
128
+ * lifetime: a host that closes and drops it leaves nothing to find, which is
129
+ * itself the answer. */
130
+ private presentedDeliveries;
131
+ private watchedFrame;
132
+ private cachedHandle;
133
+ /** WebGPU support is a main-thread fact the worker cannot cheaply probe, so
134
+ * the facade fills it onto each diagnostics snapshot for the warning rules. */
135
+ private readonly webgpuAvailable;
136
+ constructor(options: VideoEngineOptions, createWorker?: () => EngineWorkerPort);
137
+ load(): Promise<EngineReadySnapshot>;
138
+ /**
139
+ * Transfers the display canvas to the worker exactly once. The transfer is
140
+ * permanent (it neuters the element's 2D/GPU context), so a repeat call with
141
+ * the same element, or a null detach, is a no-op; the binding lives until
142
+ * dispose terminates the worker. The viewport box is measured here, where
143
+ * layout lives, and shipped so a viewport-aware decode strategy can size the
144
+ * sink worker-side.
145
+ */
146
+ bindCanvas: (el: HTMLCanvasElement | null) => void;
147
+ play: () => Promise<void>;
148
+ pause: () => void;
149
+ togglePlayback: () => void;
150
+ /**
151
+ * Forward playback speed, in media seconds per wall second. Takes effect at
152
+ * once while playing and on the next play while paused; either way it
153
+ * survives pause, seek, interactive-seek, and replay from the end, because
154
+ * it is the clock's slope and none of those touch it.
155
+ *
156
+ * Throws synchronously on a rate outside the supported forward range,
157
+ * including any reverse rate. The refusal has to happen here: the command is
158
+ * fire-and-forget, so a worker-side throw would reach no caller.
159
+ */
160
+ setPlaybackRate: (rate: number) => void;
161
+ getPlaybackRate(): number;
162
+ /**
163
+ * Fire-and-forget seek: latest-wins, does not await idle. A pointer position
164
+ * is not a frame time and never can be, so it is resolved to the frame
165
+ * covering it before it reaches the store or the worker; the table lives on
166
+ * this thread, so the playhead lands on a frame in the same tick the gesture
167
+ * arrives, with no round trip.
168
+ *
169
+ * intent steers what the cache prepares next. Ignored when cacheStrategy is
170
+ * "none": that backend has no access modes to switch and no prefetch to aim.
171
+ */
172
+ scrub: (target: SeekTarget, intent?: SeekIntent) => void;
173
+ /**
174
+ * Pause-during-drag entry point. Consumers that handle pointer-driven
175
+ * scrub gestures call this on pointerdown so playback freezes and the
176
+ * decoder is not continuously chasing the cursor; the corresponding
177
+ * endInteractiveSeek call on pointerup resumes play if the engine was
178
+ * playing when the drag started. Matches the way native <video> pauses
179
+ * during the scrub-bar drag and resumes on release.
180
+ */
181
+ beginInteractiveSeek: () => void;
182
+ /**
183
+ * Pointerup counterpart to beginInteractiveSeek. Resumes play only if the
184
+ * engine was playing when the drag started; an idle-to-idle drag leaves the
185
+ * engine paused. Resolves once the worker has applied the release.
186
+ */
187
+ endInteractiveSeek: () => Promise<void>;
188
+ /**
189
+ * Awaited seek. Resolves after the cursor settles. Use on pointer-up so
190
+ * downstream logic (export, telemetry, marker placement) sees the
191
+ * settled frame.
192
+ */
193
+ commit: (target: SeekTarget) => Promise<void>;
194
+ seekToKey: (target: SeekTarget) => Promise<void>;
195
+ /**
196
+ * Moves one frame along the source in presentation order. Which frame that
197
+ * is depends on where the walk actually settled, which only the worker
198
+ * knows, so the landing rides back on the ack and is written here, keeping
199
+ * the paused playhead in step with the freshly painted frame.
200
+ */
201
+ private stepChain;
202
+ /**
203
+ * Serialized so concurrent callers (rapid key-repeat, mashed buttons, a
204
+ * programmatic loop) never run overlapping steps that race the cursor's
205
+ * one-shot decode iterator and wedge it. Each call chains after the previous,
206
+ * so every invocation advances exactly one frame from the settled position,
207
+ * on any surface.
208
+ */
209
+ step: (direction: 1 | -1) => Promise<void>;
210
+ private runStep;
211
+ /**
212
+ * Settled iff the engine is between operations. Derived from mirror state
213
+ * rather than the cursor (which lives in the worker): Idle/Loading read as
214
+ * settled, otherwise a live seek is the only thing that unsettles it.
215
+ */
216
+ isIdle(): boolean;
217
+ getSeeking(): boolean;
218
+ /** Where the transport has settled: a frame of the source, never a request
219
+ * and never a clock reading. */
220
+ getPlayhead(): FrameLanding;
221
+ getTimeMs(): number;
222
+ getDurationMs(): number;
223
+ getStatus(): PlaybackStatus;
224
+ getPaintSeq(): PaintSeq;
225
+ getMetadata(): EngineReadySnapshot | null;
226
+ /**
227
+ * Cache hit-rate, scrub-decode latency, and access mode from the worker, or
228
+ * null on the uncached cursor. A round-trip per call; for diagnostics, not
229
+ * the hot path.
230
+ */
231
+ getStats(): Promise<EngineDiagnostics | null>;
232
+ /**
233
+ * Opt-in diagnostics broadcast. Starts the worker's BROADCAST_HZ timer and
234
+ * flips on the per-rAF counters; snapshots arrive on the diag plane and land
235
+ * in the DiagnosticsStore. The instrument calls this on mount and
236
+ * stopDiagnostics on unmount, so a closed panel costs the engine nothing.
237
+ */
238
+ startDiagnostics: (hz?: number) => void;
239
+ stopDiagnostics: () => void;
240
+ /** Arm the worker trace rings. Fire-and-forget; disarmTrace frees them. */
241
+ armTrace: (windowMs: number) => void;
242
+ disarmTrace: () => void;
243
+ /** The capture rescued from a dispose that landed mid-recording, or null. */
244
+ getLastTrace: () => EngineTrace | null;
245
+ /** Awaitable: assembles the worker trace and returns it for download. Null
246
+ * when nothing was armed. */
247
+ exportTrace: () => Promise<EngineTrace | null>;
248
+ /**
249
+ * Registers THE consumer of presented frames, in "frames" presentation mode.
250
+ * A second registration replaces the first, so at most one holder exists.
251
+ * The handler owns every frame it is given and must close() it; one left
252
+ * open pins a decoder buffer and stalls the decoder.
253
+ *
254
+ * There is deliberately no counterpart that reports the frame most recently
255
+ * presented. A frame readable apart from the message that carried it can be
256
+ * read at a moment when a newer one has already been handed out, which is
257
+ * the desync this plane is shaped to make impossible.
258
+ */
259
+ onPresentedFrame: (handler: PresentedFrameHandler) => void;
260
+ /** Subscribe to diagnostics pushes; fires on every diag broadcast. Separate
261
+ * from the playback subscribe channels so a diagnostics consumer never wakes
262
+ * on playback state and vice versa. */
263
+ subscribeDiagnostics: (listener: () => void) => (() => void);
264
+ /** Latest broadcast snapshot, or null before the first push. */
265
+ getLatestDiagnostics: () => DiagnosticsSnapshot | null;
266
+ subscribe(channel: EngineChannel, listener: () => void): () => void;
267
+ /**
268
+ * Tears the engine down: drains pending requests so an in-flight load/commit
269
+ * rejects rather than hanging, and terminates the worker. The dispose ack is
270
+ * awaited first so the worker closes its cursor cleanly before the realm is
271
+ * killed.
272
+ *
273
+ * The engine is inert afterwards. A fire-and-forget command is dropped and an
274
+ * awaitable one rejects with {@link VideoEngineErrorCode.Aborted}; neither
275
+ * starts another worker.
276
+ */
277
+ dispose(): Promise<void>;
278
+ /**
279
+ * Curated subset exposed to React via useImperativeHandle. Cached so the
280
+ * handle keeps a stable identity for the lifetime of the engine (consumers
281
+ * may list it in useEffect deps).
282
+ */
283
+ toHandle(): VideoEngineHandle;
284
+ private readonly isIdleBound;
285
+ private readonly getPlayheadBound;
286
+ private readonly getTimeMsBound;
287
+ private readonly getDurationMsBound;
288
+ private readonly getPaintSeqBound;
289
+ private readonly getMetadataBound;
290
+ private readonly getStatsBound;
291
+ private readonly getPlaybackStateBound;
292
+ private readonly getSeekingBound;
293
+ private readonly getPlaybackRateBound;
294
+ private readonly subscribeBound;
295
+ private readonly onWorkerMessage;
296
+ /**
297
+ * Hands one frame to the registered consumer, which owns it from here. With
298
+ * nobody registered it is closed at once rather than dropped on the floor:
299
+ * the worker has already let go of it, so an unclaimed frame is a leak that
300
+ * pins a decoder buffer.
301
+ */
302
+ private deliverPresentedFrame;
303
+ /**
304
+ * Says out loud that this host does not close the frames it is handed.
305
+ * Nothing else in the runtime can: the frame left the worker on the transfer
306
+ * list, so no engine-side counter ever sees it again, and the decoder it
307
+ * starves reports the damage as a hung decode instead.
308
+ *
309
+ * One frame is watched and read once, so the check costs a host that closes a
310
+ * single allocation for the whole session and every later delivery one
311
+ * predicted-false branch.
312
+ */
313
+ private checkFrameOwnership;
314
+ private settle;
315
+ /**
316
+ * Spawns the worker on first use and wires the state plane into the mirror
317
+ * store. Deferring the spawn keeps construction side-effect-free, so a
318
+ * VideoEngine built during render (e.g. a useState initializer) never leaks
319
+ * a worker when React discards a duplicate.
320
+ */
321
+ private ensurePort;
322
+ private request;
323
+ private post;
324
+ private rejectAllPending;
325
+ /**
326
+ * The frame a target names.
327
+ *
328
+ * A frame names itself. A millisecond position is narrowed in seconds and
329
+ * then settled against `timeAt(i) * 1000`, the expression getTimeMs
330
+ * publishes: dividing a published millisecond back into seconds re-rounds
331
+ * it, and on tick rates like NTSC's 24000 the quotient can land just under
332
+ * the frame's own second, one frame early.
333
+ */
334
+ private snap;
335
+ private writePlayheadAt;
336
+ private writePlayhead;
337
+ private requireTimeline;
338
+ private measureViewport;
339
+ }
340
+ /**
341
+ * Receives one presented frame and owns it: it must close() the VideoFrame, and
342
+ * the identity it is judged against arrives in the same object, never fetched.
343
+ */
344
+ export type PresentedFrameHandler = (presented: PresentedFrame) => void;
345
+ /**
346
+ * Imperative handle exposed to React via useImperativeHandle. Stable identity
347
+ * for the lifetime of one source, so consumers may list it in effect deps.
348
+ *
349
+ * Curated subset on purpose: coarse status + error are reachable via the
350
+ * PlaybackStateContext or useVideoEngineState hook, NOT through the handle, so a
351
+ * consumer that latches onto the handle does not also depend on the shape of
352
+ * getPlaybackState.
353
+ */
354
+ export interface VideoEngineHandle {
355
+ play(): Promise<void>;
356
+ pause(): void;
357
+ togglePlayback(): void;
358
+ /**
359
+ * Forward playback speed in media seconds per wall second, within the range
360
+ * PLAYBACK_RATE bounds. Throws synchronously outside it, reverse included.
361
+ * Subscribe on the "rate" channel to follow it.
362
+ */
363
+ setPlaybackRate(rate: number): void;
364
+ getPlaybackRate(): number;
365
+ scrub(target: SeekTarget, intent?: SeekIntent): void;
366
+ commit(target: SeekTarget): Promise<void>;
367
+ seekToKey(target: SeekTarget): Promise<void>;
368
+ step(direction: 1 | -1): Promise<void>;
369
+ /**
370
+ * Pointerdown of a drag-based scrub. Pauses if the engine was playing
371
+ * and remembers to resume on endInteractiveSeek. Idempotent inside a
372
+ * drag (re-entries while the resume flag is armed are no-ops, so the
373
+ * original "was playing" state survives).
374
+ */
375
+ beginInteractiveSeek(): void;
376
+ /** Pointerup of a drag-based scrub. Resumes play iff begin paused us. */
377
+ endInteractiveSeek(): Promise<void>;
378
+ isIdle(): boolean;
379
+ /** Where the transport has settled, as a frame of the source. */
380
+ getPlayhead(): FrameLanding;
381
+ /** The same position on the whole-millisecond plane, for a host that still
382
+ * speaks it. Handing this value back to scrub, commit or seekToKey lands on
383
+ * the frame it came from, on every source. */
384
+ getTimeMs(): number;
385
+ getDurationMs(): number;
386
+ getPaintSeq(): PaintSeq;
387
+ getMetadata(): EngineReadySnapshot | null;
388
+ /** Worker-side runtime stats (cache hit-rate, scrub latency, access mode)
389
+ * for diagnostics; null on the uncached cursor. A round-trip per call. */
390
+ getStats(): Promise<EngineDiagnostics | null>;
391
+ getPlaybackState(): PlaybackState;
392
+ /**
393
+ * True while the cursor is mid-scrub. Cache-hit scrubs do not flip this
394
+ * because the cache paint is synchronous; only real cursor decode walks
395
+ * trip it. Subscribed via the "seeking" channel.
396
+ */
397
+ getSeeking(): boolean;
398
+ bindCanvas(el: HTMLCanvasElement | null): void;
399
+ /**
400
+ * Registers the single consumer of presented frames ("frames" presentation
401
+ * mode). Registering again replaces the previous consumer. The handler owns
402
+ * each frame and must close() it.
403
+ */
404
+ onPresentedFrame(handler: PresentedFrameHandler): void;
405
+ subscribe(channel: EngineChannel, listener: () => void): () => void;
406
+ /**
407
+ * Opt-in diagnostics broadcast control. The instrument starts on mount and
408
+ * stops on unmount (and on visibilitychange), so the worker pays nothing when
409
+ * no panel listens. Snapshots arrive via subscribeDiagnostics; the playback
410
+ * channels are untouched.
411
+ */
412
+ startDiagnostics(hz?: number): void;
413
+ stopDiagnostics(): void;
414
+ /** Arm/disarm the worker trace rings (fire-and-forget). */
415
+ armTrace(windowMs: number): void;
416
+ disarmTrace(): void;
417
+ /** Assemble and return the worker trace for download; null when not armed. */
418
+ exportTrace(): Promise<EngineTrace | null>;
419
+ /** The capture rescued from a dispose that landed mid-recording, or null. */
420
+ getLastTrace(): EngineTrace | null;
421
+ /** Subscribe to diagnostics pushes. Separate from the playback channels. */
422
+ subscribeDiagnostics(listener: () => void): () => void;
423
+ /** Latest broadcast snapshot, or null before the first push. */
424
+ getLatestDiagnostics(): DiagnosticsSnapshot | null;
425
+ }
426
+ //# sourceMappingURL=video-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-engine.d.ts","sourceRoot":"","sources":["../src/video-engine.ts"],"names":[],"mappings":"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"}