@bitmagic/cli 0.1.61-dev.5 → 0.1.61-dev.7

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.
@@ -1,5 +1,6 @@
1
1
  import * as http from 'http';
2
2
  import { WebSocketServer } from 'ws';
3
+ import { type CaptureCodec } from './capture-file.js';
3
4
  export declare const RECORD_STREAM_PATH = "/api/dev/record-stream";
4
5
  export declare const FRAME_HEADER_BYTES = 4;
5
6
  /** Sanity bounds on a start request — nothing a real recorder sends is refused. */
@@ -8,6 +9,8 @@ export interface StreamStart {
8
9
  recordingName: string;
9
10
  width: number;
10
11
  height: number;
12
+ /** Absent for raw RGBA frames. */
13
+ codec?: CaptureCodec;
11
14
  }
12
15
  export interface StreamError {
13
16
  error: string;
@@ -20,7 +23,7 @@ export declare function parseFrameMessage(data: Buffer, frameBytes: number): {
20
23
  pixels: Buffer;
21
24
  } | null;
22
25
  /**
23
- * Keeps the encoder's input contiguous. The encoder numbers frames sequentially from 0, so the
26
+ * Keeps the raw encoder's input contiguous. The encoder numbers frames sequentially from 0, so the
24
27
  * frame written Nth becomes `_00000N.png`; feeding it exactly one frame per index — the real one
25
28
  * when it arrived, the previous one when it did not — is what keeps the files aligned with the
26
29
  * recorder's own frame count (the trailer's clock).
@@ -35,7 +38,11 @@ export declare class FrameSequencer {
35
38
  finish(frameCount: number): Buffer[];
36
39
  get written(): number;
37
40
  }
38
- /** ffmpeg arguments: raw RGBA on stdin, one PNG per frame at `<dir>/<name>_%06d.png`. */
41
+ /**
42
+ * Raw path ffmpeg arguments: RGBA on stdin, one PNG per frame at `<dir>/<name>_%06d.png`, numbered
43
+ * from 0 — the image2 muxer's own default is 1, which would put frame 0 in `_000001.png` while
44
+ * every reader in `cli/src/trailer/` looks for `_000000.png`.
45
+ */
39
46
  export declare function encoderArgs(start: StreamStart, dir: string): string[];
40
47
  /**
41
48
  * Mount the sink on the sidecar's HTTP server. One session per socket; a second `start` on the
@@ -1,22 +1,30 @@
1
1
  /**
2
- * The F9 recorder's WebSocket frame sink: raw RGBA in, PNG frames on disk out.
2
+ * The F9 recorder's WebSocket frame sink: encoded video (or raw RGBA) in, PNG frames on disk out.
3
3
  *
4
4
  * Why not the HTTP sink (`recording-sink.ts`) for frames: every PNG the browser encodes with
5
5
  * `canvas.toBlob` is a Blob, a Blob lives in Chrome's blob storage until its JS wrapper is
6
6
  * garbage-collected, and a game loop rendering at 20 fps starves V8's GC enough that the store
7
7
  * fills after roughly a thousand 1080p frames — from then on every new Blob is invalid and every
8
8
  * upload fails until the tab reloads. Dropping the Blobs sooner did not help; the only cure is not
9
- * making them. So the recorder reads raw pixels (`getImageData`, an ArrayBuffer in the heap),
10
- * ships them over one WebSocket (measured at ~166 MB/s to this process), and THIS side turns them
11
- * into PNGs with ffmpeg — which also takes PNG encoding off the game's main thread.
9
+ * making them. So the recorder reads raw pixels into the heap and ships them over one WebSocket.
10
+ *
11
+ * Why video rather than raw pixels: raw 1080p RGBA is 8.3 MB a frame and this socket carries
12
+ * ~95 MB/s, which pinned capture at 11 fps and made a guided session play in slow motion. The
13
+ * recorder's worker now encodes with WebCodecs (H.264 or VP9, ~100 KB a frame at 60 Mbps) and the
14
+ * heavy work moves to after the recording: this side appends the chunks to a file, and at stop it
15
+ * remuxes them into `capture.mp4` and extracts the PNGs with ffmpeg (`capture-file.ts`). Nothing
16
+ * downstream changes — `bitmagic trailer` reads the same `<name>_%06d.png` + `timeline.json`.
17
+ * Raw RGBA stays for a browser without an encoder, piped straight into ffmpeg during the recording.
12
18
  *
13
19
  * Wire protocol, all on `/api/dev/record-stream`:
14
- * client → text {type:'start', recordingName, width, height}
15
- * server → text {type:'started'} | {type:'error', error}
16
- * client → binary [frameIndex: uint32 LE][RGBA bytes, width*height*4]
17
- * server → text {type:'ack', frameIndex} once the frame is handed to the encoder
20
+ * client → text {type:'start', recordingName, width, height, codec?: 'avc'|'vp9'} (no codec: raw RGBA)
21
+ * server → text {type:'started', codec?, container?} | {type:'error', error}
22
+ * client → binary video: [frameIndex: uint32 LE][keyframe: uint8][encoded chunk]
23
+ * raw: [frameIndex: uint32 LE][RGBA bytes, width*height*4]
24
+ * server → text {type:'ack', frameIndex} once the frame is on disk / handed to the encoder
18
25
  * client → text {type:'stop', frameCount}
19
- * server → text {type:'stopped', written, missing: number[]} once every PNG is on disk
26
+ * server → text {type:'progress', phase: 'muxing'|'extracting', frames} while ffmpeg runs after stop
27
+ * server → text {type:'stopped', written, missing: number[], error?} once every PNG is on disk
20
28
  *
21
29
  * Frames must arrive in index order (a WebSocket delivers in order, and the recorder sends in
22
30
  * order); a gap is filled by repeating the previous frame so the `%06d` sequence stays aligned
@@ -29,6 +37,7 @@ import * as path from 'path';
29
37
  import { WebSocketServer } from 'ws';
30
38
  import { isSafeRecordingName } from './recording-sink.js';
31
39
  import { recordingDir } from '../trailer/paths.js';
40
+ import { CaptureWriter, ChunkLedger, EXTRACT_DIR, containerName, extractArgs, finalizeFrames, isCaptureCodec, parseChunkMessage, remuxArgs, } from './capture-file.js';
32
41
  export const RECORD_STREAM_PATH = '/api/dev/record-stream';
33
42
  export const FRAME_HEADER_BYTES = 4;
34
43
  /** Sanity bounds on a start request — nothing a real recorder sends is refused. */
@@ -47,7 +56,9 @@ export function parseStreamStart(raw) {
47
56
  || width > MAX_FRAME_DIMENSION || height > MAX_FRAME_DIMENSION) {
48
57
  return { error: 'invalid frame size' };
49
58
  }
50
- return { recordingName, width, height };
59
+ if (msg.codec !== undefined && !isCaptureCodec(msg.codec))
60
+ return { error: `unknown codec ${JSON.stringify(msg.codec)}` };
61
+ return { recordingName, width, height, ...(msg.codec !== undefined ? { codec: msg.codec } : {}) };
51
62
  }
