@maravilla-labs/types 0.8.0 → 0.8.3
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/index.d.ts +205 -0
- package/index.ts +230 -0
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -294,6 +294,207 @@ export interface Storage {
|
|
|
294
294
|
*/
|
|
295
295
|
getMetadata(key: string): Promise<StorageMetadata>;
|
|
296
296
|
}
|
|
297
|
+
/** Output image format for browser screenshots. */
|
|
298
|
+
export type ScreenshotFormat = 'png' | 'jpeg' | 'webp';
|
|
299
|
+
/** Page-size preset for browser PDF renders. */
|
|
300
|
+
export type PdfPageFormat = 'A4' | 'A3' | 'Letter' | 'Legal' | 'Tabloid';
|
|
301
|
+
/** Video codec for deterministic frame renders. */
|
|
302
|
+
export type FramesCodec = 'h264' | 'vp9';
|
|
303
|
+
/** Lifecycle state of a browser / frames job. Mirrors transforms `JobStatus`. */
|
|
304
|
+
export type BrowserJobStatus = 'pending' | 'running' | 'complete' | 'failed';
|
|
305
|
+
/** Viewport (CSS pixels) the headless browser launches with. */
|
|
306
|
+
export interface BrowserViewport {
|
|
307
|
+
width: number;
|
|
308
|
+
height: number;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* "Wait until" predicate before the screenshot / PDF capture fires.
|
|
312
|
+
* Set at most one of `selector`, `network_idle`, or `ms`; the worker
|
|
313
|
+
* picks the first non-null in that order.
|
|
314
|
+
*/
|
|
315
|
+
export interface BrowserWaitFor {
|
|
316
|
+
/** CSS selector that must resolve before the capture fires. */
|
|
317
|
+
selector?: string;
|
|
318
|
+
/** Wait for the network to go idle (~500ms with no in-flight requests). */
|
|
319
|
+
network_idle?: boolean;
|
|
320
|
+
/** Sleep for this many milliseconds then capture. Capped at ~30s by the worker. */
|
|
321
|
+
ms?: number;
|
|
322
|
+
}
|
|
323
|
+
/** Cookie pre-installed on the browser context before navigation. */
|
|
324
|
+
export interface BrowserCookie {
|
|
325
|
+
name: string;
|
|
326
|
+
value: string;
|
|
327
|
+
domain?: string;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Request shape for `platform.env.BROWSER.screenshot(...)`.
|
|
331
|
+
*
|
|
332
|
+
* Exactly one of `url` (public URL — SSRF-gated by the worker) or `path`
|
|
333
|
+
* (relative path resolved against the tenant's deployment via loopback
|
|
334
|
+
* to Delivery) must be set.
|
|
335
|
+
*/
|
|
336
|
+
export interface ScreenshotRequest {
|
|
337
|
+
/** Public URL. Worker blocks loopback / RFC1918 / link-local after DNS. */
|
|
338
|
+
url?: string;
|
|
339
|
+
/** Path on the tenant's own deployment, e.g. `/dashboard`. */
|
|
340
|
+
path?: string;
|
|
341
|
+
viewport?: BrowserViewport;
|
|
342
|
+
wait_for?: BrowserWaitFor;
|
|
343
|
+
/** Capture the full scrollable page rather than the viewport. */
|
|
344
|
+
full_page?: boolean;
|
|
345
|
+
/** Defaults to `"png"` server-side when omitted. */
|
|
346
|
+
format?: ScreenshotFormat;
|
|
347
|
+
/** JPEG / WebP quality 1–100. Ignored for PNG. */
|
|
348
|
+
quality?: number;
|
|
349
|
+
cookies?: BrowserCookie[];
|
|
350
|
+
/** Extra HTTP headers applied to every navigation request. */
|
|
351
|
+
headers?: Record<string, string>;
|
|
352
|
+
/** Storage key where the PNG / JPEG / WebP is written. Required. */
|
|
353
|
+
target: string;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Request shape for `platform.env.BROWSER.pdf(...)`. Same `url`/`path`
|
|
357
|
+
* discipline as {@link ScreenshotRequest}.
|
|
358
|
+
*/
|
|
359
|
+
export interface PdfRequest {
|
|
360
|
+
url?: string;
|
|
361
|
+
path?: string;
|
|
362
|
+
/** Defaults to `"A4"` server-side when omitted. */
|
|
363
|
+
format?: PdfPageFormat;
|
|
364
|
+
landscape?: boolean;
|
|
365
|
+
/** Render CSS background colour / images. Defaults `true` server-side. */
|
|
366
|
+
print_background?: boolean;
|
|
367
|
+
cookies?: BrowserCookie[];
|
|
368
|
+
headers?: Record<string, string>;
|
|
369
|
+
target: string;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Request shape for `platform.env.FRAMES.render(...)`.
|
|
373
|
+
*
|
|
374
|
+
* Path-only on purpose: the renderer drives one of the tenant's own
|
|
375
|
+
* deployment routes (which is expected to import `@maravilla/frames`
|
|
376
|
+
* and call `defineTimeline({...})`) frame-by-frame via CDP
|
|
377
|
+
* `HeadlessExperimental.beginFrame`.
|
|
378
|
+
*/
|
|
379
|
+
export interface FramesRenderRequest {
|
|
380
|
+
/** Path on the tenant's deployment, e.g. `/render/intro-card?title=Hi`. */
|
|
381
|
+
path: string;
|
|
382
|
+
/** Frames per second. Must be ≥ 1; worker caps the upper bound. */
|
|
383
|
+
fps: number;
|
|
384
|
+
/** Total clip duration in milliseconds. */
|
|
385
|
+
duration_ms: number;
|
|
386
|
+
/** Output width (CSS pixels). Doubles as the browser viewport width. */
|
|
387
|
+
width: number;
|
|
388
|
+
/** Output height. */
|
|
389
|
+
height: number;
|
|
390
|
+
/** Storage key of an optional audio track ffmpeg mixes in. */
|
|
391
|
+
audio?: string;
|
|
392
|
+
/** Defaults to `"h264"` server-side when omitted. */
|
|
393
|
+
codec?: FramesCodec;
|
|
394
|
+
/** Constant Rate Factor for the encoder. Worker picks a default when unset. */
|
|
395
|
+
crf?: number;
|
|
396
|
+
/** Storage key the MP4 / WebM is written to. Required — no auto-generation. */
|
|
397
|
+
target: string;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Handle returned by every BROWSER / FRAMES method. `output_key` is the
|
|
401
|
+
* caller-supplied `target` and is known up front; status updates as the
|
|
402
|
+
* worker progresses through the shared transforms job ledger.
|
|
403
|
+
*/
|
|
404
|
+
export interface BrowserJobHandle {
|
|
405
|
+
id: string;
|
|
406
|
+
src_key: string;
|
|
407
|
+
output_key: string;
|
|
408
|
+
status: BrowserJobStatus;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Headless-browser surface exposed as `platform.env.BROWSER`.
|
|
412
|
+
*/
|
|
413
|
+
export interface BrowserClient {
|
|
414
|
+
/**
|
|
415
|
+
* Capture a screenshot of a public URL or one of the tenant's own
|
|
416
|
+
* routes. Returns a {@link BrowserJobHandle} whose `output_key` equals
|
|
417
|
+
* the caller-supplied `request.target` and is known up front — poll
|
|
418
|
+
* `platform.media.transforms.job(handle.id)` for status, then fetch
|
|
419
|
+
* the bytes from `platform.env.STORAGE` once the job completes.
|
|
420
|
+
*
|
|
421
|
+
* Exactly one of `request.url` or `request.path` must be set.
|
|
422
|
+
* `url` mode is gated by an SSRF block-list applied after DNS
|
|
423
|
+
* resolution; `path` mode loopback-routes to the tenant's own
|
|
424
|
+
* deployment.
|
|
425
|
+
*
|
|
426
|
+
* @param request `url` (public, SSRF-gated) or `path` (own deployment),
|
|
427
|
+
* plus optional `viewport`, `wait_for`, `format`, `cookies`,
|
|
428
|
+
* `headers`, and the required `target` storage key.
|
|
429
|
+
* @returns A handle to poll. `output_key` is `request.target`.
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* ```ts
|
|
433
|
+
* const handle = await platform.env.BROWSER.screenshot({
|
|
434
|
+
* url: 'https://example.com',
|
|
435
|
+
* viewport: { width: 1280, height: 720 },
|
|
436
|
+
* target: 'shots/example.png',
|
|
437
|
+
* });
|
|
438
|
+
* ```
|
|
439
|
+
*/
|
|
440
|
+
screenshot(request: ScreenshotRequest): Promise<BrowserJobHandle>;
|
|
441
|
+
/**
|
|
442
|
+
* Render the target page to a PDF. Same `url` xor `path` discipline
|
|
443
|
+
* as {@link BrowserClient.screenshot}.
|
|
444
|
+
*
|
|
445
|
+
* @param request `url` or `path`, plus optional `format` (page-size
|
|
446
|
+
* preset), `landscape`, `print_background`, `cookies`, `headers`,
|
|
447
|
+
* and the required `target` storage key.
|
|
448
|
+
* @returns A handle to poll. `output_key` is `request.target`.
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```ts
|
|
452
|
+
* const handle = await platform.env.BROWSER.pdf({
|
|
453
|
+
* path: '/invoices/INV-1042',
|
|
454
|
+
* format: 'A4',
|
|
455
|
+
* print_background: true,
|
|
456
|
+
* target: 'invoices/INV-1042.pdf',
|
|
457
|
+
* });
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
pdf(request: PdfRequest): Promise<BrowserJobHandle>;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Deterministic-video surface exposed as `platform.env.FRAMES`.
|
|
464
|
+
*/
|
|
465
|
+
export interface FramesClient {
|
|
466
|
+
/**
|
|
467
|
+
* Render one of the tenant's own deployment routes to MP4 / WebM,
|
|
468
|
+
* frame-accurately. The route is expected to import
|
|
469
|
+
* `@maravilla-labs/frames` and call `defineTimeline({...})` at load
|
|
470
|
+
* time — the worker drives `window.__mvFrames.applyState(t)` once
|
|
471
|
+
* per frame and captures via CDP `HeadlessExperimental.beginFrame`,
|
|
472
|
+
* piping PNG frames into ffmpeg.
|
|
473
|
+
*
|
|
474
|
+
* Same render against the same route is deterministic — two
|
|
475
|
+
* back-to-back renders produce byte-identical output (modulo
|
|
476
|
+
* already-stripped muxer metadata).
|
|
477
|
+
*
|
|
478
|
+
* @param request `path` on the tenant's deployment, `fps`,
|
|
479
|
+
* `duration_ms`, `width`, `height`, optional `audio` storage key,
|
|
480
|
+
* `codec` (`h264` default, `vp9` for WebM), optional `crf`, and
|
|
481
|
+
* the required `target` storage key.
|
|
482
|
+
* @returns A handle to poll. `output_key` is `request.target`.
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```ts
|
|
486
|
+
* const handle = await platform.env.FRAMES.render({
|
|
487
|
+
* path: '/render/hello',
|
|
488
|
+
* fps: 30,
|
|
489
|
+
* duration_ms: 2000,
|
|
490
|
+
* width: 1280,
|
|
491
|
+
* height: 720,
|
|
492
|
+
* target: 'renders/hello.mp4',
|
|
493
|
+
* });
|
|
494
|
+
* ```
|
|
495
|
+
*/
|
|
496
|
+
render(request: FramesRenderRequest): Promise<BrowserJobHandle>;
|
|
497
|
+
}
|
|
297
498
|
/**
|
|
298
499
|
* Authenticated user record from the platform auth service.
|
|
299
500
|
*/
|
|
@@ -969,6 +1170,10 @@ export interface Platform {
|
|
|
969
1170
|
KV: KvStore;
|
|
970
1171
|
DB: Database;
|
|
971
1172
|
STORAGE: Storage;
|
|
1173
|
+
/** Headless-browser screenshot / PDF — Phase 1 stub, real impl in Task #2. */
|
|
1174
|
+
BROWSER: BrowserClient;
|
|
1175
|
+
/** Deterministic HTML → MP4 / WebM render — Phase 1 stub, real impl in Task #3. */
|
|
1176
|
+
FRAMES: FramesClient;
|
|
972
1177
|
};
|
|
973
1178
|
}
|
|
974
1179
|
/**
|
package/index.ts
CHANGED
|
@@ -338,6 +338,232 @@ export interface Storage {
|
|
|
338
338
|
getMetadata(key: string): Promise<StorageMetadata>;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
// ════════════════════════════════════════════════════════════════════
|
|
342
|
+
// Headless browser + deterministic-video render
|
|
343
|
+
// ════════════════════════════════════════════════════════════════════
|
|
344
|
+
//
|
|
345
|
+
// Same JobHandle / polling model as the existing media-transforms surface
|
|
346
|
+
// (`@maravilla-labs/platform`'s `transforms.ts`): every mutating method
|
|
347
|
+
// returns a {@link BrowserJobHandle} the caller polls until the status is
|
|
348
|
+
// terminal. Phase 1 wires the contract surface end-to-end — the underlying
|
|
349
|
+
// worker returns `failed("not implemented")` until Task #2 and Task #3
|
|
350
|
+
// implement the Chromium + ffmpeg pipelines.
|
|
351
|
+
|
|
352
|
+
/** Output image format for browser screenshots. */
|
|
353
|
+
export type ScreenshotFormat = 'png' | 'jpeg' | 'webp';
|
|
354
|
+
|
|
355
|
+
/** Page-size preset for browser PDF renders. */
|
|
356
|
+
export type PdfPageFormat = 'A4' | 'A3' | 'Letter' | 'Legal' | 'Tabloid';
|
|
357
|
+
|
|
358
|
+
/** Video codec for deterministic frame renders. */
|
|
359
|
+
export type FramesCodec = 'h264' | 'vp9';
|
|
360
|
+
|
|
361
|
+
/** Lifecycle state of a browser / frames job. Mirrors transforms `JobStatus`. */
|
|
362
|
+
export type BrowserJobStatus = 'pending' | 'running' | 'complete' | 'failed';
|
|
363
|
+
|
|
364
|
+
/** Viewport (CSS pixels) the headless browser launches with. */
|
|
365
|
+
export interface BrowserViewport {
|
|
366
|
+
width: number;
|
|
367
|
+
height: number;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* "Wait until" predicate before the screenshot / PDF capture fires.
|
|
372
|
+
* Set at most one of `selector`, `network_idle`, or `ms`; the worker
|
|
373
|
+
* picks the first non-null in that order.
|
|
374
|
+
*/
|
|
375
|
+
export interface BrowserWaitFor {
|
|
376
|
+
/** CSS selector that must resolve before the capture fires. */
|
|
377
|
+
selector?: string;
|
|
378
|
+
/** Wait for the network to go idle (~500ms with no in-flight requests). */
|
|
379
|
+
network_idle?: boolean;
|
|
380
|
+
/** Sleep for this many milliseconds then capture. Capped at ~30s by the worker. */
|
|
381
|
+
ms?: number;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** Cookie pre-installed on the browser context before navigation. */
|
|
385
|
+
export interface BrowserCookie {
|
|
386
|
+
name: string;
|
|
387
|
+
value: string;
|
|
388
|
+
domain?: string;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Request shape for `platform.env.BROWSER.screenshot(...)`.
|
|
393
|
+
*
|
|
394
|
+
* Exactly one of `url` (public URL — SSRF-gated by the worker) or `path`
|
|
395
|
+
* (relative path resolved against the tenant's deployment via loopback
|
|
396
|
+
* to Delivery) must be set.
|
|
397
|
+
*/
|
|
398
|
+
export interface ScreenshotRequest {
|
|
399
|
+
/** Public URL. Worker blocks loopback / RFC1918 / link-local after DNS. */
|
|
400
|
+
url?: string;
|
|
401
|
+
/** Path on the tenant's own deployment, e.g. `/dashboard`. */
|
|
402
|
+
path?: string;
|
|
403
|
+
viewport?: BrowserViewport;
|
|
404
|
+
wait_for?: BrowserWaitFor;
|
|
405
|
+
/** Capture the full scrollable page rather than the viewport. */
|
|
406
|
+
full_page?: boolean;
|
|
407
|
+
/** Defaults to `"png"` server-side when omitted. */
|
|
408
|
+
format?: ScreenshotFormat;
|
|
409
|
+
/** JPEG / WebP quality 1–100. Ignored for PNG. */
|
|
410
|
+
quality?: number;
|
|
411
|
+
cookies?: BrowserCookie[];
|
|
412
|
+
/** Extra HTTP headers applied to every navigation request. */
|
|
413
|
+
headers?: Record<string, string>;
|
|
414
|
+
/** Storage key where the PNG / JPEG / WebP is written. Required. */
|
|
415
|
+
target: string;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Request shape for `platform.env.BROWSER.pdf(...)`. Same `url`/`path`
|
|
420
|
+
* discipline as {@link ScreenshotRequest}.
|
|
421
|
+
*/
|
|
422
|
+
export interface PdfRequest {
|
|
423
|
+
url?: string;
|
|
424
|
+
path?: string;
|
|
425
|
+
/** Defaults to `"A4"` server-side when omitted. */
|
|
426
|
+
format?: PdfPageFormat;
|
|
427
|
+
landscape?: boolean;
|
|
428
|
+
/** Render CSS background colour / images. Defaults `true` server-side. */
|
|
429
|
+
print_background?: boolean;
|
|
430
|
+
cookies?: BrowserCookie[];
|
|
431
|
+
headers?: Record<string, string>;
|
|
432
|
+
target: string;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Request shape for `platform.env.FRAMES.render(...)`.
|
|
437
|
+
*
|
|
438
|
+
* Path-only on purpose: the renderer drives one of the tenant's own
|
|
439
|
+
* deployment routes (which is expected to import `@maravilla/frames`
|
|
440
|
+
* and call `defineTimeline({...})`) frame-by-frame via CDP
|
|
441
|
+
* `HeadlessExperimental.beginFrame`.
|
|
442
|
+
*/
|
|
443
|
+
export interface FramesRenderRequest {
|
|
444
|
+
/** Path on the tenant's deployment, e.g. `/render/intro-card?title=Hi`. */
|
|
445
|
+
path: string;
|
|
446
|
+
/** Frames per second. Must be ≥ 1; worker caps the upper bound. */
|
|
447
|
+
fps: number;
|
|
448
|
+
/** Total clip duration in milliseconds. */
|
|
449
|
+
duration_ms: number;
|
|
450
|
+
/** Output width (CSS pixels). Doubles as the browser viewport width. */
|
|
451
|
+
width: number;
|
|
452
|
+
/** Output height. */
|
|
453
|
+
height: number;
|
|
454
|
+
/** Storage key of an optional audio track ffmpeg mixes in. */
|
|
455
|
+
audio?: string;
|
|
456
|
+
/** Defaults to `"h264"` server-side when omitted. */
|
|
457
|
+
codec?: FramesCodec;
|
|
458
|
+
/** Constant Rate Factor for the encoder. Worker picks a default when unset. */
|
|
459
|
+
crf?: number;
|
|
460
|
+
/** Storage key the MP4 / WebM is written to. Required — no auto-generation. */
|
|
461
|
+
target: string;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Handle returned by every BROWSER / FRAMES method. `output_key` is the
|
|
466
|
+
* caller-supplied `target` and is known up front; status updates as the
|
|
467
|
+
* worker progresses through the shared transforms job ledger.
|
|
468
|
+
*/
|
|
469
|
+
export interface BrowserJobHandle {
|
|
470
|
+
id: string;
|
|
471
|
+
src_key: string;
|
|
472
|
+
output_key: string;
|
|
473
|
+
status: BrowserJobStatus;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Headless-browser surface exposed as `platform.env.BROWSER`.
|
|
478
|
+
*/
|
|
479
|
+
export interface BrowserClient {
|
|
480
|
+
/**
|
|
481
|
+
* Capture a screenshot of a public URL or one of the tenant's own
|
|
482
|
+
* routes. Returns a {@link BrowserJobHandle} whose `output_key` equals
|
|
483
|
+
* the caller-supplied `request.target` and is known up front — poll
|
|
484
|
+
* `platform.media.transforms.job(handle.id)` for status, then fetch
|
|
485
|
+
* the bytes from `platform.env.STORAGE` once the job completes.
|
|
486
|
+
*
|
|
487
|
+
* Exactly one of `request.url` or `request.path` must be set.
|
|
488
|
+
* `url` mode is gated by an SSRF block-list applied after DNS
|
|
489
|
+
* resolution; `path` mode loopback-routes to the tenant's own
|
|
490
|
+
* deployment.
|
|
491
|
+
*
|
|
492
|
+
* @param request `url` (public, SSRF-gated) or `path` (own deployment),
|
|
493
|
+
* plus optional `viewport`, `wait_for`, `format`, `cookies`,
|
|
494
|
+
* `headers`, and the required `target` storage key.
|
|
495
|
+
* @returns A handle to poll. `output_key` is `request.target`.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```ts
|
|
499
|
+
* const handle = await platform.env.BROWSER.screenshot({
|
|
500
|
+
* url: 'https://example.com',
|
|
501
|
+
* viewport: { width: 1280, height: 720 },
|
|
502
|
+
* target: 'shots/example.png',
|
|
503
|
+
* });
|
|
504
|
+
* // poll handle.id via platform.media.transforms.job(...)
|
|
505
|
+
* ```
|
|
506
|
+
*/
|
|
507
|
+
screenshot(request: ScreenshotRequest): Promise<BrowserJobHandle>;
|
|
508
|
+
/**
|
|
509
|
+
* Render the target page to a PDF. Same `url` xor `path` discipline
|
|
510
|
+
* as {@link BrowserClient.screenshot}.
|
|
511
|
+
*
|
|
512
|
+
* @param request `url` or `path`, plus optional `format` (page-size
|
|
513
|
+
* preset), `landscape`, `print_background`, `cookies`, `headers`,
|
|
514
|
+
* and the required `target` storage key.
|
|
515
|
+
* @returns A handle to poll. `output_key` is `request.target`.
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* ```ts
|
|
519
|
+
* const handle = await platform.env.BROWSER.pdf({
|
|
520
|
+
* path: '/invoices/INV-1042',
|
|
521
|
+
* format: 'A4',
|
|
522
|
+
* print_background: true,
|
|
523
|
+
* target: 'invoices/INV-1042.pdf',
|
|
524
|
+
* });
|
|
525
|
+
* ```
|
|
526
|
+
*/
|
|
527
|
+
pdf(request: PdfRequest): Promise<BrowserJobHandle>;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Deterministic-video surface exposed as `platform.env.FRAMES`.
|
|
532
|
+
*/
|
|
533
|
+
export interface FramesClient {
|
|
534
|
+
/**
|
|
535
|
+
* Render one of the tenant's own deployment routes to MP4 / WebM,
|
|
536
|
+
* frame-accurately. The route is expected to import
|
|
537
|
+
* `@maravilla-labs/frames` and call `defineTimeline({...})` at load
|
|
538
|
+
* time — the worker drives `window.__mvFrames.applyState(t)` once
|
|
539
|
+
* per frame and captures via CDP `HeadlessExperimental.beginFrame`,
|
|
540
|
+
* piping PNG frames into ffmpeg.
|
|
541
|
+
*
|
|
542
|
+
* Same render against the same route is deterministic — two
|
|
543
|
+
* back-to-back renders produce byte-identical output (modulo
|
|
544
|
+
* already-stripped muxer metadata).
|
|
545
|
+
*
|
|
546
|
+
* @param request `path` on the tenant's deployment, `fps`,
|
|
547
|
+
* `duration_ms`, `width`, `height`, optional `audio` storage key,
|
|
548
|
+
* `codec` (`h264` default, `vp9` for WebM), optional `crf`, and
|
|
549
|
+
* the required `target` storage key.
|
|
550
|
+
* @returns A handle to poll. `output_key` is `request.target`.
|
|
551
|
+
*
|
|
552
|
+
* @example
|
|
553
|
+
* ```ts
|
|
554
|
+
* const handle = await platform.env.FRAMES.render({
|
|
555
|
+
* path: '/render/hello',
|
|
556
|
+
* fps: 30,
|
|
557
|
+
* duration_ms: 2000,
|
|
558
|
+
* width: 1280,
|
|
559
|
+
* height: 720,
|
|
560
|
+
* target: 'renders/hello.mp4',
|
|
561
|
+
* });
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
render(request: FramesRenderRequest): Promise<BrowserJobHandle>;
|
|
565
|
+
}
|
|
566
|
+
|
|
341
567
|
// ════════════════════════════════════════════════════════════════════
|
|
342
568
|
// Auth, Stewardship, Resources, Circles, Groups, Relations
|
|
343
569
|
// ════════════════════════════════════════════════════════════════════
|
|
@@ -1136,6 +1362,10 @@ export interface Platform {
|
|
|
1136
1362
|
KV: KvStore;
|
|
1137
1363
|
DB: Database;
|
|
1138
1364
|
STORAGE: Storage;
|
|
1365
|
+
/** Headless-browser screenshot / PDF — Phase 1 stub, real impl in Task #2. */
|
|
1366
|
+
BROWSER: BrowserClient;
|
|
1367
|
+
/** Deterministic HTML → MP4 / WebM render — Phase 1 stub, real impl in Task #3. */
|
|
1368
|
+
FRAMES: FramesClient;
|
|
1139
1369
|
};
|
|
1140
1370
|
}
|
|
1141
1371
|
|