import type { DevHandle } from '../project/dev-handle.js'; export interface RecorderCapabilities { /** The recorder can stream frames to the host-announced sink at all. */ sink: boolean; /** Start/stop over postMessage, with state reports back. */ message: boolean; /** Camera fly-through over postMessage. */ flythrough: boolean; } /** Read straight off `engine/debug/ScreenRecorder.ts`, the vendored recorder source. */ export declare function recorderCapabilities(root: string): RecorderCapabilities; export declare function upgradeMessage(what: string, marker: string): string; export declare const NO_DEV_MESSAGE: string; export interface FlythroughMarker { position: { x: number; y: number; z: number; }; rotation?: { x: number; y: number; z: number; }; lookAt?: { x: number; y: number; z: number; }; timestamp: number; } export interface FlythroughPath { version: 1; name?: string; markers: FlythroughMarker[]; } export declare const MAX_FLYTHROUGH_SEC = 600; /** Validate a fly-through document so a typo is reported here, not as a silent no-op in the engine. */ export declare function parseFlythrough(raw: unknown, source: string): FlythroughPath; export declare function loadFlythrough(file: string): FlythroughPath; /** A recording directory that was not there before the session started, or null. */ export declare function findNewRecording(before: ReadonlySet, dir: string): string | null; export declare function listRecordingNames(dir: string): Set; /** * The recorder's own warnings, deduplicated with frame numbers stripped, so a thousand * "save-frame 1384 failed: TypeError: Failed to fetch" lines read as one reason. */ export declare function summarizeRecorderWarnings(consoleLines: readonly string[]): string[]; /** "H.264 (hardware encoder)" from the manifest's capture block; undefined for raw or older recorders. */ export declare function describeCapture(capture: { codec?: string; hardware?: boolean | null; } | undefined): string | undefined; export declare function countFrames(dir: string): number; /** * Frames on disk after stop, counting the ones ffmpeg is still extracting into the sidecar's * scratch directory (they are renamed into place only once the whole capture is decoded). */ export declare function countFramesLanding(dir: string): number; export interface RecordOptions { root: string; handle: DevHandle; /** Stop after this many seconds of recording. Absent: until the creator presses F9 (or the fly-through ends). */ seconds?: number; /** `WxH`, one of the shell's RECORDING_RESOLUTIONS. */ resolution: string; flythrough?: FlythroughPath; log: (line: string) => void; /** After stop: how long the sidecar may go without progress (a new frame on disk, a state report) before giving up. */ stopWaitMs?: number; /** How long to wait for the creator to press Play. */ playWaitMs?: number; } export interface RecordResult { name: string; dir: string; frameCount: number; /** Frames the recorder could not save; the renderer fills them from neighbours. */ missingFrames: number; width: number; height: number; /** Wall-clock length of the session. */ durationSec: number; /** Footage actually recorded, in seconds of game time: frameCount / fps. Below durationSec on a machine that renders under 60 fps. */ gameSeconds: number; trigger: 'message' | 'f9'; /** Distinct `[ScreenRecorder]` warnings the game logged — the reason behind any missing frames. */ recorderWarnings: string[]; /** How the frames left the browser, when the recorder said: "H.264 (software encoder)". */ capture?: string; } /** * Wait for `done`, giving up only when `activity()` has not changed for `idleMs` (or after * `capMs` regardless). The sidecar's post-stop work — remux, then one PNG per frame — takes as * long as the recording is long, so a fixed budget would fail exactly the recordings worth keeping; * silence is the failure signal. `onPoll` runs every poll for progress lines. */ export declare function waitForActivity(done: () => boolean, activity: () => string, idleMs: number, capMs: number, onPoll?: () => void, pollMs?: number): Promise; /** * Run one recording session end to end. Throws a CliError when the recording never happened or * never finished; returns where it landed otherwise. */ export declare function recordGameplay(options: RecordOptions): Promise;