pup-recorder 0.2.6 → 0.2.8

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/build.ts CHANGED
@@ -3,15 +3,12 @@ import { rm } from "fs/promises";
3
3
  import { createRequire } from "module";
4
4
  import { join } from "path";
5
5
  import { build, type Options } from "tsup";
6
- import { buildRust } from "./build_rust";
7
6
  import { dependencies } from "./package.json";
8
7
 
9
8
  const require = createRequire(import.meta.url);
10
9
  const tsPath = require.resolve("@typescript/native-preview/package.json");
11
10
  const tsgo = join(tsPath, "..", "bin", "tsgo.js");
12
11
 
13
- await buildRust();
14
-
15
12
  await $`${tsgo}`;
16
13
  await rm("dist", { recursive: true, force: true });
17
14
 
@@ -1,9 +1,11 @@
1
1
  import { AV_SAMPLE_FMT_FLT } from 'node-av/constants';
2
2
  import { AV_SAMPLE_FMT_FLTP } from 'node-av/constants';
3
+ import { AVPixelFormat } from 'node-av/constants';
3
4
  import { BrowserWindow } from 'electron';
4
5
  import { ChildProcess } from 'child_process';
5
6
  import { CodecContext } from 'node-av';
6
7
  import type { Debugger } from 'electron';
8
+ import { EventEmitter } from 'events';
7
9
  import { FFAudioEncoder } from 'node-av/constants';
8
10
  import { FFVideoEncoder } from 'node-av/constants';
9
11
  import { FormatContext } from 'node-av';
@@ -11,23 +13,31 @@ import { Frame } from 'node-av';
11
13
  import type { NativeImage } from 'electron';
12
14
  import { Packet } from 'node-av';
13
15
  import { Size } from 'electron';
16
+ import { Socket } from 'net';
17
+ import { SoftwareScaleContext } from 'node-av';
14
18
  import { SpawnOptions } from 'child_process';
15
19
  import z from 'zod';
16
20
 
17
21
  export declare function advanceVirtualTime(cdp: Debugger, budget: number): Promise<void>;
18
22
 
19
23
  export declare interface AudioCapture {
20
- teardown(): Promise<AudioSpec | undefined>;
24
+ teardown(): Promise<void>;
25
+ }
26
+
27
+ export declare interface AudioCaptureOptions {
28
+ encoder: EncoderPipeline;
29
+ getVideoTimeMs: () => number;
30
+ onError: (error: Error) => void;
21
31
  }
22
32
 
