pup-recorder 0.4.2 → 0.4.4

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/biome.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/latest/schema.json",
3
+ "root": false,
4
+ "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 120 },
5
+ "javascript": { "formatter": { "quoteStyle": "double", "semicolons": "always", "trailingCommas": "all" } },
6
+ "linter": {
7
+ "rules": {
8
+ "complexity": { "useLiteralKeys": "off" },
9
+ "style": {
10
+ "noNonNullAssertion": "off",
11
+ "useBlockStatements": "error",
12
+ "useNamingConvention": {
13
+ "level": "error",
14
+ "options": {
15
+ "strictCase": false,
16
+ "conventions": [
17
+ { "selector": { "kind": "classProperty", "modifiers": ["private"] }, "match": "_(.+)" },
18
+ { "selector": { "kind": "classMethod", "modifiers": ["private"] }, "match": "[^_].*" },
19
+ { "selector": { "kind": "typeProperty" }, "match": "__.+|[a-z][A-Za-z0-9]*|[a-z][a-z0-9]*(?:_[a-z0-9]+)*|[A-Z][A-Za-z0-9]*|[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*" },
20
+ { "selector": { "kind": "objectLiteralProperty" }, "formats": ["camelCase", "snake_case", "PascalCase", "CONSTANT_CASE"] },
21
+ { "selector": { "kind": "variable" }, "formats": ["camelCase", "snake_case", "PascalCase", "CONSTANT_CASE"] },
22
+ { "selector": { "kind": "enumMember" }, "formats": ["PascalCase", "CONSTANT_CASE"] }
23
+ ]
24
+ }
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "files": { "includes": ["src/**/*.ts"] }
30
+ }
package/build.ts CHANGED
@@ -7,9 +7,12 @@ import { dependencies } from "./package.json";
7
7
 
8
8
  const require = createRequire(import.meta.url);
9
9
  const tsPath = require.resolve("@typescript/native-preview/package.json");
10
- const tsgo = join(tsPath, "..", "bin", "tsgo.js");
10
+ const tsgo = join(tsPath, "..", require(tsPath).bin.tsgo);
11
+ const biomePath = require.resolve("@biomejs/biome/package.json");
12
+ const biome = join(biomePath, "..", "bin", "biome");
11
13
 
12
14
  await $`${tsgo}`;
15
+ await $`${biome} check --write --error-on-warnings`;
13
16
  await rm("dist", { recursive: true, force: true });
14
17
 
15
18
  const common: Options = {
@@ -38,8 +41,8 @@ await build({
38
41
  ...common,
39
42
  entry: [
40
43
  "src/app.ts", //
41
- "src/audio_preload.ts",
42
- "src/iframe_preload.ts",
44
+ "src/runtime/audio_preload.ts",
45
+ "src/runtime/iframe_preload.ts",
43
46
  ],
44
47
  format: "cjs",
45
48
  outDir: "dist",
@@ -3,33 +3,41 @@ import { AV_SAMPLE_FMT_FLTP } from 'node-av/constants';
3
3
  import { AVColorRange } from 'node-av/constants';
4
4
  import { AVPixelFormat } from 'node-av/constants';
5
5
  import { BrowserWindow } from 'electron';
6
- import { ChildProcess } from 'child_process';
6
+ import { ChildProcess } from 'node:child_process';
7
7
  import { Codec } from 'node-av';
8
8
  import { CodecContext } from 'node-av';
9
- import { Debugger } from 'electron';
10
- import { EventEmitter } from 'events';
9
+ import type { Debugger } from 'electron';
10
+ import { Demuxer } from 'node-av/api';
11
+ import { EventEmitter } from 'node:events';
11
12
  import { FFAudioEncoder } from 'node-av/constants';
12
- import { FFVideoEncoder } from 'node-av/constants';
13
- import { FormatContext } from 'node-av';
13
+ import type { FFVideoEncoder } from 'node-av/constants';
14
14
  import { Frame } from 'node-av';
15
15
  import { HardwareContext } from 'node-av/api';
16
16
  import { HardwareFramesContext } from 'node-av';
17
17
  import type { NativeImage } from 'electron';
18
18
  import { Packet } from 'node-av';
19
- import { Size } from 'electron';
19
+ import type { Size } from 'electron';
20
20
  import { SoftwareScaleContext } from 'node-av';
21
- import { SpawnOptions } from 'child_process';
21
+ import { SpawnOptions } from 'node:child_process';
22
22
  import { Stream } from 'node-av';
23
- import { WebContents } from 'electron';
23
+ import type { WebContents } from 'electron';
24
24
  import type { WebFrameMain } from 'electron';
25
25
  import z from 'zod';
26
26
 
27
+ export declare function abortable<T>(p: Promise<T>, signal?: AbortSignal): Promise<T>;
28
+
27
29
  /** Insert emulation prevention bytes (00 00 03) for Annex B compliance. */
28
30
  export declare function addEmulationPrevention(nal: Buffer): Buffer;
29
31
 
30
32
  export declare function advance(hook: VideoHook, timestampMs: number): Promise<unknown>;
31
33
 
32
- export declare function advanceVideos(frame: WebFrameMain | undefined, timestampMs: number): Promise<void>;
34
+ export declare interface AdvanceOptions {
35
+ frame: WebFrameMain | undefined;
36
+ timestampMs: number;
37
+ signal?: AbortSignal;
38
+ }
39
+
40
+ export declare function advanceVideos({ frame, timestampMs, signal }: AdvanceOptions): Promise<void>;
33
41
 
34
42
  export declare function advanceVirtualTime(cdp: Debugger, budget: number): Promise<void>;
35
43
 
@@ -135,7 +143,7 @@ export declare function buildStegoHTML(targetURL: string, size: Size): string;
135
143
  export declare function buildUnifiedExtradata(opts: UnifiedExtradataOptions): Buffer;
136
144
 
137
145
  export declare interface CancelMsg {
138
- type: IpcMsgType.CANCEL;
146
+ type: IpcMsgType.Cancel;
139
147
  reason?: string;
140
148
  }
141
149
 
@@ -189,7 +197,7 @@ export declare class ConcurrencyLimiter {
189
197
  export declare type ConsoleCallback = (level: string, message: string) => void;
190
198
 
191
199
  export declare interface ConsoleMsg {
192
- type: IpcMsgType.CONSOLE;
200
+ type: IpcMsgType.Console;
193
201
  level: string;
194
202
  message: string;
195
203
  }
@@ -200,22 +208,32 @@ export declare function createStegoURL(src: string, size: Size): string;
200
208
 
201
209
  export declare function debounce<T extends (...args: unknown[]) => void>(fn: T, delay?: number): T;
202
210
 
211
+ export declare interface DecodedFrame {
212
+ idx: number;
213
+ buf: Buffer;
214
+ }
215
+
216
+ export declare function decodeFrames(src: string, meta: VideoMeta, signal: AbortSignal): AsyncGenerator<DecodedFrame>;
217
+
203
218
  export declare class DecodeSession {
204
219
  readonly meta: VideoMeta;
205
- private readonly src;
206
- private buf;
207
- private ready;
208
- private want;
209
- private done;
210
- private closed;
211
- private gen;
212
- private ctrl;
213
- private waiters;
214
- private resume;
215
- private restart;
216
- constructor(meta: VideoMeta, src: string);
220
+ private readonly _src;
221
+ private _buf;
222
+ private _ready;
223
+ private _want;
224
+ private _done;
225
+ private _closed;
226
+ private _gen;
227
+ private _ctrl;
228
+ private _waiters;
229
+ private _resume;
230
+ private _restart;
231
+ private readonly _leadFrames;
232
+ private readonly _keepCount;
233
+ private readonly _pumpDone;
234
+ constructor(meta: VideoMeta, _src: string);
217
235
  getFrame(idx: number): Promise<Buffer>;
218
- close(): void;
236
+ close(): Promise<void>;
219
237
  private wait;
220
238
  private wake;
221
239
  private requestRestart;
@@ -247,12 +265,16 @@ declare const DEFAULT_WIDTH = 1920;
247
265
  export { DEFAULT_WIDTH }
248
266
  export { DEFAULT_WIDTH as DEFAULT_WIDTH_alias_1 }
249
267
 
268
+ declare const DEFAULT_WINDOW_TIMEOUT = 10;
269
+ export { DEFAULT_WINDOW_TIMEOUT }
270
+ export { DEFAULT_WINDOW_TIMEOUT as DEFAULT_WINDOW_TIMEOUT_alias_1 }
271
+
250
272
  export declare const defaultRenderOptions: RenderOptions;
251
273
 
252
274
  export declare function disposeWindow(win: BrowserWindow): Promise<void>;
253
275
 
254
276
  export declare interface DoneMsg {
255
- type: IpcMsgType.DONE;
277
+ type: IpcMsgType.Done;
256
278
  payload: IpcDonePayload;
257
279
  }
258
280
 
@@ -310,7 +332,7 @@ export declare interface EncoderPipelineOptions {
310
332
  export declare type EnvParser<T> = (value: unknown) => T;
311
333
 
312
334
  export declare interface ErrorMsg {
313
- type: IpcMsgType.ERROR;
335
+ type: IpcMsgType.Error;
314
336
  error: string;
315
337
  }
316
338
 
@@ -327,8 +349,9 @@ export declare function fitRect(srcW: number, srcH: number, dstW: number, dstH:
327
349
  export declare class FormatMuxer {
328
350
  private readonly _ctx;
329
351
  private _opened;
352
+ private _disposed;
330
353
  constructor(outPath: string, formatName?: string);
331
- addStream(codecCtx: CodecContext, codecTag?: string): ReturnType<FormatContext["newStream"]>;
354
+ addStream(codecCtx: CodecContext, codecTag?: string): Stream;
332
355
  open(): Promise<void>;
333
356
  writePacket(pkt: Packet): Promise<void>;
334
357
  [Symbol.asyncDispose](): Promise<void>;
@@ -339,9 +362,9 @@ export declare const FRAME_SYNC_MARKER_HEIGHT = 1;
339
362
  export declare const FRAME_SYNC_MARKER_WIDTH = 32;
340
363
 
341
364
  export declare class FrameCache {
342
- private caches;
365
+ private _caches;
343
366
  cacheOf(id: string): VideoCache;
344
- fetch(state: VideoState, idx: number): Promise<ImageBitmap | null>;
367
+ fetch(state: VideoState, idx: number): Promise<ImageBitmap | undefined>;
345
368
  prefetch(state: VideoState, fromIdx: number, count: number): void;
346
369
  evict(c: VideoCache): void;
347
370
  release(id: string, state: VideoState): void;
@@ -382,19 +405,16 @@ export declare class FrameDropStats {
382
405
  }
383
406
 
384
407
  export declare class FrameServer {
385
- private sessions;
386
- private srcs;
387
- private inFlightOpens;
388
- private closed;
408
+ private readonly _useInnerProxy;
409
+ private _sessions;
410
+ private _closed;
411
+ constructor(_useInnerProxy: boolean);
389
412
  open(opts: OpenOptions): Promise<VideoMeta>;
390
- private openInner;
391
413
  getFrame(id: string, idx: number): Promise<Buffer>;
392
- close(id: string): void;
414
+ close(id: string): Promise<void>;
393
415
  closeAll(): Promise<void>;
394
416
  }
395
417
 
396
- export declare const frameServer: FrameServer;
397
-
398
418
  export declare const HAVE_ENOUGH_DATA = 4;
399
419
 
400
420
  export declare const HAVE_METADATA = 1;
@@ -445,12 +465,12 @@ export declare interface IpcEvents {
445
465
 
446
466
  export declare type IpcMsg = ConsoleMsg | ProgressMsg | DoneMsg | ErrorMsg | CancelMsg;
447
467
 
448
- export declare const enum IpcMsgType {
449
- CONSOLE = "console",
450
- PROGRESS = "progress",
451
- DONE = "done",
452
- ERROR = "error",
453
- CANCEL = "cancel"
468
+ export declare enum IpcMsgType {
469
+ Console = "console",
470
+ Progress = "progress",
471
+ Done = "done",
472
+ Error = "error",
473
+ Cancel = "cancel"
454
474
  }
455
475
 
456
476
  export declare class IpcReader extends EventEmitter<IpcEvents> {
@@ -579,7 +599,7 @@ export declare interface NetworkOptions {
579
599
 
580
600
  export declare function newVideoState(video: HTMLVideoElement, cv: HTMLCanvasElement): VideoState;
581
601
 
582
- declare function noerr<Fn extends (...args: any[]) => any, D>(fn: Fn, defaultValue: D): (...args: Parameters<Fn>) => ReturnType<Fn> | D;
602
+ declare function noerr<A extends unknown[], R, D>(fn: (...args: A) => R, defaultValue: D): (...args: A) => R | D;
583
603
  export { noerr }
584
604
  export { noerr as noerr_alias_1 }
585
605
 
@@ -606,6 +626,8 @@ export declare interface NvencHevcConfig {
606
626
  ppsHasLoopFilterAcrossSlicesFlag: boolean;
607
627
  }
608
628
 
629
+ export declare function openInput(src: string, signal?: AbortSignal): Promise<Demuxer>;
630
+
609
631
  export declare interface OpenOptions {
610
632
  src: string;
611
633
  fps: number;
@@ -616,7 +638,7 @@ export declare interface OpenOptions {
616
638
  fit?: string;
617
639
  }
618
640
 
619
- export declare function openSession(hook: VideoHook, args: AttachArgs): Promise<VideoState | null>;
641
+ export declare function openSession(hook: VideoHook, args: AttachArgs): Promise<VideoState | undefined>;
620
642
 
621
643
  export declare function openVideoCtx(opts: VideoCtxOptions, label: string): Promise<CodecContext>;
622
644
 
@@ -661,7 +683,7 @@ declare function penv<T>(name: string, parser: EnvParser<T>, defaultValue?: T):
661
683
  export { penv }
662
684
  export { penv as penv_alias_1 }
663
685
 
664
- declare function periodical(callback: (count: number) => Promise<void> | void, ms: number): () => void;
686
+ declare function periodical(callback: (count: number) => Promise<number | undefined> | undefined, ms: number): () => void;
665
687
  export { periodical }
666
688
  export { periodical as periodical_alias_1 }
667
689
 
@@ -671,6 +693,8 @@ export declare interface ProbeResult {
671
693
  width: number;
672
694
  height: number;
673
695
  duration: number;
696
+ /** PTS (s) of the first decodable frame; a corrupt/empty leading run is held on it, like Chrome. */
697
+ leadGap: number;
674
698
  }
675
699
 
676
700
  export declare interface ProcessHandle {
@@ -705,7 +729,7 @@ export { ProgressCallback }
705
729
  export { ProgressCallback as ProgressCallback_alias_1 }
706
730
 
707
731
  export declare interface ProgressMsg {
708
- type: IpcMsgType.PROGRESS;
732
+ type: IpcMsgType.Progress;
709
733
  value: number;
710
734
  }
711
735
 
@@ -745,7 +769,7 @@ export declare function removeEmulationPrevention(data: Buffer): Buffer;
745
769
 
746
770
  export declare function render(options: IPCRenderOptions): Promise<IpcDonePayload>;
747
771
 
748
- declare type RenderOptions = z.infer<typeof RenderSchema>;
772
+ declare type RenderOptions = z.infer<typeof renderSchema>;
749
773
  export { RenderOptions }
750
774
  export { RenderOptions as RenderOptions_alias_1 }
751
775
 
@@ -758,7 +782,7 @@ declare interface RenderResult {
758
782
  export { RenderResult }
759
783
  export { RenderResult as RenderResult_alias_1 }
760
784
 
761
- export declare const RenderSchema: z.ZodObject<{
785
+ export declare const renderSchema: z.ZodObject<{
762
786
  duration: z.ZodNumber;
763
787
  width: z.ZodNumber;
764
788
  height: z.ZodNumber;
@@ -770,11 +794,12 @@ export declare const RenderSchema: z.ZodObject<{
770
794
  disableGpu: z.ZodBoolean;
771
795
  disableHwCodec: z.ZodBoolean;
772
796
  windowTolerant: z.ZodBoolean;
797
+ windowTimeout: z.ZodNumber;
773
798
  }, z.core.$strip>;
774
799
 
775
800
  export declare function resizeDrawable(cdp: Debugger, size: Size): Promise<void>;
776
801
 
777
- declare interface RetryOptions<Args extends any[], Ret> {
802
+ declare interface RetryOptions<Args extends unknown[], Ret> {
778
803
  fn: (...args: Args) => Promise<Ret>;
779
804
  maxAttempts?: number;
780
805
  timeout?: number;
@@ -816,8 +841,6 @@ export declare function setInterceptor({ source, window, useInnerProxy, cancelMe
816
841
 
817
842
  export declare function setupCanvas(video: HTMLVideoElement, snap: OffscreenCanvas | undefined): HTMLCanvasElement;
818
843
 
819
- export declare function setupFrameProtocol(): void;
820
-
821
844
  export declare function setupPupProtocol(): void;
822
845
 
823
846
  export declare function shoot(options: IPCRenderOptions): Promise<IpcDonePayload>;
@@ -844,15 +867,6 @@ export { sleep as sleep_alias_1 }
844
867
  /** Split Annex B bitstream into NAL units. */
845
868
  export declare function splitNalUnits(bitstream: Buffer): NalUnit[];
846
869
 
847
- export declare class SrcCache {
848
- private inFlight;
849
- private ctrl;
850
- localize(src: string): Promise<string>;
851
- abort(): void;
852
- clear(): Promise<void>;
853
- private download;
854
- }
855
-
856
870
  export declare function startElectronCrashReporter(): void;
857
871
 
858
872
  export declare function startStego(cdp: Debugger): Promise<unknown>;
@@ -867,7 +881,7 @@ export declare function syncOverlay(video: HTMLVideoElement, cv: HTMLCanvasEleme
867
881
 
868
882
  export declare const TAG = "[VideoHook]";
869
883
 
870
- export declare function tick(frame: WebFrameMain | undefined, timestampMs: number): Promise<void>;
884
+ export declare function tick(args: AdvanceOptions): Promise<void>;
871
885
 
872
886
  export declare const TICK_SYMBOL = "__pup_tick__";
873
887
 
@@ -888,7 +902,9 @@ export declare interface UnifiedExtradataOptions {
888
902
 
889
903
  export declare function unsetInterceptor(window: BrowserWindow): void;
890
904
 
891
- declare function useRetry<Args extends any[], Ret>({ fn, maxAttempts, timeout, signal }: RetryOptions<Args, Ret>): (...args: Args) => Promise<Ret>;
905
+ export declare function useFrameProtocol(useInnerProxy: boolean): AsyncDisposable;
906
+
907
+ declare function useRetry<Args extends unknown[], Ret>({ fn, maxAttempts, timeout, signal, }: RetryOptions<Args, Ret>): (...args: Args) => Promise<Ret>;
892
908
  export { useRetry }
893
909
  export { useRetry as useRetry_alias_1 }
894
910
 
@@ -896,7 +912,7 @@ declare type Vec4 = [number, number, number, number];
896
912
 
897
913
  export declare interface VideoCache {
898
914
  bitmaps: Map<number, ImageBitmap>;
899
- inFlight: Map<number, Promise<ImageBitmap | null>>;
915
+ inFlight: Map<number, Promise<ImageBitmap | undefined>>;
900
916
  readers: Map<VideoState, number>;
901
917
  }
902
918
 
@@ -950,13 +966,15 @@ export declare interface VideoFrameMeta {
950
966
 
951
967
  export declare class VideoHook {
952
968
  readonly sessions: WeakMap<HTMLVideoElement, VideoState>;
953
- readonly attaching: WeakMap<HTMLVideoElement, Promise<VideoState | null>>;
969
+ readonly attaching: WeakMap<HTMLVideoElement, Promise<VideoState | undefined>>;
970
+ readonly opening: Set<Promise<unknown>>;
954
971
  readonly cache: FrameCache;
955
972
  rvfcSeq: number;
956
973
  currMs: number;
957
- private lastSnapshot;
974
+ private _lastSnapshot;
958
975
  install(): void;
959
- attach(video: HTMLVideoElement, native?: boolean): Promise<VideoState | null>;
976
+ attach(video: HTMLVideoElement, native?: boolean): Promise<VideoState | undefined>;
977
+ ready(): Promise<void>;
960
978
  resume(video: HTMLVideoElement, state: VideoState): void;
961
979
  detach(video: HTMLVideoElement): void;
962
980
  onSrcChange(video: HTMLVideoElement): void;
@@ -974,6 +992,8 @@ export declare interface VideoMeta {
974
992
  frameHeight: number;
975
993
  fps: number;
976
994
  duration: number;
995
+ /** Seconds of corrupt/empty leading content held on the first decodable frame. */
996
+ leadGap: number;
977
997
  }
978
998
 
979
999
  export declare interface VideoMeta_alias_1 {
@@ -995,7 +1015,7 @@ export declare interface VideoSetup {
995
1015
  }
996
1016
 
997
1017
  export declare interface VideoState {
998
- meta: VideoMeta_alias_1 | null;
1018
+ meta?: VideoMeta_alias_1;
999
1019
  cv: HTMLCanvasElement;
1000
1020
  ctx: CanvasRenderingContext2D;
1001
1021
  paused: boolean;