@kheleshikhi/studio-agent 0.8.0 → 0.9.1
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/README.md +54 -0
- package/dist/attempt.d.ts +4 -0
- package/dist/attempt.js +11 -1
- package/dist/attempt.js.map +1 -1
- package/dist/browser.d.ts +18 -4
- package/dist/browser.js +84 -22
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +429 -97
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +72 -8
- package/dist/daemon.js.map +1 -1
- package/dist/episode-runner.d.ts +109 -0
- package/dist/episode-runner.js +381 -0
- package/dist/episode-runner.js.map +1 -0
- package/dist/episode.d.ts +332 -0
- package/dist/episode.js +648 -0
- package/dist/episode.js.map +1 -0
- package/dist/project.d.ts +30 -0
- package/dist/project.js +204 -0
- package/dist/project.js.map +1 -0
- package/dist/render-jobs.d.ts +101 -0
- package/dist/render-jobs.js +241 -0
- package/dist/render-jobs.js.map +1 -0
- package/dist/shot-provenance.d.ts +66 -0
- package/dist/shot-provenance.js +114 -0
- package/dist/shot-provenance.js.map +1 -0
- package/dist/state.js +10 -6
- package/dist/state.js.map +1 -1
- package/dist/video.d.ts +38 -5
- package/dist/video.js +73 -12
- package/dist/video.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -221,6 +221,43 @@ query, returns ranked summaries with a small default limit, and leaves full
|
|
|
221
221
|
source to `example inspect <id>`; normally inspect no more than three relevant
|
|
222
222
|
examples.
|
|
223
223
|
|
|
224
|
+
### Authoring projects (library scope)
|
|
225
|
+
|
|
226
|
+
A Maker's authoring project fixes which asset libraries the work may draw
|
|
227
|
+
from. Start the Attempt in one and every later command in that workspace is
|
|
228
|
+
scoped by the server:
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
nerdbro project list # your projects
|
|
232
|
+
nerdbro project libraries # every library; home/permitted marked for the active project
|
|
233
|
+
nerdbro project create --title "Siege of the fort" --output-target video \
|
|
234
|
+
--home-library history-youtube [--purpose <text>] [--permitted shared-general,...]
|
|
235
|
+
nerdbro attempt start --label siege --project <project-id>
|
|
236
|
+
nerdbro project current | project show [<project-id>]
|
|
237
|
+
nerdbro component search cannon # compact, in-scope page; outside-scope ids on stderr
|
|
238
|
+
nerdbro component search cannon --all-libraries [--limit n] [--offset n]
|
|
239
|
+
nerdbro component search cannon --full # the old full-contract list
|
|
240
|
+
nerdbro component inspect physics.cannon.v1 # libraries, inScope, scopeBasis; never filtered
|
|
241
|
+
nerdbro project import physics.cannon.v1 --reason "siege cannon" [--kind component|behavior|audio|experience]
|
|
242
|
+
nerdbro studio validate <asset-id> # scope_warnings: LIBRARY_SCOPE_NOT_PERMITTED
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The project's public id is kept in `.nerdbro-attempt.json`; `project show`
|
|
246
|
+
and `project import` default to it (pass `--project` or an id to choose
|
|
247
|
+
another). In a project Attempt, `component|behavior search` returns
|
|
248
|
+
`view: "compact"`, `scope`, and `outside_scope` `{count, examples, hint}`; the
|
|
249
|
+
human output prints the scope and hint on stderr (stdout stays JSON).
|
|
250
|
+
`--compact` asks for the compact view without a project; `--full` and
|
|
251
|
+
`--compact` are exclusive. Studio assets created in a project Attempt join
|
|
252
|
+
the project. `studio validate|compile|preview` copy any
|
|
253
|
+
`LIBRARY_SCOPE_NOT_PERMITTED` diagnostics to `scope_warnings`; approval in the
|
|
254
|
+
Studio refuses an unimported out-of-scope dependency. Without `--project`
|
|
255
|
+
nothing changes. Routes and scopes: `GET /v1/agent/libraries`
|
|
256
|
+
(`CATALOGUE_READ`), `GET /v1/agent/projects[/{id}]` (`STUDIO_READ`),
|
|
257
|
+
`POST /v1/agent/projects` (`STUDIO_ASSET_CREATE`),
|
|
258
|
+
`POST /v1/agent/projects/{id}/imports` (`STUDIO_DRAFT_WRITE`); no library or
|
|
259
|
+
membership writes.
|
|
260
|
+
|
|
224
261
|
`nerdbro experience inspect-browser <id>` opens the canonical Experience
|
|
225
262
|
workspace. `nerdbro experience drive <id> --scenario scenario.json` runs a
|
|
226
263
|
bounded scenario against the mounted Experience Preview of **your local
|
|
@@ -354,6 +391,23 @@ For a gesture with an interaction handle, assert
|
|
|
354
391
|
`gestures.<id>.affordance_visible` before `drag`; the driver also refuses a
|
|
355
392
|
handle that the mounted preview has not presented.
|
|
356
393
|
|
|
394
|
+
## Presentation video and episodes
|
|
395
|
+
|
|
396
|
+
`nerdbro studio render-video <asset> --recipe recipe.json` and `nerdbro
|
|
397
|
+
experience render-video <stable-id> --recipe recipe.json` render one
|
|
398
|
+
presentation MP4 (H.264/AAC, exact frame times, sounds mixed from canonical
|
|
399
|
+
bytes; needs local FFmpeg) as a daemon render job the CLI polls; Ctrl-C
|
|
400
|
+
cancels it. `render.json` records the source hash, the dependency record
|
|
401
|
+
digest (Scene) or per-Scene provenance (Experience), the recipe and every
|
|
402
|
+
frame's SHA-256, plus a per-phase capture timing breakdown.
|
|
403
|
+
|
|
404
|
+
`nerdbro episode validate|plan|render|status <episode.json>` assembles an
|
|
405
|
+
episode from such shots with a content-addressed shot cache, one ducked and
|
|
406
|
+
loudness-normalised mix, SRT subtitles and a QC report. `NERDBRO_RENDER_WORKERS`
|
|
407
|
+
(default 1, at most 4) sets how many render browsers the daemon may run, and
|
|
408
|
+
`--workers` how many shots render at once. See
|
|
409
|
+
[episode video production](../docs/guides/episode-video.md).
|
|
410
|
+
|
|
357
411
|
## Library authoring
|
|
358
412
|
|
|
359
413
|
The Studio Library's semantic kinds — `experience`, `audio`, `component`
|
package/dist/attempt.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface AttemptPointer {
|
|
|
7
7
|
attempt_root: string;
|
|
8
8
|
server_origin: string;
|
|
9
9
|
started_at: string;
|
|
10
|
+
/** Authoring project public id when the Attempt was started in one; the server owns its scope. */
|
|
11
|
+
project?: string | null;
|
|
10
12
|
}
|
|
11
13
|
export declare function attemptHome(): string;
|
|
12
14
|
export declare function attemptDirectory(attemptId: string): string;
|
|
@@ -15,6 +17,8 @@ export declare function readAttemptPointer(start?: string): Promise<{
|
|
|
15
17
|
workspace: string;
|
|
16
18
|
} | null>;
|
|
17
19
|
export declare function createAttemptPointer(server: Record<string, unknown>, serverOrigin: string, workspace?: string): Promise<AttemptPointer>;
|
|
20
|
+
/** The project public id the server scoped this Attempt to, if any. */
|
|
21
|
+
export declare function attemptProject(server: Record<string, unknown>): string | null;
|
|
18
22
|
export declare function saveCommandEvidence(pointer: AttemptPointer, commandId: string, command: string, result: unknown): Promise<void>;
|
|
19
23
|
export declare function finalizeClient(pointer: AttemptPointer, workspace: string, server: Record<string, unknown>): Promise<{
|
|
20
24
|
path: string;
|
package/dist/attempt.js
CHANGED
|
@@ -54,12 +54,22 @@ export async function createAttemptPointer(server, serverOrigin, workspace = pro
|
|
|
54
54
|
label: String(server.label), mode: String(server.mode),
|
|
55
55
|
attempt_root: root, server_origin: serverOrigin,
|
|
56
56
|
started_at: String(server.started_at),
|
|
57
|
+
// Only a project Attempt records one, so unscoped pointers stay as before.
|
|
58
|
+
...(attemptProject(server) ? { project: attemptProject(server) } : {}),
|
|
57
59
|
};
|
|
58
60
|
await writeFile(path.join(workspace, POINTER_NAME), `${JSON.stringify(pointer, null, 2)}\n`, { flag: "wx", mode: 0o600 });
|
|
59
|
-
await writeFile(path.join(root, "README.md"), `# NerdBro Attempt ${attemptId}\n\nLabel: ${pointer.label}\nMode: ${pointer.mode}\n\nRun \`nerdbro attempt finish --outcome completed|blocked|incomplete|abandoned\` in the original workspace with the accurate outcome, then run \`just studio-agent-attempt-export ${attemptId}\` from the NerdBro repository.\n`);
|
|
61
|
+
await writeFile(path.join(root, "README.md"), `# NerdBro Attempt ${attemptId}\n\nLabel: ${pointer.label}\nMode: ${pointer.mode}\n${pointer.project ? `Project: ${pointer.project}\n` : ""}\nRun \`nerdbro attempt finish --outcome completed|blocked|incomplete|abandoned\` in the original workspace with the accurate outcome, then run \`just studio-agent-attempt-export ${attemptId}\` from the NerdBro repository.\n`);
|
|
60
62
|
await writeFile(path.join(root, "RUN_MANIFEST.json"), `${JSON.stringify({ schema: "kheleshikhi.studio-agent-attempt-run.v1", ...server }, null, 2)}\n`);
|
|
61
63
|
return pointer;
|
|
62
64
|
}
|
|
65
|
+
/** The project public id the server scoped this Attempt to, if any. */
|
|
66
|
+
export function attemptProject(server) {
|
|
67
|
+
const scope = server.project_scope;
|
|
68
|
+
if (!scope || typeof scope !== "object")
|
|
69
|
+
return null;
|
|
70
|
+
const project = scope.project;
|
|
71
|
+
return typeof project === "string" && project ? project : null;
|
|
72
|
+
}
|
|
63
73
|
export async function saveCommandEvidence(pointer, commandId, command, result) {
|
|
64
74
|
const root = attemptDirectory(pointer.attempt_id);
|
|
65
75
|
const destination = path.join(root, "client", "evidence", command.startsWith("studio.drive") ? "drives" : command.startsWith("studio.inspect") ? "captures" : command.startsWith("studio.certify") ? "certification" : "other");
|
package/dist/attempt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attempt.js","sourceRoot":"","sources":["../src/attempt.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"attempt.js","sourceRoot":"","sources":["../src/attempt.ts"],"names":[],"mappings":"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"}
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { type RenderRecipe } from "./video.js";
|
|
2
2
|
import { type Page } from "playwright";
|
|
3
3
|
import { AgentApi } from "./protocol.js";
|
|
4
|
+
import { type RenderProgress } from "./render-jobs.js";
|
|
4
5
|
import { type DriveScenario, type ExperienceScenario } from "./scenario.js";
|
|
6
|
+
/** A render's cancellation signal and progress reports (a daemon render job). */
|
|
7
|
+
export type RenderControl = {
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
onProgress?: (value: RenderProgress) => void;
|
|
10
|
+
};
|
|
5
11
|
/** One semantic step as it happened, for Agent Presence and the activity feed. */
|
|
6
12
|
export type DriveStepReport = {
|
|
7
13
|
index: number;
|
|
@@ -90,13 +96,15 @@ export interface PreviewObservationRequest extends BrowserCaptureRequest {
|
|
|
90
96
|
}
|
|
91
97
|
export declare class StudioBrowser {
|
|
92
98
|
private api;
|
|
99
|
+
private readonly profileName;
|
|
93
100
|
private context?;
|
|
94
101
|
private page?;
|
|
95
102
|
private headless;
|
|
96
103
|
private browserEngine;
|
|
97
104
|
private apiOrigin;
|
|
98
105
|
private credentials;
|
|
99
|
-
|
|
106
|
+
/** `profileName` keeps a render worker's persistent profile apart from the main browser's. */
|
|
107
|
+
constructor(api: AgentApi, profileName?: string);
|
|
100
108
|
start(headless: boolean): Promise<void>;
|
|
101
109
|
stop(): Promise<void>;
|
|
102
110
|
clearAuthentication(): void;
|
|
@@ -139,7 +147,7 @@ export declare class StudioBrowser {
|
|
|
139
147
|
audioDirectory: string;
|
|
140
148
|
/** Optional: afterwards, play in real time and sample frame intervals. */
|
|
141
149
|
measurePlaybackSeconds?: number;
|
|
142
|
-
}): Promise<Record<string, unknown>>;
|
|
150
|
+
} & RenderControl): Promise<Record<string, unknown>>;
|
|
143
151
|
/**
|
|
144
152
|
* Presentation frames of an Experience: the canonical Experience player
|
|
145
153
|
* in the presentation host, driven by video time (`renderBegin`, then
|
|
@@ -154,11 +162,17 @@ export declare class StudioBrowser {
|
|
|
154
162
|
recipe: RenderRecipe;
|
|
155
163
|
framesDirectory: string;
|
|
156
164
|
audioDirectory: string;
|
|
157
|
-
}): Promise<Record<string, unknown>>;
|
|
165
|
+
} & RenderControl): Promise<Record<string, unknown>>;
|
|
158
166
|
private requirePage;
|
|
159
167
|
/** The page's runtime observation and its one-at-a-time drive channel. */
|
|
160
168
|
private renderChannel;
|
|
161
|
-
/**
|
|
169
|
+
/**
|
|
170
|
+
* The newest observation once [ready] holds. The page publishes one every
|
|
171
|
+
* 150 ms and after every command; while not ready, each read also asks the
|
|
172
|
+
* host for a fresh one (the drive-command wake event, with no command
|
|
173
|
+
* waiting, only republishes), so a paint that lands between polls is seen
|
|
174
|
+
* within milliseconds.
|
|
175
|
+
*/
|
|
162
176
|
private waitForRender;
|
|
163
177
|
/**
|
|
164
178
|
* The frame loop both subjects share: actions at their seconds, a step to
|
package/dist/browser.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
2
|
-
import { actionsBetween, audioKey, frameCount, frameTime, pngSize, sha256 } from "./video.js";
|
|
2
|
+
import { actionsBetween, audioKey, frameCount, frameTime, PhaseTimes, pngSize, sha256 } from "./video.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { chromium } from "playwright";
|
|
5
5
|
import { cacheDirectory } from "./state.js";
|
|
6
|
+
import { throwIfCancelled } from "./render-jobs.js";
|
|
6
7
|
import { CliError } from "./types.js";
|
|
7
8
|
import { assertCurrentObservation, ObservationSampler, observationSettings } from "./observation.js";
|
|
8
9
|
import { evidenceMode, isDriveCommand, matchesObservation, isExperienceCommand, matchesExperienceObservation, observedValue, stepSummary } from "./scenario.js";
|
|
@@ -49,6 +50,25 @@ export async function waitForCapturePaint(page) {
|
|
|
49
50
|
throw new CliError("Studio did not paint after runtime readiness.", "STUDIO_CAPTURE_PAINT_TIMEOUT");
|
|
50
51
|
}
|
|
51
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* One PNG of the viewport `clip` at device scale 1, through the page's
|
|
55
|
+
* existing CDP session with Chrome's fast PNG encoder (`optimizeForSpeed`:
|
|
56
|
+
* the same pixels, lighter compression). Playwright's screenshot is the
|
|
57
|
+
* fallback.
|
|
58
|
+
*/
|
|
59
|
+
async function captureViewportPng(page, clip) {
|
|
60
|
+
const session = viewportSessions.get(page);
|
|
61
|
+
if (session) {
|
|
62
|
+
try {
|
|
63
|
+
const { data } = await session.send("Page.captureScreenshot", {
|
|
64
|
+
format: "png", optimizeForSpeed: true, captureBeyondViewport: false, clip: { ...clip, scale: 1 },
|
|
65
|
+
});
|
|
66
|
+
return Buffer.from(data, "base64");
|
|
67
|
+
}
|
|
68
|
+
catch { /* fall back to Playwright */ }
|
|
69
|
+
}
|
|
70
|
+
return page.screenshot({ type: "png", scale: "css", clip });
|
|
71
|
+
}
|
|
52
72
|
async function waitForVisualReady(page, timeoutMs, stage) {
|
|
53
73
|
try {
|
|
54
74
|
await page.waitForFunction(() => {
|
|
@@ -269,14 +289,17 @@ function driveOutcome(kind, steps, results, summaries, final) {
|
|
|
269
289
|
const LIBRARY_WORKSPACES = new Set(["experiences", "audio", "components", "behaviors"]);
|
|
270
290
|
export class StudioBrowser {
|
|
271
291
|
api;
|
|
292
|
+
profileName;
|
|
272
293
|
context;
|
|
273
294
|
page;
|
|
274
295
|
headless = false;
|
|
275
296
|
browserEngine = "not-started";
|
|
276
297
|
apiOrigin;
|
|
277
298
|
credentials;
|
|
278
|
-
|
|
299
|
+
/** `profileName` keeps a render worker's persistent profile apart from the main browser's. */
|
|
300
|
+
constructor(api, profileName = "browser-profile") {
|
|
279
301
|
this.api = api;
|
|
302
|
+
this.profileName = profileName;
|
|
280
303
|
this.apiOrigin = new URL(api.origin).origin;
|
|
281
304
|
this.credentials = new BrowserCredentialManager(api);
|
|
282
305
|
}
|
|
@@ -284,7 +307,7 @@ export class StudioBrowser {
|
|
|
284
307
|
if (this.context)
|
|
285
308
|
return;
|
|
286
309
|
this.headless = headless;
|
|
287
|
-
const profile = path.join(cacheDirectory(),
|
|
310
|
+
const profile = path.join(cacheDirectory(), this.profileName);
|
|
288
311
|
await mkdir(profile, { recursive: true, mode: 0o700 });
|
|
289
312
|
const attempts = [
|
|
290
313
|
{ channel: "chrome", name: "Google Chrome" },
|
|
@@ -877,10 +900,12 @@ export class StudioBrowser {
|
|
|
877
900
|
*/
|
|
878
901
|
async renderFrames(request) {
|
|
879
902
|
const { recipe } = request;
|
|
903
|
+
request.onProgress?.({ stage: "mount" });
|
|
880
904
|
const mounted = await this.drive({ ...request, viewport: `${recipe.width}x${recipe.height}`, present: true,
|
|
881
905
|
deviceScaleFactor: 1, scenario: { version: 1, steps: [{ op: "pause" }] } });
|
|
882
906
|
const page = this.requirePage();
|
|
883
|
-
const
|
|
907
|
+
const phases = new PhaseTimes();
|
|
908
|
+
const { observation, command } = this.renderChannel(page, phases);
|
|
884
909
|
const first = await observation();
|
|
885
910
|
if (first.scene_clock_seconds === undefined || first.scene_clock_seconds === null) {
|
|
886
911
|
throw new CliError("This Scene has no SceneClock; a video needs logical time.", "VIDEO_NO_CLOCK", 2);
|
|
@@ -892,7 +917,7 @@ export class StudioBrowser {
|
|
|
892
917
|
// plays, so an authored pause holds the picture. Record each stretch.
|
|
893
918
|
const clock = [];
|
|
894
919
|
let lastPlaying;
|
|
895
|
-
const frames = await this.captureFrames(page, request, async (time, index) => {
|
|
920
|
+
const frames = await this.captureFrames(page, { ...request, phases }, async (time, index) => {
|
|
896
921
|
const reached = await this.waitForRender(page, (value) => typeof value.render_video_seconds === "number" &&
|
|
897
922
|
Math.abs(value.render_video_seconds - time) <= 1e-6 && value.visual_ready === true, "the Scene to stand at the frame and paint");
|
|
898
923
|
if (typeof reached.scene_clock_seconds !== "number") {
|
|
@@ -904,8 +929,9 @@ export class StudioBrowser {
|
|
|
904
929
|
lastPlaying = reached.scene_clock_playing;
|
|
905
930
|
return reached;
|
|
906
931
|
}, command);
|
|
932
|
+
request.onProgress?.({ stage: "audio_collect" });
|
|
907
933
|
const log = await command({ op: "renderLog" });
|
|
908
|
-
const audio = await this.collectAudio(log.audio ?? [], request.audioDirectory, recipe, async (event) => (await command({ op: "audioBytes", target: event.id }, 30_000)).bytes);
|
|
934
|
+
const audio = await this.collectAudio(log.audio ?? [], request.audioDirectory, recipe, request.signal, async (event) => (await command({ op: "audioBytes", target: event.id }, 30_000)).bytes);
|
|
909
935
|
const final = await observation();
|
|
910
936
|
// Real-time playback timing on the same mounted learner preview: the
|
|
911
937
|
// clock plays from the recipe's start and every animation frame interval
|
|
@@ -913,6 +939,8 @@ export class StudioBrowser {
|
|
|
913
939
|
let playback;
|
|
914
940
|
const seconds = Math.min(30, Math.max(0, request.measurePlaybackSeconds ?? 0));
|
|
915
941
|
if (seconds > 0) {
|
|
942
|
+
throwIfCancelled(request.signal);
|
|
943
|
+
request.onProgress?.({ stage: "playback_measure" });
|
|
916
944
|
// Video time only moves forward; real-time playback seeks instead.
|
|
917
945
|
await command({ op: "reset" });
|
|
918
946
|
await command({ op: "seek", value: recipe.start });
|
|
@@ -965,17 +993,19 @@ export class StudioBrowser {
|
|
|
965
993
|
*/
|
|
966
994
|
async renderExperienceFrames(request) {
|
|
967
995
|
const { recipe } = request;
|
|
996
|
+
request.onProgress?.({ stage: "mount" });
|
|
968
997
|
await this.driveExperience({ ...request, viewport: `${recipe.width}x${recipe.height}`, present: true,
|
|
969
998
|
deviceScaleFactor: 1, scenario: { version: 1, steps: [] }, out: path.join(request.audioDirectory, "..", "mounted.png") });
|
|
970
999
|
const page = this.requirePage();
|
|
971
|
-
const
|
|
1000
|
+
const phases = new PhaseTimes();
|
|
1001
|
+
const { observation, command } = this.renderChannel(page, phases);
|
|
972
1002
|
const first = await observation();
|
|
973
1003
|
await command({ op: "renderBegin" });
|
|
974
1004
|
await this.waitForRender(page, (value) => value.mounted === true && value.stage_ready === true, "the Experience stage to paint");
|
|
975
1005
|
await command({ op: "step", value: recipe.start });
|
|
976
1006
|
const scenes = [];
|
|
977
1007
|
let lastScene;
|
|
978
|
-
const frames = await this.captureFrames(page, request, async (time, index) => {
|
|
1008
|
+
const frames = await this.captureFrames(page, { ...request, phases }, async (time, index) => {
|
|
979
1009
|
const reached = await this.waitForRender(page, (value) => value.stage_ready === true, "the Experience stage to paint");
|
|
980
1010
|
if (typeof reached.render_video_ms !== "number" || Math.abs(reached.render_video_ms - time * 1000) > 1) {
|
|
981
1011
|
throw new CliError("The Experience did not stand at the requested video time.", "VIDEO_CLOCK_DRIFT", 1, { expected_ms: time * 1000, observed_ms: reached.render_video_ms });
|
|
@@ -985,8 +1015,9 @@ export class StudioBrowser {
|
|
|
985
1015
|
lastScene = reached.active_scene;
|
|
986
1016
|
return reached;
|
|
987
1017
|
}, command);
|
|
1018
|
+
request.onProgress?.({ stage: "audio_collect" });
|
|
988
1019
|
const log = await command({ op: "renderLog" });
|
|
989
|
-
const audio = await this.collectAudio(log.audio ?? [], request.audioDirectory, recipe, async (event) => (await command({ op: "audioBytes", target: event.id, ...(event.scene ? { scene: event.scene } : {}) }, 30_000)).bytes);
|
|
1020
|
+
const audio = await this.collectAudio(log.audio ?? [], request.audioDirectory, recipe, request.signal, async (event) => (await command({ op: "audioBytes", target: event.id, ...(event.scene ? { scene: event.scene } : {}) }, 30_000)).bytes);
|
|
990
1021
|
const final = await observation();
|
|
991
1022
|
return {
|
|
992
1023
|
...frames,
|
|
@@ -1006,7 +1037,7 @@ export class StudioBrowser {
|
|
|
1006
1037
|
return this.page;
|
|
1007
1038
|
}
|
|
1008
1039
|
/** The page's runtime observation and its one-at-a-time drive channel. */
|
|
1009
|
-
renderChannel(page) {
|
|
1040
|
+
renderChannel(page, phases) {
|
|
1010
1041
|
const observation = async () => page.evaluate(() => {
|
|
1011
1042
|
const raw = document.getElementById("kheleshikhi-studio-runtime-observation")?.textContent;
|
|
1012
1043
|
return raw ? JSON.parse(raw) : {};
|
|
@@ -1014,6 +1045,7 @@ export class StudioBrowser {
|
|
|
1014
1045
|
let sequence = 0;
|
|
1015
1046
|
const command = async (payload, timeoutMs = 10_000) => {
|
|
1016
1047
|
const id = `render-${sequence += 1}`;
|
|
1048
|
+
const sent = performance.now();
|
|
1017
1049
|
await page.evaluate(({ id, payload }) => {
|
|
1018
1050
|
let node = document.getElementById("kheleshikhi-studio-drive-command");
|
|
1019
1051
|
if (!node) {
|
|
@@ -1023,7 +1055,12 @@ export class StudioBrowser {
|
|
|
1023
1055
|
document.body.append(node);
|
|
1024
1056
|
}
|
|
1025
1057
|
node.textContent = JSON.stringify({ id, ...payload });
|
|
1058
|
+
// Wake the host now; a host without the listener still finds the
|
|
1059
|
+
// command on its next 150 ms poll.
|
|
1060
|
+
document.dispatchEvent(new Event("kheleshikhi-studio-drive-command"));
|
|
1026
1061
|
}, { id, payload });
|
|
1062
|
+
const delivered = performance.now();
|
|
1063
|
+
phases?.add("command_send", delivered - sent);
|
|
1027
1064
|
const reply = await page.waitForFunction((expected) => {
|
|
1028
1065
|
const raw = document.getElementById("kheleshikhi-studio-drive-result")?.textContent;
|
|
1029
1066
|
if (!raw)
|
|
@@ -1033,25 +1070,34 @@ export class StudioBrowser {
|
|
|
1033
1070
|
}, id, { timeout: timeoutMs }).then((handle) => handle.jsonValue()).catch(() => {
|
|
1034
1071
|
throw new CliError("The presentation host did not acknowledge a render step.", "VIDEO_STEP_TIMEOUT", 1, { payload: { ...payload, bytes: undefined } });
|
|
1035
1072
|
});
|
|
1073
|
+
phases?.add("command_ack_wait", performance.now() - delivered);
|
|
1036
1074
|
if (reply.ok !== true)
|
|
1037
1075
|
throw new CliError(String(reply.error || "Render step failed."), "VIDEO_STEP_FAILED", 1, { payload, reply });
|
|
1038
1076
|
return reply;
|
|
1039
1077
|
};
|
|
1040
1078
|
return { observation, command };
|
|
1041
1079
|
}
|
|
1042
|
-
/**
|
|
1080
|
+
/**
|
|
1081
|
+
* The newest observation once [ready] holds. The page publishes one every
|
|
1082
|
+
* 150 ms and after every command; while not ready, each read also asks the
|
|
1083
|
+
* host for a fresh one (the drive-command wake event, with no command
|
|
1084
|
+
* waiting, only republishes), so a paint that lands between polls is seen
|
|
1085
|
+
* within milliseconds.
|
|
1086
|
+
*/
|
|
1043
1087
|
async waitForRender(page, ready, what, timeoutMs = 20_000) {
|
|
1044
1088
|
const deadline = Date.now() + timeoutMs;
|
|
1045
|
-
for (;;) {
|
|
1046
|
-
const value = await page.evaluate(() => {
|
|
1089
|
+
for (let attempt = 0;; attempt += 1) {
|
|
1090
|
+
const value = await page.evaluate((wake) => {
|
|
1047
1091
|
const raw = document.getElementById("kheleshikhi-studio-runtime-observation")?.textContent;
|
|
1092
|
+
if (wake)
|
|
1093
|
+
document.dispatchEvent(new Event("kheleshikhi-studio-drive-command"));
|
|
1048
1094
|
return raw ? JSON.parse(raw) : {};
|
|
1049
|
-
});
|
|
1095
|
+
}, attempt > 0);
|
|
1050
1096
|
if (ready(value))
|
|
1051
1097
|
return value;
|
|
1052
1098
|
if (Date.now() > deadline)
|
|
1053
1099
|
throw new CliError(`Timed out waiting for ${what}.`, "VIDEO_STAGE_NOT_READY", 1, { observed: value });
|
|
1054
|
-
await page.waitForTimeout(
|
|
1100
|
+
await page.waitForTimeout(attempt === 0 ? 0 : 10);
|
|
1055
1101
|
}
|
|
1056
1102
|
}
|
|
1057
1103
|
/**
|
|
@@ -1061,6 +1107,8 @@ export class StudioBrowser {
|
|
|
1061
1107
|
*/
|
|
1062
1108
|
async captureFrames(page, request, arrived, command) {
|
|
1063
1109
|
const { recipe } = request;
|
|
1110
|
+
const phases = request.phases ?? new PhaseTimes();
|
|
1111
|
+
throwIfCancelled(request.signal);
|
|
1064
1112
|
await mkdir(request.framesDirectory, { recursive: true });
|
|
1065
1113
|
const viewport = await page.evaluate(() => ({ width: window.innerWidth, height: window.innerHeight, dpr: window.devicePixelRatio }));
|
|
1066
1114
|
if (viewport.width !== recipe.width || viewport.height !== recipe.height || viewport.dpr !== 1) {
|
|
@@ -1074,29 +1122,41 @@ export class StudioBrowser {
|
|
|
1074
1122
|
let previous = recipe.start - 1;
|
|
1075
1123
|
let lastShot;
|
|
1076
1124
|
const started = Date.now();
|
|
1125
|
+
phases.active = true;
|
|
1077
1126
|
for (let index = 0; index < total; index += 1) {
|
|
1127
|
+
const frameStarted = performance.now();
|
|
1128
|
+
// A cancelled job (client gone, Ctrl-C, deadline) stops here, between frames.
|
|
1129
|
+
throwIfCancelled(request.signal);
|
|
1130
|
+
request.onProgress?.({ stage: "capture", frame: index, frames: total });
|
|
1078
1131
|
const time = frameTime(recipe, index);
|
|
1079
1132
|
for (const action of actionsBetween(recipe, previous, time)) {
|
|
1080
|
-
await
|
|
1081
|
-
|
|
1133
|
+
await phases.time("actions", async () => {
|
|
1134
|
+
await command({ op: "step", value: action.at });
|
|
1135
|
+
await command({ op: action.op, ...(action.target !== undefined ? { target: action.target } : {}), ...(action.value !== undefined ? { value: action.value } : {}) });
|
|
1136
|
+
});
|
|
1082
1137
|
performed.push({ at: action.at, op: action.op, ...(action.target !== undefined ? { target: action.target } : {}), frame: index });
|
|
1083
1138
|
}
|
|
1084
|
-
await command({ op: "step", value: time });
|
|
1085
|
-
const reached = await arrived(time, index);
|
|
1086
|
-
await waitForCapturePaint(page);
|
|
1087
|
-
const png = await
|
|
1139
|
+
await phases.time("step", () => command({ op: "step", value: time }));
|
|
1140
|
+
const reached = await phases.time("arrival", () => arrived(time, index));
|
|
1141
|
+
await phases.time("paint", () => waitForCapturePaint(page));
|
|
1142
|
+
const png = await phases.time("screenshot", () => captureViewportPng(page, clip));
|
|
1143
|
+
const writeStarted = performance.now();
|
|
1088
1144
|
const size = pngSize(png);
|
|
1089
1145
|
if (size.width !== recipe.width || size.height !== recipe.height) {
|
|
1090
1146
|
throw new CliError(`Frame ${index} is ${size.width}x${size.height}, not ${recipe.width}x${recipe.height}.`, "VIDEO_FRAME_SIZE_MISMATCH", 1, { frame: index, size });
|
|
1091
1147
|
}
|
|
1092
1148
|
hashes.push(sha256(png));
|
|
1093
1149
|
await writeFile(path.join(request.framesDirectory, `${String(index).padStart(6, "0")}.png`), png);
|
|
1150
|
+
phases.add("hash_and_write", performance.now() - writeStarted);
|
|
1151
|
+
phases.add("frame_total", performance.now() - frameStarted);
|
|
1094
1152
|
const shot = reached.learner_camera?.shot ?? null;
|
|
1095
1153
|
if (index === 0 || shot !== lastShot)
|
|
1096
1154
|
shots.push({ frame: index, at: time, shot });
|
|
1097
1155
|
lastShot = shot;
|
|
1098
1156
|
previous = time;
|
|
1099
1157
|
}
|
|
1158
|
+
phases.active = false;
|
|
1159
|
+
request.onProgress?.({ stage: "capture", frame: total, frames: total });
|
|
1100
1160
|
return {
|
|
1101
1161
|
frames: total,
|
|
1102
1162
|
frame_size: { width: recipe.width, height: recipe.height, device_scale_factor: 1, verified_frames: total },
|
|
@@ -1106,10 +1166,11 @@ export class StudioBrowser {
|
|
|
1106
1166
|
camera_shots: shots,
|
|
1107
1167
|
actions: performed,
|
|
1108
1168
|
capture_seconds: (Date.now() - started) / 1000,
|
|
1169
|
+
capture_phases: phases.summary(total),
|
|
1109
1170
|
};
|
|
1110
1171
|
}
|
|
1111
1172
|
/** Every logged sound's canonical bytes, written once by key; checked against the logged SHA-256. */
|
|
1112
|
-
async collectAudio(events, directory, recipe, bytesOf) {
|
|
1173
|
+
async collectAudio(events, directory, recipe, signal, bytesOf) {
|
|
1113
1174
|
const sources = {};
|
|
1114
1175
|
if (recipe.audio === "scene") {
|
|
1115
1176
|
await mkdir(directory, { recursive: true });
|
|
@@ -1117,6 +1178,7 @@ export class StudioBrowser {
|
|
|
1117
1178
|
const key = audioKey(event);
|
|
1118
1179
|
if (event.action !== "play" || sources[key])
|
|
1119
1180
|
continue;
|
|
1181
|
+
throwIfCancelled(signal);
|
|
1120
1182
|
if (Object.keys(sources).length >= 32)
|
|
1121
1183
|
throw new CliError("A render mixes at most 32 distinct sounds.", "VIDEO_AUDIO_TOO_MANY", 2);
|
|
1122
1184
|
const data = Buffer.from(await bytesOf(event), "base64");
|