@alpha2-sh/editor 0.0.0 → 0.1.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 (98) hide show
  1. package/README.md +107 -1
  2. package/dist/browser/bridge.d.ts +44 -0
  3. package/dist/browser/bridge.js +2176 -0
  4. package/dist/browser/extensions-worker-entry.js +3 -0
  5. package/dist/browser/extensions-worker.d.ts +46 -0
  6. package/dist/browser/extensions-worker.js +149 -0
  7. package/dist/browser/hash-worker-entry.d.ts +1 -0
  8. package/dist/browser/hash-worker-entry.js +3 -0
  9. package/dist/browser/hash-worker.d.ts +24 -0
  10. package/dist/browser/hash-worker.js +87 -0
  11. package/dist/browser/index.d.ts +11 -0
  12. package/dist/browser/index.js +9 -0
  13. package/dist/browser/jobs.d.ts +82 -0
  14. package/dist/browser/jobs.js +291 -0
  15. package/dist/browser/resources.d.ts +40 -0
  16. package/dist/browser/resources.js +83 -0
  17. package/dist/browser/runtime/assets.d.ts +233 -0
  18. package/dist/browser/runtime/assets.js +633 -0
  19. package/dist/browser/runtime/audio.d.ts +60 -0
  20. package/dist/browser/runtime/audio.js +549 -0
  21. package/dist/browser/runtime/budget.d.ts +11 -0
  22. package/dist/browser/runtime/budget.js +26 -0
  23. package/dist/browser/runtime/caption-fonts.d.ts +34 -0
  24. package/dist/browser/runtime/caption-fonts.js +69 -0
  25. package/dist/browser/runtime/color.d.ts +7 -0
  26. package/dist/browser/runtime/color.js +12 -0
  27. package/dist/browser/runtime/engine.d.ts +91 -0
  28. package/dist/browser/runtime/engine.js +352 -0
  29. package/dist/browser/runtime/export-audio.d.ts +23 -0
  30. package/dist/browser/runtime/export-audio.js +75 -0
  31. package/dist/browser/runtime/exporter.d.ts +140 -0
  32. package/dist/browser/runtime/exporter.js +751 -0
  33. package/dist/browser/runtime/extension-import.d.ts +196 -0
  34. package/dist/browser/runtime/extension-import.js +521 -0
  35. package/dist/browser/runtime/fingerprint.d.ts +57 -0
  36. package/dist/browser/runtime/fingerprint.js +157 -0
  37. package/dist/browser/runtime/generators.d.ts +188 -0
  38. package/dist/browser/runtime/generators.js +173 -0
  39. package/dist/browser/runtime/locks.d.ts +32 -0
  40. package/dist/browser/runtime/locks.js +86 -0
  41. package/dist/browser/runtime/output.d.ts +87 -0
  42. package/dist/browser/runtime/output.js +230 -0
  43. package/dist/browser/runtime/preview-utils.d.ts +3 -0
  44. package/dist/browser/runtime/preview-utils.js +49 -0
  45. package/dist/browser/runtime/proxies.d.ts +72 -0
  46. package/dist/browser/runtime/proxies.js +369 -0
  47. package/dist/browser/runtime/proxy-storage.d.ts +59 -0
  48. package/dist/browser/runtime/proxy-storage.js +119 -0
  49. package/dist/browser/runtime/sources.d.ts +82 -0
  50. package/dist/browser/runtime/sources.js +819 -0
  51. package/dist/browser/runtime/staging.d.ts +10 -0
  52. package/dist/browser/runtime/staging.js +32 -0
  53. package/dist/browser/runtime/still.d.ts +21 -0
  54. package/dist/browser/runtime/still.js +52 -0
  55. package/dist/browser/runtime/wasm.d.ts +9 -0
  56. package/dist/browser/runtime/wasm.js +20 -0
  57. package/dist/browser/types.d.ts +549 -0
  58. package/dist/browser/types.js +1 -0
  59. package/dist/browser/worker-entry.d.ts +1 -0
  60. package/dist/browser/worker-entry.js +2 -0
  61. package/dist/browser/worker.d.ts +24 -0
  62. package/dist/browser/worker.js +239 -0
  63. package/dist/core/captions.d.ts +34 -0
  64. package/dist/core/captions.js +108 -0
  65. package/dist/core/clip-time.d.ts +31 -0
  66. package/dist/core/clip-time.js +125 -0
  67. package/dist/core/commands.d.ts +413 -0
  68. package/dist/core/commands.js +1118 -0
  69. package/dist/core/compositions.d.ts +234 -0
  70. package/dist/core/compositions.js +851 -0
  71. package/dist/core/document.d.ts +245 -0
  72. package/dist/core/document.js +683 -0
  73. package/dist/core/keyframes.d.ts +82 -0
  74. package/dist/core/keyframes.js +153 -0
  75. package/dist/core/presets.d.ts +64 -0
  76. package/dist/core/presets.js +241 -0
  77. package/dist/core/session.d.ts +150 -0
  78. package/dist/core/session.js +541 -0
  79. package/dist/core/text.d.ts +17 -0
  80. package/dist/core/text.js +17 -0
  81. package/dist/core/time.d.ts +19 -0
  82. package/dist/core/time.js +39 -0
  83. package/dist/core/timeline-index.d.ts +44 -0
  84. package/dist/core/timeline-index.js +59 -0
  85. package/dist/core/transitions.d.ts +20 -0
  86. package/dist/core/transitions.js +118 -0
  87. package/dist/core/validated.d.ts +23 -0
  88. package/dist/core/validated.js +52 -0
  89. package/dist/index.d.ts +12 -0
  90. package/dist/index.js +11 -0
  91. package/dist/native-client/index.d.ts +131 -0
  92. package/dist/native-client/index.js +354 -0
  93. package/dist/ports/index.d.ts +146 -0
  94. package/dist/ports/index.js +1 -0
  95. package/dist/react/index.d.ts +37 -0
  96. package/dist/react/index.js +94 -0
  97. package/package.json +69 -8
  98. /package/{index.js → dist/browser/extensions-worker-entry.d.ts} +0 -0
