frameyard 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +117 -0
- package/GLOSSARY.md +46 -2
- package/README.md +174 -106
- package/dist/bindings.d.ts +42 -0
- package/dist/bindings.d.ts.map +1 -0
- package/dist/bindings.js +144 -0
- package/dist/bindings.js.map +1 -0
- package/dist/cli.js +32 -21
- package/dist/cli.js.map +1 -1
- package/dist/composition/adapter.d.ts +30 -0
- package/dist/composition/adapter.d.ts.map +1 -0
- package/dist/composition/adapter.js +2 -0
- package/dist/composition/adapter.js.map +1 -0
- package/dist/composition/animation.d.ts +19 -0
- package/dist/composition/animation.d.ts.map +1 -0
- package/dist/composition/animation.js +55 -0
- package/dist/composition/animation.js.map +1 -0
- package/dist/composition/attributes.d.ts +7 -0
- package/dist/composition/attributes.d.ts.map +1 -0
- package/dist/composition/attributes.js +24 -0
- package/dist/composition/attributes.js.map +1 -0
- package/dist/composition/descriptor.d.ts +30 -0
- package/dist/composition/descriptor.d.ts.map +1 -0
- package/dist/composition/descriptor.js +188 -0
- package/dist/composition/descriptor.js.map +1 -0
- package/dist/composition/diagnostics.d.ts +12 -0
- package/dist/composition/diagnostics.d.ts.map +1 -0
- package/dist/composition/diagnostics.js +38 -0
- package/dist/composition/diagnostics.js.map +1 -0
- package/dist/composition/index.d.ts +12 -0
- package/dist/composition/index.d.ts.map +1 -0
- package/dist/composition/index.js +7 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/composition/media.d.ts +27 -0
- package/dist/composition/media.d.ts.map +1 -0
- package/dist/composition/media.js +162 -0
- package/dist/composition/media.js.map +1 -0
- package/dist/composition/paths.d.ts +5 -0
- package/dist/composition/paths.d.ts.map +1 -0
- package/dist/composition/paths.js +16 -0
- package/dist/composition/paths.js.map +1 -0
- package/dist/composition/transcripts.d.ts +19 -0
- package/dist/composition/transcripts.d.ts.map +1 -0
- package/dist/composition/transcripts.js +57 -0
- package/dist/composition/transcripts.js.map +1 -0
- package/dist/composition/walk.d.ts +10 -0
- package/dist/composition/walk.d.ts.map +1 -0
- package/dist/composition/walk.js +32 -0
- package/dist/composition/walk.js.map +1 -0
- package/dist/contracts.d.ts +75 -47
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +14 -159
- package/dist/contracts.js.map +1 -1
- package/dist/errors.d.ts +15 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +8 -0
- package/dist/errors.js.map +1 -1
- package/dist/html/document-adapter.d.ts +5 -0
- package/dist/html/document-adapter.d.ts.map +1 -0
- package/dist/html/document-adapter.js +17 -0
- package/dist/html/document-adapter.js.map +1 -0
- package/dist/html/index.d.ts +5 -0
- package/dist/html/index.d.ts.map +1 -0
- package/dist/html/index.js +3 -0
- package/dist/html/index.js.map +1 -0
- package/dist/html/parse.d.ts +26 -0
- package/dist/html/parse.d.ts.map +1 -0
- package/dist/html/parse.js +80 -0
- package/dist/html/parse.js.map +1 -0
- package/dist/html/validate.d.ts +14 -0
- package/dist/html/validate.d.ts.map +1 -0
- package/dist/html/validate.js +648 -0
- package/dist/html/validate.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/preview/main.d.ts +10 -3
- package/dist/preview/main.d.ts.map +1 -1
- package/dist/preview/main.js +189 -89
- package/dist/preview/main.js.map +1 -1
- package/dist/project.d.ts +2 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +4 -0
- package/dist/project.js.map +1 -1
- package/dist/renderer/browser.d.ts +11 -1
- package/dist/renderer/browser.d.ts.map +1 -1
- package/dist/renderer/browser.js +93 -14
- package/dist/renderer/browser.js.map +1 -1
- package/dist/renderer/index.d.ts +25 -5
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +82 -16
- package/dist/renderer/index.js.map +1 -1
- package/dist/runtime/bindings.d.ts +11 -0
- package/dist/runtime/bindings.d.ts.map +1 -0
- package/dist/runtime/bindings.js +164 -0
- package/dist/runtime/bindings.js.map +1 -0
- package/dist/runtime/diagnostics.d.ts +4 -0
- package/dist/runtime/diagnostics.d.ts.map +1 -0
- package/dist/runtime/diagnostics.js +107 -0
- package/dist/runtime/diagnostics.js.map +1 -0
- package/dist/runtime/document-adapter.d.ts +4 -0
- package/dist/runtime/document-adapter.d.ts.map +1 -0
- package/dist/runtime/document-adapter.js +19 -0
- package/dist/runtime/document-adapter.js.map +1 -0
- package/dist/runtime/host.d.ts +14 -0
- package/dist/runtime/host.d.ts.map +1 -0
- package/dist/runtime/host.js +596 -0
- package/dist/runtime/host.js.map +1 -0
- package/dist/runtime/index.d.ts +0 -29
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +0 -360
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/media.d.ts.map +1 -1
- package/dist/runtime/media.js +20 -51
- package/dist/runtime/media.js.map +1 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +177 -84
- package/dist/scaffold.js.map +1 -1
- package/dist/server/composition-html.d.ts +20 -0
- package/dist/server/composition-html.d.ts.map +1 -0
- package/dist/server/composition-html.js +45 -0
- package/dist/server/composition-html.js.map +1 -0
- package/dist/server/preview-html.d.ts.map +1 -1
- package/dist/server/preview-html.js +19 -14
- package/dist/server/preview-html.js.map +1 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +94 -6
- package/dist/server/server.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/adr/0001-keep-composition-authoring-web-native.md +2 -0
- package/docs/adr/0006-seek-embedded-media-from-the-frame-clock.md +7 -1
- package/docs/adr/0007-make-html-documents-the-composition-unit.md +31 -0
- package/docs/adr/0008-share-the-composition-document-grammar.md +18 -0
- package/docs/adr/0009-composite-production-frames-in-software.md +37 -0
- package/docs/migration-0.4.md +279 -0
- package/docs/v0.1-design.md +78 -56
- package/examples/demo/README.md +8 -4
- package/examples/demo/compositions/demo.controller.js +120 -0
- package/examples/demo/compositions/demo.html +253 -0
- package/examples/demo/video.config.js +1 -1
- package/examples/video/README.md +61 -0
- package/examples/video/assets/clip.mp4 +0 -0
- package/examples/video/assets/clip.webm +0 -0
- package/examples/video/compositions/video-mp4.html +362 -0
- package/examples/video/compositions/video.html +362 -0
- package/examples/video/props/video.json +8 -0
- package/examples/video/scripts/make-clip.sh +109 -0
- package/examples/video/video.config.js +6 -0
- package/examples/webgl/README.md +30 -0
- package/examples/webgl/compositions/webgl.controller.js +200 -0
- package/examples/webgl/compositions/webgl.html +215 -0
- package/examples/webgl/props/webgl.json +6 -0
- package/examples/webgl/video.config.js +5 -0
- package/package.json +7 -3
- package/skills/frameyard/README.md +4 -0
- package/skills/frameyard/SKILL.md +40 -12
- package/skills/frameyard/references/audio-assets.md +25 -14
- package/skills/frameyard/references/bindings.md +73 -0
- package/skills/frameyard/references/common-mistakes.md +59 -0
- package/skills/frameyard/references/controllers.md +126 -0
- package/skills/frameyard/references/deterministic-authoring.md +143 -52
- package/skills/frameyard/references/diagnostics.md +90 -0
- package/skills/frameyard/references/failure-recovery.md +37 -14
- package/skills/frameyard/references/json-results.md +43 -9
- package/skills/frameyard/references/subtitles-karaoke.md +10 -18
- package/examples/demo/compositions/demo.js +0 -206
package/dist/project.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export type CompositionKind = "html";
|
|
1
2
|
export interface ProjectComposition {
|
|
2
3
|
id: string;
|
|
3
4
|
/** Forward-slash relative path from the project root, without a leading "./". */
|
|
4
5
|
entry: string;
|
|
5
6
|
absoluteEntry: string;
|
|
7
|
+
kind: CompositionKind;
|
|
6
8
|
}
|
|
7
9
|
export interface Project {
|
|
8
10
|
root: string;
|
package/dist/project.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C;AAYD,gEAAgE;AAChE,wBAAsB,kBAAkB,CAAC,KAAK,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB/E;AAED,qFAAqF;AACrF,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C;AAYD,gEAAgE;AAChE,wBAAsB,kBAAkB,CAAC,KAAK,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB/E;AAED,qFAAqF;AACrF,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAsEvE"}
|
package/dist/project.js
CHANGED
|
@@ -77,10 +77,14 @@ export async function loadProject(projectRoot) {
|
|
|
77
77
|
if (!(await isFile(absoluteEntry))) {
|
|
78
78
|
throw new FrameyardError("CONFIG_INVALID", `Composition "${id}" entry does not exist: ${rawEntry}`);
|
|
79
79
|
}
|
|
80
|
+
if (path.extname(absoluteEntry).toLowerCase() !== ".html") {
|
|
81
|
+
throw new FrameyardError("CONFIG_INVALID", `Composition "${id}" entry must be an .html file: ${rawEntry}`);
|
|
82
|
+
}
|
|
80
83
|
compositions.set(id, {
|
|
81
84
|
id,
|
|
82
85
|
entry: path.relative(root, absoluteEntry).split(path.sep).join("/"),
|
|
83
86
|
absoluteEntry,
|
|
87
|
+
kind: "html",
|
|
84
88
|
});
|
|
85
89
|
}
|
|
86
90
|
return { root, configPath, compositions };
|
package/dist/project.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { type Browser } from "playwright";
|
|
2
|
-
import type { CompositionMetadata, Props, ResolvedAudioClip, ResolvedTranscriptClip } from "../contracts.js";
|
|
2
|
+
import type { CompositionDiagnostic, CompositionMetadata, CompositionSourceInfo, Props, ResolvedAudioClip, ResolvedTranscriptClip } from "../contracts.js";
|
|
3
3
|
export interface CompositionSession {
|
|
4
|
+
readonly entry: string;
|
|
5
|
+
readonly controller: {
|
|
6
|
+
kind: "inline";
|
|
7
|
+
} | {
|
|
8
|
+
kind: "external";
|
|
9
|
+
src: string;
|
|
10
|
+
} | null;
|
|
4
11
|
readonly metadata: CompositionMetadata;
|
|
5
12
|
readonly props: Props;
|
|
6
13
|
readonly audioClips: ResolvedAudioClip[];
|
|
@@ -8,6 +15,7 @@ export interface CompositionSession {
|
|
|
8
15
|
readonly transcriptClips: ResolvedTranscriptClip[];
|
|
9
16
|
seek(frame: number): Promise<void>;
|
|
10
17
|
capture(): Promise<Buffer>;
|
|
18
|
+
readDiagnostics(): Promise<CompositionDiagnostic[]>;
|
|
11
19
|
assertHealthy(): void;
|
|
12
20
|
close(): Promise<void>;
|
|
13
21
|
}
|
|
@@ -18,6 +26,8 @@ export declare function openCompositionSession(options: {
|
|
|
18
26
|
serverUrl: string;
|
|
19
27
|
entry: string;
|
|
20
28
|
props?: unknown;
|
|
29
|
+
info: CompositionSourceInfo;
|
|
30
|
+
staticDiagnostics: readonly CompositionDiagnostic[];
|
|
21
31
|
}): Promise<CompositionSession>;
|
|
22
32
|
export {};
|
|
23
33
|
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/renderer/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAmD,MAAM,YAAY,CAAC;AACrG,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/renderer/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAmD,MAAM,YAAY,CAAC;AACrG,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,EACL,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnF,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,iBAAiB,EAAE,CAAC;IACzC,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,sBAAsB,EAAE,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,eAAe,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpD,aAAa,IAAI,IAAI,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAqBD,eAAO,MAAM,YAAY,EAAE,MAAM,EAkBhC,CAAC;AAEF,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAElE,eAAO,MAAM,uBAAuB,EAAE,qBAOrC,CAAC;AAoDF,wBAAsB,sBAAsB,CAAC,OAAO,EAAE;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,iBAAiB,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACrD,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkP9B"}
|
package/dist/renderer/browser.js
CHANGED
|
@@ -13,6 +13,11 @@ export const BROWSER_ARGS = [
|
|
|
13
13
|
// software rasterizer shipped with the Playwright Chromium build.
|
|
14
14
|
"--use-angle=swiftshader",
|
|
15
15
|
"--enable-unsafe-swiftshader",
|
|
16
|
+
// SwiftShader already rasterizes WebGL in software. Routing every captured
|
|
17
|
+
// frame through GPU-process compositing adds a slow copy step without making
|
|
18
|
+
// the 2D output any less deterministic. Software compositing keeps WebGL on
|
|
19
|
+
// SwiftShader while removing that round trip. See ADR 0009.
|
|
20
|
+
"--disable-gpu-compositing",
|
|
16
21
|
];
|
|
17
22
|
export const BROWSER_CONTEXT_OPTIONS = {
|
|
18
23
|
viewport: { width: 1280, height: 720 },
|
|
@@ -51,6 +56,23 @@ async function closeQuietly(action) {
|
|
|
51
56
|
// Cleanup must not hide the original failure.
|
|
52
57
|
}
|
|
53
58
|
}
|
|
59
|
+
function diagnosticKey(diagnostic) {
|
|
60
|
+
return JSON.stringify([diagnostic.severity, diagnostic.code, diagnostic.message, diagnostic.details ?? null]);
|
|
61
|
+
}
|
|
62
|
+
function mergeDiagnostics(...groups) {
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
const result = [];
|
|
65
|
+
for (const group of groups) {
|
|
66
|
+
for (const diagnostic of group) {
|
|
67
|
+
const key = diagnosticKey(diagnostic);
|
|
68
|
+
if (!seen.has(key)) {
|
|
69
|
+
seen.add(key);
|
|
70
|
+
result.push(diagnostic);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
54
76
|
export async function openCompositionSession(options) {
|
|
55
77
|
let browser;
|
|
56
78
|
try {
|
|
@@ -66,7 +88,10 @@ export async function openCompositionSession(options) {
|
|
|
66
88
|
let page;
|
|
67
89
|
let cdp;
|
|
68
90
|
try {
|
|
69
|
-
context = await browser.newContext(
|
|
91
|
+
context = await browser.newContext({
|
|
92
|
+
...BROWSER_CONTEXT_OPTIONS,
|
|
93
|
+
viewport: { width: options.info.metadata.width, height: options.info.metadata.height },
|
|
94
|
+
});
|
|
70
95
|
page = await context.newPage();
|
|
71
96
|
page.setDefaultTimeout(60_000);
|
|
72
97
|
const pageErrors = [];
|
|
@@ -76,22 +101,50 @@ export async function openCompositionSession(options) {
|
|
|
76
101
|
page.on("crash", () => {
|
|
77
102
|
pageErrors.push("The browser page crashed.");
|
|
78
103
|
});
|
|
79
|
-
|
|
104
|
+
const compositionUrl = new URL(options.entry, options.serverUrl);
|
|
105
|
+
compositionUrl.searchParams.set("__fy-manual", "1");
|
|
106
|
+
await page.goto(compositionUrl.href, {
|
|
80
107
|
waitUntil: "domcontentloaded",
|
|
81
108
|
timeout: 60_000,
|
|
82
109
|
});
|
|
83
|
-
await page.waitForFunction(() => Boolean(window.
|
|
110
|
+
await page.waitForFunction(() => Boolean(window.__fy) ||
|
|
111
|
+
Boolean(window.__fyError), undefined, { timeout: 30_000 });
|
|
112
|
+
const initError = await page.evaluate(() => window.__fyError);
|
|
113
|
+
if (initError) {
|
|
114
|
+
throw new FrameyardError(initError.code, initError.message, {
|
|
115
|
+
diagnostics: initError.diagnostics,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
84
118
|
let loaded;
|
|
85
119
|
try {
|
|
86
|
-
loaded = await page.evaluate(async ({
|
|
87
|
-
const api = window.
|
|
88
|
-
|
|
89
|
-
|
|
120
|
+
loaded = await page.evaluate(async ({ props }) => {
|
|
121
|
+
const api = window.__fy;
|
|
122
|
+
await api.ready;
|
|
123
|
+
await api.load({ props });
|
|
124
|
+
// A video painted at the load frame can stay cached in the compositor
|
|
125
|
+
// when an ancestor animates opacity. Keep the composition hidden until
|
|
126
|
+
// the first seek so the first visible paint is the requested frame.
|
|
127
|
+
document.querySelector("fy-composition")?.setAttribute("data-fy-pending", "");
|
|
128
|
+
return {
|
|
129
|
+
metadata: api.metadata,
|
|
130
|
+
props: api.props,
|
|
131
|
+
controller: api.controller,
|
|
132
|
+
audioClips: api.audioClips,
|
|
133
|
+
embeddedAudioClips: api.embeddedAudioClips,
|
|
134
|
+
transcriptClips: api.transcriptClips,
|
|
135
|
+
diagnostics: api.diagnostics,
|
|
136
|
+
};
|
|
137
|
+
}, { props: options.props });
|
|
90
138
|
}
|
|
91
139
|
catch (error) {
|
|
92
140
|
throw browserCommandError(error);
|
|
93
141
|
}
|
|
94
|
-
|
|
142
|
+
if (loaded.metadata.width !== options.info.metadata.width ||
|
|
143
|
+
loaded.metadata.height !== options.info.metadata.height ||
|
|
144
|
+
loaded.metadata.fps !== options.info.metadata.fps ||
|
|
145
|
+
loaded.metadata.durationInFrames !== options.info.metadata.durationInFrames) {
|
|
146
|
+
throw new FrameyardError("COMPOSITION_INVALID", `Composition "${options.entry}" metadata changed between static validation and browser load.`, { diagnostics: [...options.staticDiagnostics] });
|
|
147
|
+
}
|
|
95
148
|
try {
|
|
96
149
|
await page.waitForLoadState("networkidle", { timeout: 30_000 });
|
|
97
150
|
}
|
|
@@ -112,7 +165,14 @@ export async function openCompositionSession(options) {
|
|
|
112
165
|
}
|
|
113
166
|
};
|
|
114
167
|
assertHealthy();
|
|
168
|
+
let firstSeek = true;
|
|
115
169
|
const session = {
|
|
170
|
+
entry: options.entry,
|
|
171
|
+
controller: options.info.controller
|
|
172
|
+
? options.info.controller.kind === "inline"
|
|
173
|
+
? { kind: "inline" }
|
|
174
|
+
: { kind: "external", src: options.info.controller.src ?? "" }
|
|
175
|
+
: null,
|
|
116
176
|
metadata: loaded.metadata,
|
|
117
177
|
props: loaded.props,
|
|
118
178
|
audioClips: loaded.audioClips,
|
|
@@ -120,16 +180,31 @@ export async function openCompositionSession(options) {
|
|
|
120
180
|
transcriptClips: loaded.transcriptClips,
|
|
121
181
|
async seek(frame) {
|
|
122
182
|
assertHealthy();
|
|
183
|
+
const reveal = firstSeek;
|
|
184
|
+
firstSeek = false;
|
|
123
185
|
try {
|
|
124
|
-
await activePage.evaluate(async (targetFrame) => {
|
|
125
|
-
const api = window.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
186
|
+
await activePage.evaluate(async ({ targetFrame, reveal }) => {
|
|
187
|
+
const api = window.__fy;
|
|
188
|
+
try {
|
|
189
|
+
api.seek(targetFrame);
|
|
190
|
+
await api.settle();
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
if (reveal) {
|
|
194
|
+
document.querySelector("fy-composition")?.removeAttribute("data-fy-pending");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}, { targetFrame: frame, reveal });
|
|
129
198
|
}
|
|
130
199
|
catch (error) {
|
|
131
200
|
throw browserCommandError(error);
|
|
132
201
|
}
|
|
202
|
+
if (reveal) {
|
|
203
|
+
// Let the first visible paint happen before the caller captures.
|
|
204
|
+
await activePage.evaluate(() => new Promise((resolve) => {
|
|
205
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
133
208
|
assertHealthy();
|
|
134
209
|
},
|
|
135
210
|
async capture() {
|
|
@@ -156,11 +231,15 @@ export async function openCompositionSession(options) {
|
|
|
156
231
|
assertHealthy();
|
|
157
232
|
return Buffer.from(result.data, "base64");
|
|
158
233
|
},
|
|
234
|
+
async readDiagnostics() {
|
|
235
|
+
const runtime = await activePage.evaluate(() => window.__fy.diagnostics);
|
|
236
|
+
return mergeDiagnostics([...options.staticDiagnostics], runtime);
|
|
237
|
+
},
|
|
159
238
|
assertHealthy,
|
|
160
239
|
async close() {
|
|
161
240
|
await closeQuietly(async () => {
|
|
162
241
|
await activePage.evaluate(async () => {
|
|
163
|
-
const api = window.
|
|
242
|
+
const api = window.__fy;
|
|
164
243
|
await api?.dispose?.();
|
|
165
244
|
});
|
|
166
245
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/renderer/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAiE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/renderer/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/renderer/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompositionMetadata } from "../contracts.js";
|
|
1
|
+
import type { CompositionDiagnostic, CompositionMetadata } from "../contracts.js";
|
|
2
2
|
import type { Project } from "../project.js";
|
|
3
3
|
import { type AudioInspection } from "./audio.js";
|
|
4
4
|
import { type TranscriptInspection } from "./transcripts.js";
|
|
@@ -16,30 +16,51 @@ interface SessionOptions {
|
|
|
16
16
|
}
|
|
17
17
|
export interface CheckResult {
|
|
18
18
|
composition: string;
|
|
19
|
+
entry: string;
|
|
20
|
+
controller: {
|
|
21
|
+
kind: "inline";
|
|
22
|
+
} | {
|
|
23
|
+
kind: "external";
|
|
24
|
+
src: string;
|
|
25
|
+
} | null;
|
|
19
26
|
metadata: CompositionMetadata;
|
|
20
27
|
framesChecked: number;
|
|
21
28
|
audio: {
|
|
22
29
|
clips: number;
|
|
23
|
-
warnings: string[];
|
|
24
30
|
details: AudioInspection["clips"];
|
|
25
31
|
};
|
|
26
32
|
transcripts: {
|
|
27
33
|
clips: number;
|
|
28
|
-
warnings: string[];
|
|
29
34
|
details: TranscriptInspection["clips"];
|
|
30
35
|
};
|
|
36
|
+
diagnostics: CompositionDiagnostic[];
|
|
31
37
|
elapsedMs: number;
|
|
32
38
|
}
|
|
33
39
|
export interface StillResult {
|
|
34
40
|
composition: string;
|
|
41
|
+
entry: string;
|
|
42
|
+
controller: {
|
|
43
|
+
kind: "inline";
|
|
44
|
+
} | {
|
|
45
|
+
kind: "external";
|
|
46
|
+
src: string;
|
|
47
|
+
} | null;
|
|
35
48
|
frame: number;
|
|
36
49
|
path: string;
|
|
37
50
|
width: number;
|
|
38
51
|
height: number;
|
|
52
|
+
diagnostics: CompositionDiagnostic[];
|
|
39
53
|
elapsedMs: number;
|
|
40
54
|
}
|
|
41
55
|
export interface RenderResult {
|
|
42
56
|
composition: string;
|
|
57
|
+
entry: string;
|
|
58
|
+
controller: {
|
|
59
|
+
kind: "inline";
|
|
60
|
+
} | {
|
|
61
|
+
kind: "external";
|
|
62
|
+
src: string;
|
|
63
|
+
} | null;
|
|
43
64
|
path: string;
|
|
44
65
|
width: number;
|
|
45
66
|
height: number;
|
|
@@ -51,12 +72,11 @@ export interface RenderResult {
|
|
|
51
72
|
bytes: number;
|
|
52
73
|
audio: {
|
|
53
74
|
clips: number;
|
|
54
|
-
warnings: string[];
|
|
55
75
|
};
|
|
56
76
|
transcripts: {
|
|
57
77
|
clips: number;
|
|
58
|
-
warnings: string[];
|
|
59
78
|
};
|
|
79
|
+
diagnostics: CompositionDiagnostic[];
|
|
60
80
|
elapsedMs: number;
|
|
61
81
|
}
|
|
62
82
|
export declare const MAX_RENDER_CONCURRENCY = 16;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/renderer/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/renderer/index.ts"],"names":[],"mappings":"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"}
|
package/dist/renderer/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { FrameyardError, isFrameyardError } from "../errors.js";
|
|
6
|
+
import { validateHtmlComposition } from "../html/validate.js";
|
|
6
7
|
import { startPreviewServer } from "../server/server.js";
|
|
7
8
|
import { inspectTimelineAudio } from "./audio.js";
|
|
8
9
|
import { openCompositionSession } from "./browser.js";
|
|
@@ -20,17 +21,44 @@ export function validateRenderConcurrency(value) {
|
|
|
20
21
|
}
|
|
21
22
|
return concurrency;
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
+
function compositionFor(project, id) {
|
|
24
25
|
const composition = project.compositions.get(id);
|
|
25
26
|
if (!composition) {
|
|
26
27
|
const available = [...project.compositions.keys()].join(", ") || "(none)";
|
|
27
28
|
throw new FrameyardError("COMPOSITION_NOT_FOUND", `Composition "${id}" is not listed in video.config.js. Available: ${available}.`);
|
|
28
29
|
}
|
|
29
|
-
return composition
|
|
30
|
+
return composition;
|
|
30
31
|
}
|
|
31
32
|
function timelineAudioClips(session) {
|
|
32
33
|
return [...session.audioClips, ...session.embeddedAudioClips.map((clip) => ({ ...clip, allowSilent: true }))];
|
|
33
34
|
}
|
|
35
|
+
function audioDiagnostics(warnings) {
|
|
36
|
+
return warnings.map((message) => ({ severity: "warning", code: "AUDIO_WARNING", message }));
|
|
37
|
+
}
|
|
38
|
+
function transcriptDiagnostics(warnings) {
|
|
39
|
+
return warnings.map((message) => ({ severity: "warning", code: "TRANSCRIPT_WARNING", message }));
|
|
40
|
+
}
|
|
41
|
+
function diagnosticKey(diagnostic) {
|
|
42
|
+
return JSON.stringify([diagnostic.severity, diagnostic.code, diagnostic.message, diagnostic.details ?? null]);
|
|
43
|
+
}
|
|
44
|
+
function mergeDiagnostics(...groups) {
|
|
45
|
+
const seen = new Set();
|
|
46
|
+
const result = [];
|
|
47
|
+
for (const group of groups) {
|
|
48
|
+
for (const diagnostic of group) {
|
|
49
|
+
const key = diagnosticKey(diagnostic);
|
|
50
|
+
if (!seen.has(key)) {
|
|
51
|
+
seen.add(key);
|
|
52
|
+
result.push(diagnostic);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
async function readSessionDiagnostics(sessions) {
|
|
59
|
+
const groups = await Promise.all(sessions.map((session) => session.readDiagnostics()));
|
|
60
|
+
return mergeDiagnostics(...groups);
|
|
61
|
+
}
|
|
34
62
|
function throwIfAborted(signal) {
|
|
35
63
|
if (signal?.aborted) {
|
|
36
64
|
throw new FrameyardError("RENDER_FAILED", "Operation cancelled.");
|
|
@@ -74,44 +102,72 @@ async function publishFile(tempPath, outPath, overwrite) {
|
|
|
74
102
|
}
|
|
75
103
|
async function withSessions(options, resolveSessionCount, callback) {
|
|
76
104
|
throwIfAborted(options.signal);
|
|
77
|
-
const
|
|
105
|
+
const composition = compositionFor(options.project, options.compositionId);
|
|
106
|
+
const validation = await validateHtmlComposition({
|
|
107
|
+
projectRoot: options.project.root,
|
|
108
|
+
entry: composition.entry,
|
|
109
|
+
props: options.props,
|
|
110
|
+
});
|
|
111
|
+
const staticDiagnostics = validation.diagnostics;
|
|
112
|
+
const staticErrors = staticDiagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
113
|
+
if (!validation.info || staticErrors.length > 0) {
|
|
114
|
+
const first = staticErrors[0];
|
|
115
|
+
throw new FrameyardError(first?.code ?? "COMPOSITION_INVALID", `Composition "${options.compositionId}": ${first?.message ?? "static validation failed."}`, { diagnostics: validation.diagnostics });
|
|
116
|
+
}
|
|
117
|
+
const staticInfo = validation.info;
|
|
78
118
|
const server = await startPreviewServer({ projectRoot: options.project.root, port: 0 });
|
|
79
119
|
const sessions = [];
|
|
80
120
|
try {
|
|
81
121
|
try {
|
|
82
122
|
const open = async () => {
|
|
83
123
|
throwIfAborted(options.signal);
|
|
84
|
-
|
|
124
|
+
return openCompositionSession({
|
|
85
125
|
serverUrl: server.url,
|
|
86
|
-
entry,
|
|
126
|
+
entry: composition.entry,
|
|
87
127
|
props: options.props,
|
|
88
|
-
|
|
128
|
+
info: staticInfo,
|
|
129
|
+
staticDiagnostics,
|
|
130
|
+
});
|
|
89
131
|
};
|
|
90
|
-
await open();
|
|
132
|
+
sessions.push(await open());
|
|
91
133
|
const sessionCount = Math.max(1, resolveSessionCount(sessions[0]));
|
|
92
|
-
|
|
93
|
-
|
|
134
|
+
if (sessionCount > 1) {
|
|
135
|
+
// Browser startup dominates short parallel renders, so open the
|
|
136
|
+
// remaining sessions together instead of paying for each in sequence.
|
|
137
|
+
const additional = await Promise.allSettled(Array.from({ length: sessionCount - 1 }, () => open()));
|
|
138
|
+
for (const result of additional) {
|
|
139
|
+
if (result.status === "fulfilled") {
|
|
140
|
+
sessions.push(result.value);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const failed = additional.find((result) => result.status === "rejected");
|
|
144
|
+
if (failed) {
|
|
145
|
+
throw failed.reason;
|
|
146
|
+
}
|
|
94
147
|
}
|
|
95
148
|
return await callback(sessions);
|
|
96
149
|
}
|
|
97
150
|
catch (error) {
|
|
98
151
|
if (isFrameyardError(error)) {
|
|
152
|
+
const runtimeDiagnostics = sessions.length > 0 ? await readSessionDiagnostics(sessions).catch(() => []) : [];
|
|
99
153
|
throw new FrameyardError(error.code, `Composition "${options.compositionId}": ${error.message}`, {
|
|
100
154
|
cause: error,
|
|
155
|
+
details: error.details,
|
|
156
|
+
diagnostics: error.diagnostics ?? (runtimeDiagnostics.length > 0 ? runtimeDiagnostics : undefined),
|
|
101
157
|
});
|
|
102
158
|
}
|
|
103
159
|
throw error;
|
|
104
160
|
}
|
|
105
161
|
}
|
|
106
162
|
finally {
|
|
107
|
-
|
|
163
|
+
await Promise.all(sessions.map(async (session) => {
|
|
108
164
|
try {
|
|
109
165
|
await session.close();
|
|
110
166
|
}
|
|
111
167
|
catch {
|
|
112
168
|
// Preserve the command's original error.
|
|
113
169
|
}
|
|
114
|
-
}
|
|
170
|
+
}));
|
|
115
171
|
try {
|
|
116
172
|
await server.close();
|
|
117
173
|
}
|
|
@@ -227,16 +283,19 @@ export async function checkComposition(options) {
|
|
|
227
283
|
await session.seek(frame);
|
|
228
284
|
reportProgress(options, frame + 1, total, startedAt);
|
|
229
285
|
}
|
|
286
|
+
const diagnostics = mergeDiagnostics(await session.readDiagnostics(), audioDiagnostics(audio.warnings), transcriptDiagnostics(transcripts.warnings));
|
|
230
287
|
return {
|
|
231
288
|
composition: options.compositionId,
|
|
289
|
+
entry: session.entry,
|
|
290
|
+
controller: session.controller,
|
|
232
291
|
metadata: session.metadata,
|
|
233
292
|
framesChecked: total,
|
|
234
|
-
audio: { clips: audio.clips.length,
|
|
293
|
+
audio: { clips: audio.clips.length, details: audio.clips },
|
|
235
294
|
transcripts: {
|
|
236
295
|
clips: transcripts.clips.length,
|
|
237
|
-
warnings: transcripts.warnings,
|
|
238
296
|
details: transcripts.clips,
|
|
239
297
|
},
|
|
298
|
+
diagnostics,
|
|
240
299
|
elapsedMs: performance.now() - startedAt,
|
|
241
300
|
};
|
|
242
301
|
});
|
|
@@ -256,7 +315,7 @@ export async function captureStill(options) {
|
|
|
256
315
|
if (options.frame >= total) {
|
|
257
316
|
throw new FrameyardError("FRAME_OUT_OF_RANGE", `Frame ${options.frame} is outside the valid range 0..${total - 1}.`);
|
|
258
317
|
}
|
|
259
|
-
await inspectTranscriptClips({
|
|
318
|
+
const transcripts = await inspectTranscriptClips({
|
|
260
319
|
projectRoot: options.project.root,
|
|
261
320
|
clips: session.transcriptClips,
|
|
262
321
|
signal: options.signal,
|
|
@@ -264,6 +323,7 @@ export async function captureStill(options) {
|
|
|
264
323
|
throwIfAborted(options.signal);
|
|
265
324
|
await session.seek(options.frame);
|
|
266
325
|
const png = await session.capture();
|
|
326
|
+
const diagnostics = mergeDiagnostics(await session.readDiagnostics(), transcriptDiagnostics(transcripts.warnings));
|
|
267
327
|
const tempPath = path.join(path.dirname(options.outPath), `.${path.basename(options.outPath)}.frameyard-${process.pid}-${randomUUID()}.tmp`);
|
|
268
328
|
try {
|
|
269
329
|
await writeFile(tempPath, png);
|
|
@@ -275,10 +335,13 @@ export async function captureStill(options) {
|
|
|
275
335
|
}
|
|
276
336
|
return {
|
|
277
337
|
composition: options.compositionId,
|
|
338
|
+
entry: session.entry,
|
|
339
|
+
controller: session.controller,
|
|
278
340
|
frame: options.frame,
|
|
279
341
|
path: options.outPath,
|
|
280
342
|
width: session.metadata.width,
|
|
281
343
|
height: session.metadata.height,
|
|
344
|
+
diagnostics,
|
|
282
345
|
elapsedMs: performance.now() - startedAt,
|
|
283
346
|
};
|
|
284
347
|
});
|
|
@@ -370,8 +433,11 @@ export async function renderComposition(options) {
|
|
|
370
433
|
}
|
|
371
434
|
await publishFile(tempOut, options.outPath, overwrite);
|
|
372
435
|
completed = true;
|
|
436
|
+
const diagnostics = mergeDiagnostics(await readSessionDiagnostics(sessions), audioDiagnostics(audio.warnings), transcriptDiagnostics(transcripts.warnings));
|
|
373
437
|
return {
|
|
374
438
|
composition: options.compositionId,
|
|
439
|
+
entry: session.entry,
|
|
440
|
+
controller: session.controller,
|
|
375
441
|
path: options.outPath,
|
|
376
442
|
width,
|
|
377
443
|
height,
|
|
@@ -381,11 +447,11 @@ export async function renderComposition(options) {
|
|
|
381
447
|
framesRendered: total,
|
|
382
448
|
concurrency,
|
|
383
449
|
bytes: (await stat(options.outPath)).size,
|
|
384
|
-
audio: { clips: audio.clips.length
|
|
450
|
+
audio: { clips: audio.clips.length },
|
|
385
451
|
transcripts: {
|
|
386
452
|
clips: transcripts.clips.length,
|
|
387
|
-
warnings: transcripts.warnings,
|
|
388
453
|
},
|
|
454
|
+
diagnostics,
|
|
389
455
|
elapsedMs: performance.now() - startedAt,
|
|
390
456
|
};
|
|
391
457
|
}
|