52
63
  /** Split a binary message into its frame index and pixel bytes; null when it is not a frame. */
53
64
  export function parseFrameMessage(data, frameBytes) {
@@ -57,7 +68,7 @@ export function parseFrameMessage(data, frameBytes) {
57
68
  return { frameIndex, pixels: data.subarray(FRAME_HEADER_BYTES) };
58
69
  }
59
70
  /**
60
- * Keeps the encoder's input contiguous. The encoder numbers frames sequentially from 0, so the
71
+ * Keeps the raw encoder's input contiguous. The encoder numbers frames sequentially from 0, so the
61
72
  * frame written Nth becomes `_00000N.png`; feeding it exactly one frame per index — the real one
62
73
  * when it arrived, the previous one when it did not — is what keeps the files aligned with the
63
74
  * recorder's own frame count (the trailer's clock).
@@ -98,14 +109,18 @@ export class FrameSequencer {
98
109
  return this.expected;
99
110
  }
100
111
  }
101
- /** ffmpeg arguments: raw RGBA on stdin, one PNG per frame at `<dir>/<name>_%06d.png`. */
112
+ /**
113
+ * Raw path ffmpeg arguments: RGBA on stdin, one PNG per frame at `<dir>/<name>_%06d.png`, numbered
114
+ * from 0 — the image2 muxer's own default is 1, which would put frame 0 in `_000001.png` while
115
+ * every reader in `cli/src/trailer/` looks for `_000000.png`.
116
+ */
102
117
  export function encoderArgs(start, dir) {
103
118
  return [
104
119
  '-v', 'error', '-y',
105
120
  '-f', 'rawvideo', '-pixel_format', 'rgba', '-video_size', `${start.width}x${start.height}`, '-framerate', '60',
106
121
  '-i', 'pipe:0',
107
122
  // Fast compression: these files are read once by the renderer and are disposable.
108
- '-c:v', 'png', '-compression_level', '1',
123
+ '-c:v', 'png', '-compression_level', '1', '-start_number', '0',
109
124
  path.join(dir, `${start.recordingName}_%06d.png`),
110
125
  ];
111
126
  }
@@ -113,7 +128,7 @@ function send(ws, message) {
113
128
  if (ws.readyState === ws.OPEN)
114
129
  ws.send(JSON.stringify(message));
115
130
  }
116
- /** Write to the encoder honouring its backpressure: resolves once the chunk is accepted. */
131
+ /** Write to the raw encoder honouring its backpressure: resolves once the chunk is accepted. */
117
132
  function writeFrame(session, chunk) {
118
133
  return new Promise((resolve) => {
119
134
  if (session.stdinClosed || session.encoderError !== null) {
@@ -127,6 +142,33 @@ function writeFrame(session, chunk) {
127
142
  session.encoder.stdin.once('drain', () => resolve());
128
143
  });
129
144
  }
145
+ /** Run one ffmpeg step to completion; null on success, else the reason. */
146
+ function runCapture(binary, args) {
147
+ return new Promise((resolve) => {
148
+ let child;
149
+ try {
150
+ child = spawn(binary, args, { stdio: ['ignore', 'ignore', 'pipe'] });
151
+ }
152
+ catch (error) {
153
+ resolve(`ffmpeg could not start: ${error instanceof Error ? error.message : String(error)}`);
154
+ return;
155
+ }
156
+ let stderr = '';
157
+ child.stderr.on('data', (chunk) => { stderr = (stderr + chunk.toString()).slice(-4000); });
158
+ child.on('error', (error) => resolve(`ffmpeg is not available on this machine (${error.message}) — install ffmpeg to record`));
159
+ child.on('close', (code) => {
160
+ resolve(code === 0 ? null : `ffmpeg exited with code ${code}: ${stderr.trim().split('\n').slice(-3).join(' | ')}`);
161
+ });
162
+ });
163
+ }
164
+ function countPngs(dir) {
165
+ try {
166
+ return fs.readdirSync(dir).filter((name) => name.endsWith('.png')).length;
167
+ }
168
+ catch {
169
+ return 0;
170
+ }
171
+ }
130
172
  /**
131
173
  * Mount the sink on the sidecar's HTTP server. One session per socket; a second `start` on the
132
174
  * same socket is refused. Every failure is reported to the client as `{type:'error'}` so the
@@ -144,14 +186,10 @@ export function attachRecordingStream(server, root, log, ffmpegBinary = 'ffmpeg'
144
186
  });
145
187
  wss.on('connection', (ws) => {
146
188
  let session = null;
147
- // Frames are processed strictly one after another so the encoder sees them in order and the
148
- // ack for a frame means "the encoder has it".
189
+ // Frames are processed strictly one after another so the file sees them in order and the
190
+ // ack for a frame means "it is on disk / the encoder has it".
149
191
  let chain = Promise.resolve();
150
- const finish = async (frameCount) => {
151
- const s = session;
152
- if (s === null)
153
- return;
154
- session = null;
192
+ const finishRaw = async (s, frameCount) => {
155
193
  await chain;
156
194
  if (frameCount !== null) {
157
195
  for (const chunk of s.sequencer.finish(frameCount))
@@ -176,12 +214,69 @@ export function attachRecordingStream(server, root, log, ffmpegBinary = 'ffmpeg'
176
214
  ...(s.encoderError !== null ? { error: s.encoderError } : {}),
177
215
  });
178
216
  };
217
+ // After stop the real work happens: remux, then extract. Progress goes back every two seconds
218
+ // so the recorder (and `bitmagic trailer record` behind it) can tell a long extraction from a
219
+ // dead sidecar.
220
+ const finishVideo = async (s, frameCount) => {
221
+ await chain;
222
+ s.writer.close();
223
+ const declared = frameCount ?? s.ledger.expected;
224
+ s.ledger.finish(declared);
225
+ const name = s.start.recordingName;
226
+ const codecName = s.codec === 'avc' ? 'H.264' : 'VP9';
227
+ log(`[editor] recording stream ${name}: ${s.ledger.received} frames captured as ${codecName}, ${s.ledger.missing.length} missing — writing ${containerName(s.codec)}`);
228
+ send(ws, { type: 'progress', phase: 'muxing', frames: 0 });
229
+ let error = s.error;
230
+ if (error === null)
231
+ error = await runCapture(ffmpegBinary, remuxArgs(s.codec, s.dir));
232
+ if (error === null) {
233
+ fs.rmSync(s.writer.filePath, { force: true });
234
+ const extractDir = path.join(s.dir, EXTRACT_DIR);
235
+ fs.mkdirSync(extractDir, { recursive: true });
236
+ const ticker = setInterval(() => send(ws, { type: 'progress', phase: 'extracting', frames: countPngs(extractDir) }), 2000);
237
+ error = await runCapture(ffmpegBinary, extractArgs(s.codec, s.dir));
238
+ clearInterval(ticker);
239
+ }
240
+ const result = finalizeFrames(s.dir, name, s.ledger, declared);
241
+ log(`[editor] recording stream ${name}: ${result.written} frames on disk, ${result.missing.length} missing${error !== null ? `, error: ${error}` : ''}`);
242
+ send(ws, { type: 'stopped', written: result.written, missing: result.missing, ...(error !== null ? { error } : {}) });
243
+ };
244
+ const finish = async (frameCount) => {
245
+ const s = session;
246
+ if (s === null)
247
+ return;
248
+ session = null;
249
+ if (s.kind === 'raw')
250
+ await finishRaw(s, frameCount);
251
+ else
252
+ await finishVideo(s, frameCount);
253
+ };
179
254
  ws.on('message', (data, isBinary) => {
180
255
  if (isBinary) {
181
256
  const s = session;
182
257
  if (s === null)
183
258
  return;
184
259
  const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
260
+ if (s.kind === 'video') {
261
+ const chunk = parseChunkMessage(buffer);
262
+ if (chunk === null) {
263
+ send(ws, { type: 'error', error: `chunk message of ${buffer.length} bytes carries no frame` });
264
+ return;
265
+ }
266
+ const bytes = Buffer.from(chunk.bytes);
267
+ chain = chain.then(() => {
268
+ if (s.ledger.accept(chunk.frameIndex)) {
269
+ try {
270
+ s.writer.append(chunk.frameIndex, bytes);
271
+ }
272
+ catch (error) {
273
+ s.error = `could not write ${s.writer.filePath}: ${error instanceof Error ? error.message : String(error)}`;
274
+ }
275
+ }
276
+ send(ws, { type: 'ack', frameIndex: chunk.frameIndex });
277
+ });
278
+ return;
279
+ }
185
280
  const frame = parseFrameMessage(buffer, s.frameBytes);
186
281
  if (frame === null) {
187
282
  send(ws, { type: 'error', error: `frame message of ${buffer.length} bytes does not match ${s.start.width}x${s.start.height} RGBA` });
@@ -215,6 +310,20 @@ export function attachRecordingStream(server, root, log, ffmpegBinary = 'ffmpeg'
215
310
  }
216
311
  const dir = recordingDir(root, start.recordingName);
217
312
  fs.mkdirSync(dir, { recursive: true });
313
+ if (start.codec !== undefined) {
314
+ let writer;
315
+ try {
316
+ writer = new CaptureWriter(start.codec, dir, start.width, start.height);
317
+ }
318
+ catch (error) {
319
+ send(ws, { type: 'error', error: `could not open the capture file: ${error instanceof Error ? error.message : String(error)}` });
320
+ return;
321
+ }
322
+ session = { kind: 'video', start, codec: start.codec, dir, ledger: new ChunkLedger(), writer, error: null };
323
+ log(`[editor] recording stream ${start.recordingName}: ${start.width}x${start.height} ${start.codec === 'avc' ? 'H.264' : 'VP9'} → ${dir}`);
324
+ send(ws, { type: 'started', codec: start.codec, container: containerName(start.codec) });
325
+ return;
326
+ }
218
327
  let encoder;
219
328
  try {
220
329
  encoder = spawn(ffmpegBinary, encoderArgs(start, dir), { stdio: ['pipe', 'ignore', 'pipe'] });
@@ -223,7 +332,7 @@ export function attachRecordingStream(server, root, log, ffmpegBinary = 'ffmpeg'
223
332
  send(ws, { type: 'error', error: `ffmpeg could not start: ${error instanceof Error ? error.message : String(error)}` });
224
333
  return;
225
334
  }
226
- const s = { start, frameBytes: start.width * start.height * 4, sequencer: new FrameSequencer(), encoder, encoderError: null, stdinClosed: false };
335
+ const s = { kind: 'raw', start, frameBytes: start.width * start.height * 4, sequencer: new FrameSequencer(), encoder, encoderError: null, stdinClosed: false };
227
336
  let stderr = '';
228
337
  encoder.stderr.on('data', (chunk) => { stderr = (stderr + chunk.toString()).slice(-4000); });
229
338
  encoder.on('error', (error) => {
@@ -236,7 +345,7 @@ export function attachRecordingStream(server, root, log, ffmpegBinary = 'ffmpeg'
236
345
  s.encoderError = `ffmpeg exited with code ${code}: ${stderr.trim().split('\n').slice(-3).join(' | ')}`;
237
346
  });
238
347
  session = s;
239
- log(`[editor] recording stream ${start.recordingName}: ${start.width}x${start.height} → ${dir}`);
348
+ log(`[editor] recording stream ${start.recordingName}: ${start.width}x${start.height} raw → ${dir}`);
240
349
  send(ws, { type: 'started' });
241
350
  return;
242
351
  }
@@ -1 +1 @@
1
- {"version":3,"file":"recording-stream.js","sourceRoot":"","sources":["../../src/editor/recording-stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recording-stream.js","sourceRoot":"","sources":["../../src/editor/recording-stream.ts"],"names":[],"mappings":"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"}
@@ -889,6 +889,19 @@ export async function startEditorServer(options) {
889
889
  const handleMotionStatus = (res) => {
890
890
  sendJson(res, 200, { ok: true, job: motionJob, worldMtimeMs: lastWrittenMtimeMs });
891
891
  };
892
+ /**
893
+ * Read a recording POST's body, answering 413 itself when it is over the sink's limit. Null means
894
+ * the response is already sent and the caller is done.
895
+ */
896
+ const readRecordingBody = async (req, res) => {
897
+ try {
898
+ return await readBodyBuffer(req, RECORDING_BODY_LIMIT_BYTES);
899
+ }
900
+ catch (error) {
901
+ sendJson(res, 413, { ok: false, error: messageOf(error) });
902
+ return null;
903
+ }
904
+ };
892
905
  /**
893
906
  * One F9 gameplay frame from the recorder in the game iframe — the one caller of this server
894
907
  * that is NOT the shell. Request shape and the `~/Downloads/<name>/` layout mirror
@@ -896,14 +909,9 @@ export async function startEditorServer(options) {
896
909
  * the trailer tooling reads a pro-lane recording unchanged.
897
910
  */
898
911
  const handleRecordingFrame = async (req, res, query) => {
899
- let body;
900
- try {
901
- body = await readBodyBuffer(req, RECORDING_BODY_LIMIT_BYTES);
902
- }
903
- catch (error) {
904
- sendJson(res, 413, { ok: false, error: messageOf(error) });
912
+ const body = await readRecordingBody(req, res);
913
+ if (body === null)
905
914
  return;
906
- }
907
915
  const parsed = await parseSaveFrameRequest(req.headers['content-type'], body, query);
908
916
  if ('error' in parsed) {
909
917
  sendJson(res, 400, { ok: false, error: parsed.error });
@@ -921,14 +929,9 @@ export async function startEditorServer(options) {
921
929
  };
922
930
  /** The recording's timeline manifest, POSTed once when an F9 frame recording stops. */
923
931
  const handleRecordingTimeline = async (req, res) => {
924
- let body;
925
- try {
926
- body = await readBodyBuffer(req, RECORDING_BODY_LIMIT_BYTES);
927
- }
928
- catch (error) {
929
- sendJson(res, 413, { ok: false, error: messageOf(error) });
932
+ const body = await readRecordingBody(req, res);
933
+ if (body === null)
930
934
  return;
931
- }
932
935
  const parsed = parseTimelineRequest(body);
933
936
  if ('error' in parsed) {
934
937
  sendJson(res, 400, { ok: false, error: parsed.error });
@@ -952,6 +955,8 @@ export async function startEditorServer(options) {
952
955
  return;
953
956
  }
954
957
  const url = (req.url ?? '/').split('?')[0];
958
+ // Parsed once for every route that reads a query parameter (the frame sink, the asset-source
959
+ // allowlist, the shell's own state poll).
955
960
  const query = new URL(req.url ?? '/', 'http://localhost').searchParams;
956
961
  if (req.method === 'GET' && (url === '/' || url === '/index.html')) {
957
962
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(shell);
@@ -1145,7 +1150,7 @@ export async function startEditorServer(options) {
1145
1150
  * nothing else.
1146
1151
  */
1147
1152
  if (req.method === 'GET' && url === '/api/assets/source') {
1148
- const requested = new URL(req.url ?? '/', 'http://127.0.0.1').searchParams.get('url');
1153
+ const requested = query.get('url');
1149
1154
  if (requested === null || !projectAssetUrls(options.root, options.gameId).has(requested)) {
1150
1155
  sendJson(res, 403, { ok: false, error: 'Not an asset of this project' });
1151
1156
  return;
@@ -1200,7 +1205,7 @@ export async function startEditorServer(options) {
1200
1205
  return;
1201
1206
  }
1202
1207
  if (req.method === 'GET' && url === '/api/state') {
1203
- if (new URL(req.url ?? '/', 'http://127.0.0.1').searchParams.get('from') === 'shell') {
1208
+ if (query.get('from') === 'shell') {
1204
1209
  lastShellPollAt = Date.now();
1205
1210
  }
1206
1211
  sendJson(res, 200, {