@alpha2-sh/editor 0.0.0-stage → 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 (99) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +108 -2
  3. package/dist/browser/bridge.d.ts +44 -0
  4. package/dist/browser/bridge.js +2176 -0
  5. package/dist/browser/extensions-worker-entry.d.ts +1 -0
  6. package/dist/browser/extensions-worker-entry.js +3 -0
  7. package/dist/browser/extensions-worker.d.ts +46 -0
  8. package/dist/browser/extensions-worker.js +149 -0
  9. package/dist/browser/hash-worker-entry.d.ts +1 -0
  10. package/dist/browser/hash-worker-entry.js +3 -0
  11. package/dist/browser/hash-worker.d.ts +24 -0
  12. package/dist/browser/hash-worker.js +87 -0
  13. package/dist/browser/index.d.ts +11 -0
  14. package/dist/browser/index.js +9 -0
  15. package/dist/browser/jobs.d.ts +82 -0
  16. package/dist/browser/jobs.js +291 -0
  17. package/dist/browser/resources.d.ts +40 -0
  18. package/dist/browser/resources.js +83 -0
  19. package/dist/browser/runtime/assets.d.ts +233 -0
  20. package/dist/browser/runtime/assets.js +633 -0
  21. package/dist/browser/runtime/audio.d.ts +60 -0
  22. package/dist/browser/runtime/audio.js +549 -0
  23. package/dist/browser/runtime/budget.d.ts +11 -0
  24. package/dist/browser/runtime/budget.js +26 -0
  25. package/dist/browser/runtime/caption-fonts.d.ts +34 -0
  26. package/dist/browser/runtime/caption-fonts.js +69 -0
  27. package/dist/browser/runtime/color.d.ts +7 -0
  28. package/dist/browser/runtime/color.js +12 -0
  29. package/dist/browser/runtime/engine.d.ts +91 -0
  30. package/dist/browser/runtime/engine.js +352 -0
  31. package/dist/browser/runtime/export-audio.d.ts +23 -0
  32. package/dist/browser/runtime/export-audio.js +75 -0
  33. package/dist/browser/runtime/exporter.d.ts +140 -0
  34. package/dist/browser/runtime/exporter.js +751 -0
  35. package/dist/browser/runtime/extension-import.d.ts +196 -0
  36. package/dist/browser/runtime/extension-import.js +521 -0
  37. package/dist/browser/runtime/fingerprint.d.ts +57 -0
  38. package/dist/browser/runtime/fingerprint.js +157 -0
  39. package/dist/browser/runtime/generators.d.ts +188 -0
  40. package/dist/browser/runtime/generators.js +173 -0
  41. package/dist/browser/runtime/locks.d.ts +32 -0
  42. package/dist/browser/runtime/locks.js +86 -0
  43. package/dist/browser/runtime/output.d.ts +87 -0
  44. package/dist/browser/runtime/output.js +230 -0
  45. package/dist/browser/runtime/preview-utils.d.ts +3 -0
  46. package/dist/browser/runtime/preview-utils.js +49 -0
  47. package/dist/browser/runtime/proxies.d.ts +72 -0
  48. package/dist/browser/runtime/proxies.js +369 -0
  49. package/dist/browser/runtime/proxy-storage.d.ts +59 -0
  50. package/dist/browser/runtime/proxy-storage.js +119 -0
  51. package/dist/browser/runtime/sources.d.ts +82 -0
  52. package/dist/browser/runtime/sources.js +819 -0
  53. package/dist/browser/runtime/staging.d.ts +10 -0
  54. package/dist/browser/runtime/staging.js +32 -0
  55. package/dist/browser/runtime/still.d.ts +21 -0
  56. package/dist/browser/runtime/still.js +52 -0
  57. package/dist/browser/runtime/wasm.d.ts +9 -0
  58. package/dist/browser/runtime/wasm.js +20 -0
  59. package/dist/browser/types.d.ts +549 -0
  60. package/dist/browser/types.js +1 -0
  61. package/dist/browser/worker-entry.d.ts +1 -0
  62. package/dist/browser/worker-entry.js +2 -0
  63. package/dist/browser/worker.d.ts +24 -0
  64. package/dist/browser/worker.js +239 -0
  65. package/dist/core/captions.d.ts +34 -0
  66. package/dist/core/captions.js +108 -0
  67. package/dist/core/clip-time.d.ts +31 -0
  68. package/dist/core/clip-time.js +125 -0
  69. package/dist/core/commands.d.ts +413 -0
  70. package/dist/core/commands.js +1118 -0
  71. package/dist/core/compositions.d.ts +234 -0
  72. package/dist/core/compositions.js +851 -0
  73. package/dist/core/document.d.ts +245 -0
  74. package/dist/core/document.js +683 -0
  75. package/dist/core/keyframes.d.ts +82 -0
  76. package/dist/core/keyframes.js +153 -0
  77. package/dist/core/presets.d.ts +64 -0
  78. package/dist/core/presets.js +241 -0
  79. package/dist/core/session.d.ts +150 -0
  80. package/dist/core/session.js +541 -0
  81. package/dist/core/text.d.ts +17 -0
  82. package/dist/core/text.js +17 -0
  83. package/dist/core/time.d.ts +19 -0
  84. package/dist/core/time.js +39 -0
  85. package/dist/core/timeline-index.d.ts +44 -0
  86. package/dist/core/timeline-index.js +59 -0
  87. package/dist/core/transitions.d.ts +20 -0
  88. package/dist/core/transitions.js +118 -0
  89. package/dist/core/validated.d.ts +23 -0
  90. package/dist/core/validated.js +52 -0
  91. package/dist/index.d.ts +12 -0
  92. package/dist/index.js +11 -0
  93. package/dist/native-client/index.d.ts +131 -0
  94. package/dist/native-client/index.js +354 -0
  95. package/dist/ports/index.d.ts +146 -0
  96. package/dist/ports/index.js +1 -0
  97. package/dist/react/index.d.ts +37 -0
  98. package/dist/react/index.js +94 -0
  99. package/package.json +79 -4
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2026 Alpha2 contributors
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,109 @@
1
- # Temporary Holding Version
1
+ # @alpha2-sh/editor
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An editing SDK for alpha2: editing sessions over the engine's project document, with typed commands, validation and undo, and a browser bridge that previews, plays and exports the document with the [`alpha2`](https://github.com/alpha2-sh/alpha2/blob/main/packages/alpha2/README.md) engine.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install @alpha2-sh/editor alpha2
9
+ ```
10
+
11
+ `alpha2` is a peer dependency at the same version as this package. React is an optional peer, needed only for `@alpha2-sh/editor/react` (React 19.3 or a later 19). The browser requirements are `alpha2`'s.
12
+
13
+ ## Documents and commands
14
+
15
+ The root import is the editing core. It loads no DOM, React, WebAssembly or audio, so it also runs in Node.js.
16
+
17
+ ```js
18
+ import { createEditor, createEmptyDocument, serializeDocument, parseDocument } from "@alpha2-sh/editor";
19
+
20
+ const editor = createEditor({ document: createEmptyDocument({ width: 1280, height: 720 }) });
21
+ const result = editor.dispatch({
22
+ type: "track.add",
23
+ track: { id: "video", name: "Video", kind: "video", clips: [] },
24
+ });
25
+ if (!result.ok) throw result.error; // an EditorError with a `code`
26
+ editor.undo();
27
+ editor.redo();
28
+ const json = serializeDocument(editor.document); // portable JSON; media bytes stay apart
29
+ const reopened = parseDocument(json);
30
+ editor.dispose();
31
+ ```
32
+
33
+ - An editor document holds an engine project (`document.project`), the editor's metadata, and a descriptor of each asset. `serializeDocument` and `parseDocument` write and read it as JSON; `parseDocument` also reads a plain engine project.
34
+ - `dispatch` applies one `Command` (the typed union covers the project, tracks, clips, effects, transitions, caption cues, composition graphs, assets and markers); a `transaction` applies several and is checked once, by the document it ends with. A command the document's rules refuse returns `{ ok: false, error }` and changes nothing. `canExecute` asks without applying.
35
+ - Every change that commits is one undo step. The history keeps up to 120 steps and 64 MiB by default (`createEditor({ historyLimit, historyByteLimit })`).
36
+ - `beginGesture()` previews a drag: each `update(command)` shows a candidate in `editor.draft` without touching the document or the history, and `commit()` adds one undo step (`cancel()` adds none).
37
+ - `subscribe`, `getSnapshot` and `subscribeSelector` notify views of changes. A refusal is an `EditorError`, whose `code` says which check failed.
38
+
39
+ ## Browser bridge
40
+
41
+ `@alpha2-sh/editor/browser` connects a session to the engine in the browser: import, preview, playback with audio, and export to an MP4 file through WebCodecs.
42
+
43
+ ```js
44
+ import { createEditor, createEmptyDocument } from "@alpha2-sh/editor";
45
+ import { createBrowserBridge } from "@alpha2-sh/editor/browser";
46
+
47
+ const editor = createEditor({ document: createEmptyDocument({ width: 1280, height: 720 }) });
48
+ const bridge = createBrowserBridge({
49
+ editor,
50
+ // URLs of alpha2/wasm/alpha2_wasm_bg.wasm, alpha2/wasm/alpha2_audio_worklet.wasm and
51
+ // alpha2/audio-worklet-processor, as the application's bundler serves them.
52
+ runtimeAssets: { wasmUrl, audioWasmUrl, workletUrl },
53
+ });
54
+ await bridge.bindPreview(canvas);
55
+
56
+ const { assetIds } = await bridge.importFiles(files); // from an <input type="file">
57
+ const trackId = crypto.randomUUID();
58
+ const placed = editor.dispatch({
59
+ type: "transaction",
60
+ commands: [
61
+ { type: "track.add", track: { id: trackId, kind: "video", name: "Video", clips: [] } },
62
+ {
63
+ type: "clip.insert",
64
+ trackId,
65
+ clip: {
66
+ id: crypto.randomUUID(),
67
+ source_id: assetIds[0],
68
+ timeline_range: { start: 0, end: 120000 },
69
+ source_range: { start: 0, end: 120000 },
70
+ time_map: { type: "forward" },
71
+ },
72
+ },
73
+ ],
74
+ });
75
+ if (!placed.ok) throw placed.error;
76
+ await bridge.seek(0);
77
+
78
+ const artifact = await bridge.startExport({ videoCodec: "avc" }).result;
79
+ // artifact.kind "file": a temporary file in the origin's private storage; release it once downloaded.
80
+ if (artifact.kind === "file") await artifact.release();
81
+
82
+ await bridge.dispose();
83
+ await editor.dispose();
84
+ ```
85
+
86
+ - Import checks each file with the engine (media, fonts, `.cube` LUTs, SRT and WebVTT captions through `importCaptions`) and adds it to the document in one undoable step. `importSequence` imports numbered PNG or OpenEXR files as one image sequence.
87
+ - `bindPreview` draws on a canvas. With `runtimeAssets.workerFactory`, a worker running the `@alpha2-sh/editor/preview-worker` entry renders the preview off the main thread; without one, or when the worker fails, the main thread does. `hashWorkerFactory` (`@alpha2-sh/editor/hash-worker`) and `extensionsWorkerFactory` (`@alpha2-sh/editor/extensions-worker`, with `extensionsWasmUrl`) move file hashing and SVG, animated image, Lottie and OpenEXR reading into workers too.
88
+ - `seek`, `play` and `pause` move the playhead; with audio, playback follows the audio clock. Audio preview needs a cross-origin isolated page; editing and video preview do not.
89
+ - `startExport` returns a job with `result`, progress (`subscribe`) and `cancel`. The output goes to a temporary file in the origin's private storage by default (`release()` deletes it), to a file the user picked (`output: { kind: "file", handle }`), or to memory (`output: { kind: "memory", maxBytes }`). Whether the browser encodes a codec is the browser's to say: `bridge.videoEncoders()` asks ahead, and an export with a codec the browser does not encode is refused before it renders.
90
+
91
+ ## React
92
+
93
+ `@alpha2-sh/editor/react` has `EditorProvider`, `useEditor`, `useEditorSelector(selector, equal?)` and `EditorPreview`, which binds a bridge's preview to a canvas it makes:
94
+
95
+ ```jsx
96
+ <EditorProvider editor={editor}>
97
+ <EditorPreview bridge={bridge} onError={reportError} />
98
+ </EditorProvider>
99
+ ```
100
+
101
+ The application owns the session: unmounting the provider does not dispose it.
102
+
103
+ ## Native export
104
+
105
+ `@alpha2-sh/editor/native-client` (`createNativeClient({ baseUrl })`) exports a document on an HTTP export service that the application runs, for example on top of [`@alpha2-sh/node`](https://github.com/alpha2-sh/alpha2/blob/main/packages/alpha2-node/README.md). It uploads the document's media (`bridge.nativeAssets`) and follows the job to a downloadable file.
106
+
107
+ ## License
108
+
109
+ MIT, copyright Alpha2 contributors.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The default media adapter: stages each file in its own `AssetLibrary`, apart from the
3
+ * bridge's live one, so a failed or cancelled import leaves nothing behind. Files an extension
4
+ * provider reads (SVG, animated images, Lottie, OpenEXR) are probed, opened and drawn for their
5
+ * thumbnail by `alpha2/extensions`, loaded from `extensionsWasmUrl`: in a worker
6
+ * `extensionsWorkerFactory` makes for each file, which a cancelled import or a call past
7
+ * `EXTENSIONS_CALL_TIMEOUT_MS` terminates, or, without one, on this thread. A font is checked with
8
+ * the engine's parser (`alpha2/wasm`, from `wasmUrl`) and also registered with the page's
9
+ * `FontFace` set. A file's content hash is made in a worker `hashWorkerFactory` makes, where there
10
+ * is one.
11
+ * @param {{ extensionsWasmUrl?: string | URL, wasmUrl?: string | URL, hashWorkerFactory?: () => Worker, extensionsWorkerFactory?: () => Worker }} [options]
12
+ * @returns {import("./types.js").BrowserMediaAdapter}
13
+ */
14
+ export function createMediaAdapter({ extensionsWasmUrl, wasmUrl, hashWorkerFactory, extensionsWorkerFactory, }?: {
15
+ extensionsWasmUrl?: string | URL;
16
+ wasmUrl?: string | URL;
17
+ hashWorkerFactory?: () => Worker;
18
+ extensionsWorkerFactory?: () => Worker;
19
+ }): import("./types.js").BrowserMediaAdapter;
20
+ /**
21
+ * Creates the browser runtime for an editor session: preview, playback, import, proxies and
22
+ * export. No GPU device, AudioContext, worker or decoder is created until `bindPreview`, an
23
+ * import, `play` or `startExport` needs one. The bridge registers itself as an owner of
24
+ * `editor`, so disposing the session disposes it.
25
+ * @param {import("./types.js").BrowserBridgeOptions} options
26
+ * @returns {import("./types.js").BrowserBridge}
27
+ */
28
+ export function createBrowserBridge(options: import("./types.js").BrowserBridgeOptions): import("./types.js").BrowserBridge;
29
+ /**
30
+ * An export refused before it rendered: the engine's conform report says why. The message names
31
+ * each source as `nameOf` does (the document's asset names), the report and `entityId` by ID.
32
+ */
33
+ export class ConformError extends EditorError {
34
+ /**
35
+ * @param {import("alpha2/assets").ConformReport} report
36
+ * @param {{ operation?: string, nameOf?: (sourceId: string) => string | undefined }} [options]
37
+ */
38
+ constructor(report: import("alpha2/assets").ConformReport, { operation, nameOf }?: {
39
+ operation?: string;
40
+ nameOf?: (sourceId: string) => string | undefined;
41
+ });
42
+ report: import("alpha2/assets").ConformReport;
43
+ }
44
+ import { EditorError } from "../core/document.js";