@@ -0,0 +1,549 @@
1
+ import type { MediaFingerprint, Project } from "alpha2/project";
2
+ import type { AssetBinding, ConformReport, MediaPurpose } from "alpha2/assets";
3
+ import type { BuiltinEffectCatalog } from "alpha2/effects";
4
+ import type { EditorSession } from "../core/session.js";
5
+ import type { CapabilityReport, PlaybackPolicy } from "alpha2";
6
+ import type { Capability } from "../ports/index.js";
7
+ import type { Json } from "../core/document.js";
8
+ import type { ExportJob } from "./jobs.js";
9
+ /**
10
+ * Where a bundler put the runtime's code and data. Each URL defaults to the location the
11
+ * packaged module resolves on its own.
12
+ */
13
+ export interface RuntimeAssets {
14
+ /**
15
+ * Creates a worker running `installEditorWorker`. With one, the preview renders in that
16
+ * worker; without, it renders on the main thread.
17
+ */
18
+ readonly workerFactory?: () => Worker;
19
+ /**
20
+ * Creates a worker running the `@alpha2-sh/editor/hash-worker` entry. With one, each imported or
21
+ * relinked file is hashed in a worker of its own; without, on the page's thread, which lets
22
+ * other tasks run every few milliseconds but spends the page's CPU (about 5 ms a megabyte).
23
+ */
24
+ readonly hashWorkerFactory?: () => Worker;
25
+ /**
26
+ * Creates a worker running the `@alpha2-sh/editor/extensions-worker` entry. With one, each file an
27
+ * extension provider reads (SVG, animated image, Lottie, OpenEXR) is probed, opened and drawn for
28
+ * its thumbnail at import, and an SVG opened again for its font report, in a worker of its own,
29
+ * which a cancelled import terminates, as does a call running past `EXTENSIONS_CALL_TIMEOUT_MS`
30
+ * (40 s; the import fails as `provider_stalled`). Without one, or when the worker cannot start,
31
+ * those calls run on the page's thread, which waits for each: an animated image's open decodes
32
+ * every frame.
33
+ */
34
+ readonly extensionsWorkerFactory?: () => Worker;
35
+ /** The engine's wasm binary (`alpha2/wasm`). */
36
+ readonly wasmUrl?: string | URL;
37
+ /**
38
+ * Where a bundler put `alpha2_extensions_bg.wasm`, loaded when an SVG, animated image, or image
39
+ * sequence is opened.
40
+ */
41
+ readonly extensionsWasmUrl?: string | URL;
42
+ /** The audio worklet's wasm binary, loaded on the first Play. */
43
+ readonly audioWasmUrl?: string | URL;
44
+ /** The audio worklet processor module. */
45
+ readonly workletUrl?: string | URL;
46
+ /**
47
+ * Fonts the runtime provides beyond the document's font assets. They follow those in the
48
+ * fallback order for captions and SVG text, and native exports receive them too.
49
+ */
50
+ readonly fonts?: readonly RuntimeFont[];
51
+ }
52
+ /** A font file the runtime registers with the engine. */
53
+ export interface RuntimeFont {
54
+ readonly id: string;
55
+ readonly name: string;
56
+ readonly bytes: Uint8Array;
57
+ /** The face to read in a collection file (`.ttc`/`.otc`); 0 for a single-face file. */
58
+ readonly faceIndex: number;
59
+ }
60
+ /**
61
+ * A source's media as this browser session holds it. Never part of the project document or its
62
+ * history.
63
+ */
64
+ export interface RuntimeAsset {
65
+ readonly id: string;
66
+ /** `video`, `image`, `audio`, `text`, `font`, `lut3d`, or `generated`. */
67
+ readonly kind: string;
68
+ readonly name?: string;
69
+ /**
70
+ * What the source is read from. A still is decoded from it each time a frame needs its raster and
71
+ * the cache does not hold it: no decoded picture stays with the asset.
72
+ */
73
+ readonly file?: File;
74
+ /** Small preview canvas; `dataUrl` is a ready-to-use image URL. */
75
+ readonly thumbnail?: {
76
+ readonly dataUrl?: string;
77
+ readonly width: number;
78
+ readonly height: number;
79
+ } | null;
80
+ /** Display size in pixels, where the media has one. */
81
+ readonly width?: number;
82
+ readonly height?: number;
83
+ /** Seconds; 0 for a still. */
84
+ readonly duration?: number;
85
+ /**
86
+ * Whether the file has an audio stream: what the document records as the source's `has_audio`,
87
+ * whichever browser imported it.
88
+ */
89
+ readonly hasAudio?: boolean;
90
+ /**
91
+ * `false` when this browser cannot decode the file's audio (Safari before 26 has no
92
+ * `AudioDecoder`): it plays and exports silent in this session, and the document still says the
93
+ * source has audio, which a native host and other browsers hear.
94
+ */
95
+ readonly audioDecodable?: boolean;
96
+ /** Per-bucket peak magnitudes across the whole file, for audio sources. */
97
+ readonly peaks?: Float32Array | null;
98
+ /** `native`: drawn centred at its own pixel size (text); otherwise contained. */
99
+ readonly fit?: "native" | "contain";
100
+ }
101
+ /** A file decoded and probed for import, before it enters the document. */
102
+ export interface StagedAsset {
103
+ readonly runtime: RuntimeAsset;
104
+ /** The asset's authoring description, recorded in the document. */
105
+ readonly description: Json;
106
+ /** Evidence of the file, recorded with the asset and its project source. */
107
+ readonly fingerprint?: MediaFingerprint;
108
+ /** Releases what staging opened. Called once the bridge no longer holds the runtime. */
109
+ dispose(): void;
110
+ }
111
+ /** Decodes and probes files for import. `createMediaAdapter` makes the default one. */
112
+ export interface BrowserMediaAdapter {
113
+ /**
114
+ * Stages one file. Rejects with an `EditorError`: `unsupported_media` for a file that is no media
115
+ * the adapter imports, `unreadable_media` for media this browser could not read (a codec it does
116
+ * not decode, a damaged file, or one an extension provider refuses, such as one whose drawing is
117
+ * past its budgets; the decoder's or provider's reason is in the message and is the `cause`),
118
+ * `too_large` for a Lottie, dotLottie or SVG file larger than the engine parses
119
+ * (`MAX_LOTTIE_DOCUMENT_BYTES`, `MAX_PROVIDER_DOCUMENT_BYTES` for a dotLottie package,
120
+ * `MAX_SVG_DOCUMENT_BYTES`), `provider_stalled` for one the extensions worker read past
121
+ * `EXTENSIONS_CALL_TIMEOUT_MS`, and when `signal` aborts.
122
+ */
123
+ stage(file: File, signal: AbortSignal, options?: {
124
+ /**
125
+ * `false` when the caller has no use for the file's fingerprint and it need not be computed:
126
+ * the bridge adopts a kept proxy by its original's hash. Default `true`.
127
+ */
128
+ readonly fingerprint?: boolean;
129
+ }): Promise<StagedAsset>;
130
+ /** Stages numbered PNGs or OpenEXR images as one image sequence. */
131
+ stageSequence?(files: readonly File[], options: {
132
+ readonly frameRate: {
133
+ readonly num: number;
134
+ readonly den: number;
135
+ };
136
+ readonly missing: "reject" | "hold" | "blank";
137
+ /**
138
+ * The source ID the frames are staged under: the asset's own for a relink, a new one
139
+ * otherwise.
140
+ */
141
+ readonly id?: string;
142
+ }, signal: AbortSignal): Promise<StagedAsset & {
143
+ readonly name?: string;
144
+ }>;
145
+ }
146
+ /**
147
+ * What `installEditorWorker` uses of a dedicated worker's global (`self` in the worker): its
148
+ * message handler and `postMessage`.
149
+ */
150
+ export interface EditorWorkerScope {
151
+ onmessage: ((event: MessageEvent) => void) | null;
152
+ postMessage(message: unknown, transfer?: Transferable[]): void;
153
+ }
154
+ /** Options of `createBrowserBridge`. */
155
+ export interface BrowserBridgeOptions {
156
+ /**
157
+ * The session the bridge previews, imports into, and exports. Disposing it disposes the bridge.
158
+ */
159
+ readonly editor: EditorSession;
160
+ readonly runtimeAssets?: RuntimeAssets;
161
+ /** Defaults to `createMediaAdapter(runtimeAssets)`. */
162
+ readonly mediaAdapter?: BrowserMediaAdapter;
163
+ /**
164
+ * The most runtime resources (imported media, rasterized text, proxies) held at once,
165
+ * default 128. An import past it is refused with `EditorError` `resource_budget`.
166
+ */
167
+ readonly resourceLimit?: number;
168
+ /**
169
+ * `false` renders picture only: no AudioContext is opened and playback runs on the wall clock
170
+ * (thumbnails and other silent previews).
171
+ */
172
+ readonly audio?: boolean;
173
+ /**
174
+ * Receives errors no caller awaits: a preview render that failed, audio that did not start,
175
+ * a refresh after an edit. The bridge keeps running after each.
176
+ */
177
+ readonly onError?: (error: unknown) => void;
178
+ /**
179
+ * The engine's asset decisions (fingerprint comparison, conform). Defaults to the packaged wasm
180
+ * module, loaded on first use.
181
+ */
182
+ readonly assetDecisions?: AssetBinding;
183
+ }
184
+ /** Options of `BrowserBridge.startExport`. The file is an MP4. */
185
+ export interface BrowserExportOptions {
186
+ /**
187
+ * Default `avc`. Whether this browser encodes it is the browser's to say ({@link
188
+ * BrowserBridge.videoEncoders}); an export with one it does not is refused before it renders, as
189
+ * `INVALID_INPUT`.
190
+ */
191
+ readonly videoCodec?: "avc" | "hevc" | "vp9" | "av1";
192
+ /**
193
+ * One of the engine's quality levels (`very-low`, `low`, `medium`, `high`, `very-high`),
194
+ * default `high`. The engine resolves it to a bitrate for the codec, size, and frame rate,
195
+ * as it does for a native export.
196
+ */
197
+ readonly videoQuality?: string;
198
+ /** An engine quality level for the audio, default `high`. */
199
+ readonly audioQuality?: string;
200
+ /**
201
+ * Default `true`. Audio is written only when an audible source is shown. An export with
202
+ * audio is refused before it renders on a browser that encodes neither AAC nor Opus.
203
+ */
204
+ readonly includeAudio?: boolean;
205
+ /**
206
+ * The exact rate to export at instead of the project's, frames per second as `num / den`
207
+ * (`{ num: 30000, den: 1001 }` for 29.97), as the project states its own: both backends export
208
+ * exactly this rate. One the engine cannot read (`num` and `den` positive 32-bit integers, a
209
+ * frame at least one tick long) is refused when the export starts, with an `EditorError`
210
+ * `invalid_frame_rate`.
211
+ */
212
+ readonly frameRate?: {
213
+ readonly num: number;
214
+ readonly den: number;
215
+ };
216
+ /**
217
+ * `original` (the default) reads originals and refuses without them; `proxies` reads fresh
218
+ * proxies where there are some.
219
+ */
220
+ readonly media?: "original" | "proxies";
221
+ /**
222
+ * Where the file is written. `opfs` (the default where the browser supports it) streams it to a
223
+ * temporary origin-private file, which the job's artifact holds until released; `file` streams it
224
+ * into a file the user picked (`showSaveFilePicker`, obtained during the click that started the
225
+ * export); `memory` keeps it in memory, for small outputs only: the export is refused before it
226
+ * starts when its estimated size, with room for the buffer's growth and copies, passes `maxBytes`
227
+ * (default 512 MiB). Without a disk API the export falls back to `memory` under the same limit,
228
+ * never to an unbounded buffer.
229
+ */
230
+ readonly output?: ExportOutputTarget;
231
+ /**
232
+ * `inFlightBytes` bounds the rendered frames the export holds at once (GPU readbacks and the
233
+ * copies queued for the encoder), default 128 MiB. The export submits a frame only when it fits,
234
+ * gives back the renderer's idle GPU memory when the budget stops it, and is refused before it
235
+ * starts when one frame's readback and copy cannot fit. The result's `performance.memory` reports
236
+ * the budget, the least one frame needed, the most held, and how often the budget waited.
237
+ */
238
+ readonly memory?: {
239
+ readonly inFlightBytes?: number;
240
+ };
241
+ }
242
+ /** Where a browser export writes its file. */
243
+ export type ExportOutputTarget = {
244
+ readonly kind: "opfs";
245
+ } | {
246
+ readonly kind: "file";
247
+ readonly handle: FileSystemFileHandle;
248
+ } | {
249
+ readonly kind: "memory";
250
+ readonly maxBytes?: number;
251
+ };
252
+ /** A source's proxy, as the bridge keeps it. */
253
+ export interface ProxyStatus {
254
+ /** Whether a proxy made from the recorded media is kept. */
255
+ readonly available: boolean;
256
+ /** Progress of one being made, from 0 to 1, or `null`. */
257
+ readonly generating: number | null;
258
+ /** What preview reads for the source now. */
259
+ readonly reading: "original" | "proxy" | "unavailable";
260
+ }
261
+ /** A proxy kept in this browser's storage, by its original's SHA-256. */
262
+ export interface KeptProxy {
263
+ readonly hash: string;
264
+ readonly bytes: number;
265
+ }
266
+ /** What a proxy removal did: the hashes removed, and those left because a page reads them. */
267
+ export interface ProxyRemoval {
268
+ readonly removed: readonly string[];
269
+ readonly inUse: readonly string[];
270
+ }
271
+ /**
272
+ * The browser runtime of one editor session, made by `createBrowserBridge`. Times are integer
273
+ * ticks (120000 per second). Methods that change the document dispatch through the session, so
274
+ * they are undoable.
275
+ */
276
+ export interface BrowserBridge {
277
+ /** Where the preview renders: nowhere until `bindPreview`, then a worker or the main thread. */
278
+ readonly previewBackend: "unbound" | "worker" | "main-thread";
279
+ /** How many times the preview was made again after its GPU device or WebGL context was lost. */
280
+ readonly previewRecoveries: number;
281
+ /** What this page can do; `gpu` and `color` are `null` until a preview is bound. */
282
+ readonly capabilities: CapabilityReport<null, null> & {
283
+ readonly features: Readonly<Record<"preview" | "audioPreview" | "transportRate" | "worker" | "export", Capability>>;
284
+ };
285
+ /** The playhead. */
286
+ readonly tick: number;
287
+ readonly playing: boolean;
288
+ /** Runtime resources currently held (see `BrowserBridgeOptions.resourceLimit`). */
289
+ readonly resourceCount: number;
290
+ /**
291
+ * Preview output volume from 0 to 1; a monitor control, not part of the project or exports.
292
+ * The bridge keeps it: set before a preview is bound, or across bindings, it applies to every
293
+ * preview's sound. Throws for a value outside that range.
294
+ */
295
+ setMonitorVolume(value: number): void;
296
+ /** The monitor volume `setMonitorVolume` last set; 1 until then. */
297
+ readonly monitorVolume: number;
298
+ /** Logs every source upload of the preview engine to the console, for debugging. */
299
+ setTraceUploads(value: boolean): void;
300
+ /** The preview engine's latest diagnostics sample (taken at most every 250 ms), or `null`. */
301
+ readonly diagnostics: Readonly<Record<string, unknown>> | null;
302
+ /** The engine's built-in effects and transitions; `null` until a preview is bound. */
303
+ readonly catalog: BuiltinEffectCatalog | null;
304
+ /**
305
+ * What preview reads for source `id` of the draft: its original, or the kept proxy standing in
306
+ * while the original is offline; opened with the provider settings the document names. Use {@link
307
+ * BrowserBridge.hasOriginal} to ask whether the original itself is linked.
308
+ */
309
+ getAsset(id: string): RuntimeAsset | null;
310
+ /**
311
+ * Notifies when derived runtime data (such as waveform peaks) becomes available for an already
312
+ * imported asset.
313
+ */
314
+ subscribeAssets(listener: () => void): () => void;
315
+ /**
316
+ * Why the viewer holds its last frame instead of the current one, or `null` when it is current: a
317
+ * composition the playhead shows cannot draw its output yet.
318
+ */
319
+ readonly previewIssue: string | null;
320
+ /** Notifies when {@link previewIssue} changes. */
321
+ subscribePreview(listener: () => void): () => void;
322
+ /**
323
+ * Draws the preview on `canvas`. Rejects only when the surface cannot be bound (the GPU would not
324
+ * start); a first frame that cannot render, such as one whose media is not linked yet, goes to
325
+ * `onError` like any later frame and is drawn by the next edit or seek. A preview worker that
326
+ * fails, to start or later, is given up for the main-thread renderer, which draws on the same
327
+ * surface: `previewBackend` then says `main-thread` and `onError` hears why, once, as an
328
+ * `EditorError` `preview_worker_failed` (a worker that lost its GPU is recovered from without a
329
+ * report, as a lost GPU on the main thread is). A given-up worker is not started again until the
330
+ * next `bindPreview`, not even by a preview made again after a lost GPU.
331
+ */
332
+ bindPreview(canvas: HTMLCanvasElement | OffscreenCanvas): Promise<{
333
+ readonly canvas: HTMLCanvasElement | OffscreenCanvas;
334
+ dispose(): Promise<void>;
335
+ }>;
336
+ /**
337
+ * Stages `files` and adds them to the document in one undoable transaction. With `relinkId`,
338
+ * the single file replaces that asset's media, keeping its ID and clips.
339
+ *
340
+ * Rejects when staging fails, when `signal` aborts, when the session loads another project
341
+ * meanwhile (`stale_import`), for an unknown relink target (`missing_asset`), and for a relink
342
+ * that is not one file of the same kind and recorded media (`relink_conflict`). Nothing is added
343
+ * when any file fails.
344
+ */
345
+ importFiles(files: readonly File[], options?: {
346
+ signal?: AbortSignal;
347
+ relinkId?: string;
348
+ }): Promise<{
349
+ assetIds: string[];
350
+ }>;
351
+ /** `importFiles([file], { relinkId: id })`. */
352
+ relink(id: string, file: File, options?: {
353
+ signal?: AbortSignal;
354
+ }): Promise<{
355
+ assetIds: string[];
356
+ }>;
357
+ /**
358
+ * Imports numbered PNGs as one image sequence at `frameRate` (the project's by default). A gap in
359
+ * the numbering is refused unless `missing` holds or blanks it.
360
+ */
361
+ importSequence(files: readonly File[], options?: {
362
+ frameRate?: {
363
+ readonly num: number;
364
+ readonly den: number;
365
+ };
366
+ missing?: "reject" | "hold" | "blank";
367
+ signal?: AbortSignal;
368
+ }): Promise<{
369
+ assetIds: string[];
370
+ }>;
371
+ /**
372
+ * Relinks an image sequence to its frames, at the frame rate and gap rule the project recorded:
373
+ * the asset keeps its ID and clips, and the engine decides whether the frames are the sequence it
374
+ * recorded. Refused for an asset that is not an image sequence.
375
+ */
376
+ relinkSequence(id: string, files: readonly File[], options?: {
377
+ signal?: AbortSignal;
378
+ }): Promise<{
379
+ assetIds: string[];
380
+ }>;
381
+ /**
382
+ * Moves the playhead to `tick`, pausing playback, and renders that frame. Resolves `true` when
383
+ * the frame was drawn and `false` when a later seek or edit superseded it or nothing is bound.
384
+ * Rejects for a tick that is not a non-negative safe integer (`invalid_time`) and when the
385
+ * frame fails to render.
386
+ */
387
+ seek(tick: number): Promise<boolean>;
388
+ /**
389
+ * Plays from the playhead at `rate` (negative plays backwards) under a playback `policy`
390
+ * (default `drop_video_keep_audio`), stopping at the end of the export range (else of the
391
+ * content), or looping with `loop`. Sound plays only at rate 1 under a policy that allows it;
392
+ * when it cannot start within 3 s the picture plays silently and `onError` hears why. Rejects
393
+ * for a zero or non-finite rate (`invalid_rate`) and an unknown policy (`invalid_policy`).
394
+ */
395
+ play(rate?: number, options?: {
396
+ loop?: boolean;
397
+ policy?: PlaybackPolicy;
398
+ }): Promise<void>;
399
+ /** Stops playback and audio; the playhead stays where it was. */
400
+ pause(): void;
401
+ /**
402
+ * Reads a subtitle file (`.srt`, or `.vtt` for WebVTT) into a captions asset in the bin
403
+ * (`captionsAsset`); `skipped` counts blocks that were not cues. Nothing reaches the timeline
404
+ * until the asset is inserted (`captionTrackCommands`).
405
+ *
406
+ * Throws an `EditorError` (`invalid_captions`) for a file larger than `MAX_CAPTION_FILE_BYTES`,
407
+ * which is not read, and for one the engine refuses: a WebVTT file without its header, more than
408
+ * `MAX_CAPTION_FILE_CUES` cues, or cues that need more caption tracks than a project holds.
409
+ */
410
+ importCaptions(file: File): Promise<{
411
+ assetId: string;
412
+ skipped: number;
413
+ }>;
414
+ /**
415
+ * The font families caption styles can name in `font_family`: those of the document's font assets
416
+ * and the runtime's fonts, in fallback order, each once, as the engine reads them from the fonts'
417
+ * name tables.
418
+ */
419
+ captionFontFamilies(): Promise<string[]>;
420
+ /**
421
+ * The files a native export of `document` (the current one by default) needs, for upload:
422
+ * shown media (or their proxies with `media: "proxies"`), an image sequence's frames, font
423
+ * files, LUTs, and text rendered to PNG. Rejects as `startExport` does when the media is not
424
+ * ready (`ConformError`) or the document does not compile.
425
+ */
426
+ nativeAssets(document?: import("../core/document.js").EditorDocument, options?: Pick<BrowserExportOptions, "media">): Promise<import("../native-client/index.js").NativeAsset[]>;
427
+ /**
428
+ * Whether the document's media is ready for `purpose`, as the engine decides from this session's
429
+ * originals and kept proxies.
430
+ */
431
+ conform(purpose: MediaPurpose, document?: import("../core/document.js").EditorDocument): Promise<ConformReport>;
432
+ /**
433
+ * Makes and keeps a proxy of a source whose original this session holds. Proxies are made one
434
+ * at a time and never beside an export: this waits for a running export and for a proxy of
435
+ * another source being made, and an export that starts stops the conversion, which starts again
436
+ * from the beginning once the export ends (`proxyStatus` shows its progress back at 0). Rejects
437
+ * for a source without a single video file (`unsupported_media`, including HDR video), without
438
+ * its original in this session (`missing_asset`), with a proxy of it already being made
439
+ * (`proxy_busy`), or when `signal` aborts.
440
+ */
441
+ generateProxy(id: string, options?: {
442
+ signal?: AbortSignal;
443
+ }): Promise<void>;
444
+ /** Whether a source has a kept proxy, the progress of one being made, and what preview reads. */
445
+ proxyStatus(id: string): ProxyStatus;
446
+ /**
447
+ * Which video codecs this browser encodes for an export of the current document (its size and
448
+ * frame rate) at `videoQuality` (default `high`). WebCodecs leaves the codecs to the browser;
449
+ * an export with one answered `false` is refused before it renders (`INVALID_INPUT`).
450
+ */
451
+ videoEncoders(options?: {
452
+ readonly videoQuality?: string;
453
+ }): Promise<Readonly<Record<NonNullable<BrowserExportOptions["videoCodec"]>, boolean>>>;
454
+ /**
455
+ * The proxies this browser keeps, for every project: each original's SHA-256 and the bytes its
456
+ * proxy takes.
457
+ */
458
+ listProxies(): Promise<KeptProxy[]>;
459
+ /**
460
+ * Removes the kept proxies of `hashes` (originals' SHA-256). This session lets go of its own
461
+ * first and refreshes the preview; a proxy still read after that (by the preview, for a source
462
+ * whose original is offline, by an export, or by another page of the origin) is left and listed
463
+ * in `inUse`.
464
+ */
465
+ removeProxies(hashes: Iterable<string>): Promise<ProxyRemoval>;
466
+ /**
467
+ * Whether this session holds the original media of asset `id` at the document's content revision;
468
+ * a proxy standing in for it does not count.
469
+ */
470
+ hasOriginal(id: string): boolean;
471
+ /**
472
+ * Shows a composition node in the viewer instead of the composition's output, for preview only;
473
+ * `null` shows the outputs.
474
+ */
475
+ setPreviewOutput(target: {
476
+ readonly compositionId: string;
477
+ readonly nodeId: string;
478
+ } | null): void;
479
+ /** The node {@link BrowserBridge.setPreviewOutput} shows, or `null`. */
480
+ readonly previewOutput: {
481
+ readonly compositionId: string;
482
+ readonly nodeId: string;
483
+ } | null;
484
+ /**
485
+ * Shows another animation of a dotLottie source, keeping its clips. Throws `EditorError`
486
+ * `unsupported_media` for another kind of source or an animation the package lacks.
487
+ */
488
+ selectAnimation(id: string, animation: string): void;
489
+ /**
490
+ * Reads an OpenEXR source's linear RGB in `primaries`, overriding what the file declares; `null`
491
+ * goes back to the file's.
492
+ * Throws `EditorError` `unsupported_media` for a source whose primaries cannot be chosen.
493
+ */
494
+ setLinearPrimaries(id: string, primaries: import("alpha2").LinearPrimaries | null): void;
495
+ /**
496
+ * Exports the document as it is now; later edits do not affect the job. The engine's asset
497
+ * decisions must be loaded: call {@link BrowserBridge.conform} first, or pass `assetDecisions`.
498
+ *
499
+ * Throws synchronously when the bridge is disposed (`disposed`), another export runs
500
+ * (`export_busy`), `frameRate` is not one the engine reads (`invalid_frame_rate`), the asset
501
+ * decisions are not loaded (`conform_pending`), the media is not ready (`ConformError`), or the
502
+ * document does not compile. Everything later is reported through the job's `result`.
503
+ */
504
+ startExport(options?: BrowserExportOptions): ExportJob;
505
+ /**
506
+ * Cancels exports and imports, stops playback, and releases the preview, audio, and every
507
+ * runtime resource. Idempotent; later calls reject or throw `disposed`.
508
+ */
509
+ dispose(): Promise<void>;
510
+ }
511
+ /** Options of `createWorkerPreview`. */
512
+ export interface WorkerPreviewOptions {
513
+ /** `seek` returns the rendered frame as an `ImageBitmap`, default `false`. */
514
+ readonly bitmapOutput?: boolean;
515
+ /** Initial size of the worker's own canvas when no `canvas` is given, default 16x16. */
516
+ readonly width?: number;
517
+ readonly height?: number;
518
+ /** Tags every message; replies for another session are dropped. A random UUID by default. */
519
+ readonly sessionId?: string;
520
+ readonly runtimeAssets?: RuntimeAssets;
521
+ /** A canvas to render into, transferred to the worker. */
522
+ readonly canvas?: OffscreenCanvas;
523
+ }
524
+ /** The main-thread side of a preview renderer running in a worker. */
525
+ export interface WorkerPreview {
526
+ /** Settles when the worker's engine has started; rejects if it cannot start. */
527
+ readonly ready: Promise<void>;
528
+ /**
529
+ * Loads `project`. `assets` are the runtime assets it adds or changes; `keep` names those the
530
+ * previous call sent that stay as they were, so their decoders stay open. Any other asset is
531
+ * released. `fonts: null` keeps the registered fonts.
532
+ */
533
+ replaceProject(project: Project, revision: number, assets?: readonly RuntimeAsset[], fonts?: readonly RuntimeFont[] | null, keep?: readonly string[]): Promise<void>;
534
+ /**
535
+ * Renders the frame at `tick`. `rendered` is `false` for an empty project or a render
536
+ * cancelled meanwhile. `bitmap` is present only with `bitmapOutput`, and the caller owns it.
537
+ */
538
+ seek(tick: number): Promise<{
539
+ rendered: boolean;
540
+ bitmap?: ImageBitmap;
541
+ diagnostics: Readonly<Record<string, number>>;
542
+ }>;
543
+ /** Mixes `frames` project-rate samples from `startSample`, one array per channel. */
544
+ mix(startSample: number, frames: number): Promise<Float32Array[]>;
545
+ /** Drops the render in flight; its `seek` resolves with `rendered: false`. */
546
+ cancel(): Promise<void>;
547
+ /** Releases the worker's engine and terminates the worker. Idempotent. */
548
+ dispose(): Promise<void>;
549
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { installEditorWorker } from "./worker.js";
2
+ installEditorWorker(self);
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Serves the editor's preview protocol (`createWorkerPreview`) on `scope`, a dedicated worker's
3
+ * global. Importing this module has no effect until this is called. Requests run one at a
4
+ * time in arrival order. A `cancel` or `replace-project` stops the render in flight and drops the
5
+ * seeks that arrived before it, not those sent after it. Requests from another session or an
6
+ * older revision are answered with an error.
7
+ * @param {import("./types.js").EditorWorkerScope} scope
8
+ * @returns {{ dispose(): Promise<void> }} Waits for queued requests, releases the engine and
9
+ * decoders, and detaches the message handler.
10
+ */
11
+ export function installEditorWorker(scope: import("./types.js").EditorWorkerScope): {
12
+ dispose(): Promise<void>;
13
+ };
14
+ /**
15
+ * Drives a preview renderer in `worker`, which must run `installEditorWorker`. The caller owns
16
+ * the worker; `dispose()` terminates it. This port renders picture and mixes audio blocks only:
17
+ * it is separate from a bridge's main-thread audio output. Every call waits for `ready`, which
18
+ * rejects if the worker cannot start its engine; a disposed preview rejects new calls, and a
19
+ * worker error rejects every pending one.
20
+ * @param {Worker} worker
21
+ * @param {import("./types.js").WorkerPreviewOptions} [options]
22
+ * @returns {import("./types.js").WorkerPreview}
23
+ */
24
+ export function createWorkerPreview(worker: Worker, { sessionId, runtimeAssets, canvas, bitmapOutput, width, height, }?: import("./types.js").WorkerPreviewOptions): import("./types.js").WorkerPreview;