23
33
  declare class AudioEncoder_2 implements Disposable {
24
- private readonly _ctx;
25
- private readonly _stream;
26
- private readonly _outRate;
27
- private readonly _outFmt;
28
- private readonly _frameSize;
29
- private readonly _pkt;
30
- private readonly _filterFrame;
34
+ private _ctx;
35
+ private _stream;
36
+ private _pkt;
37
+ private _outRate;
38
+ private _outFmt;
39
+ private _frameSize;
40
+ private _filterFrame;
31
41
  private _graph?;
32
42
  private _bufSrc?;
33
43
  private _bufSink?;
@@ -35,14 +45,12 @@ declare class AudioEncoder_2 implements Disposable {
35
45
  private _pts;
36
46
  private constructor();
37
47
  static create(opts: AudioEncoderOptions): Promise<AudioEncoder_2>;
38
- /** Must be called once when the page's actual sample rate is known. */
39
48
  setInputRate(inSampleRate: number): void;
40
49
  encode(pcm: Buffer, muxer: FormatMuxer): Promise<void>;
41
50
  flush(muxer: FormatMuxer): Promise<void>;
42
51
  [Symbol.dispose](): void;
43
- private drainFilter;
52
+ private drain;
44
53
  private drainCodec;
45
- private disposeGraph;
46
54
  }
47
55
  export { AudioEncoder_2 as AudioEncoder }
48
56
 
@@ -55,36 +63,50 @@ export declare interface AudioEncoderOptions {
55
63
  muxer: FormatMuxer;
56
64
  }
57
65
 
58
- declare interface AudioSpec {
59
- pcmFile: string;
60
- pcmStartMs: number;
61
- pcmSampleRate: number;
62
- }
63
- export { AudioSpec }
64
- export { AudioSpec as AudioSpec_alias_1 }
65
-
66
66
  export declare function buildRust(): Promise<void>;
67
67
 
68
68
  export declare function buildStegoHTML(targetURL: string, size: Size): string;
69
69
 
70
70
  /**
71
- * Builds the JS injector that hooks all time-related globals in the target iframe.
72
- * Guards against running in the wrapper (top-level) frame so the stego canvas is unaffected.
71
+ * Builds the JS injector that hooks all time-related globals in the target frame.
72
+ * In Electron/stego mode (default), guards against running in the top-level frame.
73
+ * In Puppeteer mode (skipFrameGuard: true), injects directly into the main document.
73
74
  * Must be injected via Page.addScriptToEvaluateOnNewDocument AND directly into
74
- * already-loaded sub-frames.
75
+ * already-loaded frames.
75
76
  */
76
- export declare function buildTickInjector(): string;
77
+ export declare function buildTickInjector(opts?: TickInjectorOptions): string;
77
78
 
78
79
  export declare const canIUseGPU: Promise<boolean>;
79
80
 
80
81
  export declare function checkHTML(source: string): void;
81
82
 
83
+ export declare function chromiumOptions(): Promise<string[]>;
84
+
82
85
  export declare interface CLIOptions {
83
86
  name: string;
84
87
  defaults: RenderOptions;
85
88
  run: (source: string, options: RenderOptions) => Promise<unknown>;
86
89
  }
87
90
 
91
+ declare class CodecState_2 implements Disposable {
92
+ readonly src: Frame;
93
+ readonly dst: Frame;
94
+ readonly pkt: Packet;
95
+ private _sws?;
96
+ private _png?;
97
+ static create(width: number, height: number): Promise<CodecState_2>;
98
+ private constructor();
99
+ /**
100
+ * Create a fresh PNG decoder context.
101
+ * The FFmpeg PNG decoder accumulates APNG blending state
102
+ * across frames, so a shared instance corrupts output when decoding standalone PNGs.
103
+ */
104
+ png(): Promise<CodecContext>;
105
+ get sws(): SoftwareScaleContext;
106
+ [Symbol.dispose](): void;
107
+ }
108
+ export { CodecState_2 as CodecState }
109
+
88
110
  declare class ConcurrencyLimiter {
89
111
  readonly maxConcurrency: number;
90
112
  private _active;
@@ -101,6 +123,10 @@ declare class ConcurrencyLimiter {
101
123
  export { ConcurrencyLimiter }
102
124
  export { ConcurrencyLimiter as ConcurrencyLimiter_alias_1 }
103
125
 
126
+ export declare function connectIpc(socketPath: string): Promise<IpcWriter>;
127
+
128
+ export declare function createIpcServer(socketPath: string): Promise<IpcServer>;
129
+
104
130
  export declare function createStegoURL(src: string, size: Size): string;
105
131
 
106
132
  export declare function decodeStego(bitmap: Buffer, size: Size): number | undefined;
@@ -133,31 +159,27 @@ export declare function doEject(): string;
133
159
 
134
160
  export declare function doProcess(timestampMs: number): string;
135
161
 
136
- export declare function electronOpts(): Promise<string[]>;
137
-
138
- export declare function encodeBgra({ summary, outFile, signal, onProgress }: EncodeBgraOptions): Promise<RenderResult>;
162
+ export declare function doPuppeteer(source: string, options: RenderOptions, onProgress?: (p: number) => void): Promise<IpcDonePayload>;
139
163
 
140
- export declare interface EncodeBgraOptions {
141
- summary: RenderResult;
142
- outFile: string;
143
- signal?: AbortSignal;
144
- onProgress?: PupProgressCallback;
145
- }
164
+ export declare function electronOpts(): Promise<string[]>;
146
165
 
147
166
  declare class EncoderPipeline {
148
- private readonly _state;
149
- private readonly _sws;
150
- private readonly _srcFrame;
151
- private readonly _yuvaFrame;
167
+ private _video;
168
+ private _audio;
169
+ private _muxer;
170
+ private _limiter;
171
+ private _outFile;
172
+ private _codec;
152
173
  private _disposed;
153
174
  private constructor();
154
- static create({ width, height, fps, outFile, withAudio, videoBitrate, audioBitrate, }: EncoderPipelineOptions): Promise<EncoderPipeline>;
175
+ static create(opts: EncoderPipelineOptions): Promise<EncoderPipeline>;
155
176
  setupAudio(sampleRate: number): void;
156
- encodeFrame(input: Buffer | Frame): Promise<void>;
177
+ encodeBGRA(input: Buffer): Promise<void>;
178
+ encodePNG(pngData: Buffer): Promise<void>;
157
179
  encodeAudio(pcm: Buffer): Promise<void>;
158
180
  finish(): Promise<string>;
159
181
  [Symbol.asyncDispose](): Promise<void>;
160
- private freeShared;
182
+ private free;
161
183
  }
162
184
  export { EncoderPipeline }
163
185
  export { EncoderPipeline as EncoderPipeline_alias_1 }
@@ -168,8 +190,6 @@ declare interface EncoderPipelineOptions {
168
190
  fps: number;
169
191
  outFile: string;
170
192
  withAudio?: boolean;
171
- videoBitrate?: number;
172
- audioBitrate?: number;
173
193
  }
174
194
  export { EncoderPipelineOptions }
175
195
  export { EncoderPipelineOptions as EncoderPipelineOptions_alias_1 }
@@ -193,7 +213,7 @@ export declare const FixedBufferWriter: FixedBufferWriter;
193
213
  declare class FormatMuxer {
194
214
  private readonly _ctx;
195
215
  private _opened;
196
- constructor(outPath: string);
216
+ constructor(outPath: string, formatName?: string);
197
217
  addStream(codecCtx: CodecContext, codecTag?: string): ReturnType<FormatContext["newStream"]>;
198
218
  open(): Promise<void>;
199
219
  writePacket(pkt: Packet): Promise<void>;
@@ -238,6 +258,49 @@ export declare class FrameDropStats {
238
258
  finalize(): FrameDropScore;
239
259
  }
240
260
 
261
+ export declare interface IpcDonePayload {
262
+ written: number;
263
+ jank: number;
264
+ outFile: string;
265
+ }
266
+
267
+ export declare const enum IpcMsgType {
268
+ PROGRESS = 1,
269
+ DONE = 2,
270
+ ERROR = 3
271
+ }
272
+
273
+ export declare class IpcReader extends EventEmitter<{
274
+ progress: [value: number];
275
+ message: [type: IpcMsgType, buffer: Buffer];
276
+ done: [payload: IpcDonePayload];
277
+ error: [error: Error];
278
+ close: [];
279
+ }> {
280
+ private readonly _socket;
281
+ private _chunks;
282
+ private _buffered;
283
+ constructor(_socket: Socket);
284
+ private onData;
285
+ private flush;
286
+ private peek;
287
+ private consume;
288
+ }
289
+
290
+ export declare interface IpcServer {
291
+ waitForConnection(): Promise<IpcReader>;
292
+ close(): void;
293
+ }
294
+
295
+ export declare class IpcWriter {
296
+ private readonly _socket;
297
+ constructor(_socket: Socket);
298
+ writeProgress(value: number): void;
299
+ writeError(error: string): void;
300
+ writeDone(payload: IpcDonePayload): void;
301
+ private write;
302
+ }
303
+
241
304
  export declare function isEmpty(image: NativeImage): boolean;
242
305
 
243
306
  declare class Lazy<T> {
@@ -251,7 +314,7 @@ declare class Lazy<T> {
251
314
  export { Lazy }
252
315
  export { Lazy as Lazy_alias_1 }
253
316
 
254
- export declare function loadWindow(source: string, options: RenderOptions): Promise<BrowserWindow>;
317
+ export declare function loadWindow({ source, onCreated, renderer }: WindowOptions): Promise<BrowserWindow>;
255
318
 
256
319
  declare class Logger implements LoggerLike {
257
320
  private _level;
@@ -350,6 +413,14 @@ declare const pupDisableGPU: boolean;
350
413
  export { pupDisableGPU }
351
414
  export { pupDisableGPU as pupDisableGPU_alias_1 }
352
415
 
416
+ declare const pupExperimentalPuppeteer: boolean;
417
+ export { pupExperimentalPuppeteer }
418
+ export { pupExperimentalPuppeteer as pupExperimentalPuppeteer_alias_1 }
419
+
420
+ declare const pupIpcSocket: string | undefined;
421
+ export { pupIpcSocket }
422
+ export { pupIpcSocket as pupIpcSocket_alias_1 }
423
+
353
424
  declare const pupLogLevel: number;
354
425
  export { pupLogLevel }
355
426
  export { pupLogLevel as pupLogLevel_alias_1 }
@@ -378,7 +449,7 @@ declare const pupUseInnerProxy: boolean;
378
449
  export { pupUseInnerProxy }
379
450
  export { pupUseInnerProxy as pupUseInnerProxy_alias_1 }
380
451
 
381
- export declare function render(source: string, options: RenderOptions): Promise<void>;
452
+ export declare function render(writer: IpcWriter, source: string, options: RenderOptions): Promise<IpcDonePayload>;
382
453
 
383
454
  declare type RenderOptions = z.infer<typeof RenderSchema>;
384
455
  export { RenderOptions }
@@ -389,7 +460,6 @@ declare interface RenderResult {
389
460
  written: number;
390
461
  jank: number;
391
462
  outFile: string;
392
- audio?: AudioSpec;
393
463
  }
394
464
  export { RenderResult }
395
465
  export { RenderResult as RenderResult_alias_1 }
@@ -415,15 +485,15 @@ declare interface RetryOptions<Args extends any[], Ret> {
415
485
  export { RetryOptions }
416
486
  export { RetryOptions as RetryOptions_alias_1 }
417
487
 
418
- export declare function runElectronApp(size: Size, args: unknown[]): Promise<ProcessHandle>;
488
+ export declare function runElectronApp(size: Size, args: unknown[], ipcSocketPath: string): Promise<ProcessHandle>;
419
489
 
420
490
  export declare function setInterceptor({ source, window, useInnerProxy }: NetworkOptions): void;
421
491
 
422
- export declare function setupAudioCapture(outDir: string, getVideoTimeMs: () => number): Promise<AudioCapture>;
492
+ export declare function setupAudioCapture({ encoder, getVideoTimeMs, onError, }: AudioCaptureOptions): Promise<AudioCapture>;
423
493
 
424
494
  export declare function setupPupProtocol(): void;
425
495
 
426
- export declare function shoot(source: string, options: RenderOptions): Promise<void>;
496
+ export declare function shoot(writer: IpcWriter, source: string, options: RenderOptions): Promise<IpcDonePayload>;
427
497
 
428
498
  declare function sleep(ms: number): Promise<void>;
429
499
  export { sleep }
@@ -435,6 +505,15 @@ export declare function stopStego(cdp: Debugger): Promise<any>;
435
505
 
436
506
  export declare const TICK_SYMBOL = "__pup_tick__";
437
507
 
508
+ export declare interface TickInjectorOptions {
509
+ /**
510
+ * When true, skips the top-frame guard so the injector runs in the main document.
511
+ * Required for Puppeteer mode where the page is loaded directly (no stego iframe wrapper).
512
+ * Default: false (Electron/stego mode — only inject in iframes).
513
+ */
514
+ skipFrameGuard?: boolean;
515
+ }
516
+
438
517
  export declare function unsetInterceptor(window: BrowserWindow): void;
439
518
 
440
519
  declare function useRetry<Args extends any[], Ret>({ fn, maxAttempts, timeout }: RetryOptions<Args, Ret>): (...args: Args) => Promise<Ret>;
@@ -464,6 +543,7 @@ export declare interface VideoEncoderOptions {
464
543
  globalHeader: boolean;
465
544
  codecOpts: Record<string, string>;
466
545
  bitrate: number;
546
+ pixelFormat: AVPixelFormat;
467
547
  muxer: FormatMuxer;
468
548
  }
469
549
 
@@ -480,4 +560,11 @@ export declare interface WaitOptions {
480
560
  onTimeout?: () => void;
481
561
  }
482
562
 
563
+ export declare interface WindowOptions {
564
+ source: string;
565
+ onCreated?: (window: BrowserWindow) => Promise<void>;
566
+ renderer: RenderOptions;
567
+ warmup?: boolean;
568
+ }
569
+
483
570
  export { }