node-av 4.0.0 → 5.0.0

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.
Files changed (104) hide show
  1. package/README.md +23 -0
  2. package/binding.gyp +19 -11
  3. package/dist/api/bitstream-filter.d.ts +13 -12
  4. package/dist/api/bitstream-filter.js +33 -29
  5. package/dist/api/bitstream-filter.js.map +1 -1
  6. package/dist/api/decoder.d.ts +211 -96
  7. package/dist/api/decoder.js +396 -375
  8. package/dist/api/decoder.js.map +1 -1
  9. package/dist/api/demuxer.d.ts +10 -10
  10. package/dist/api/demuxer.js +7 -10
  11. package/dist/api/demuxer.js.map +1 -1
  12. package/dist/api/encoder.d.ts +155 -122
  13. package/dist/api/encoder.js +368 -541
  14. package/dist/api/encoder.js.map +1 -1
  15. package/dist/api/filter-complex.d.ts +769 -0
  16. package/dist/api/filter-complex.js +1596 -0
  17. package/dist/api/filter-complex.js.map +1 -0
  18. package/dist/api/filter-presets.d.ts +68 -0
  19. package/dist/api/filter-presets.js +96 -0
  20. package/dist/api/filter-presets.js.map +1 -1
  21. package/dist/api/filter.d.ts +183 -113
  22. package/dist/api/filter.js +347 -365
  23. package/dist/api/filter.js.map +1 -1
  24. package/dist/api/fmp4-stream.d.ts +2 -2
  25. package/dist/api/fmp4-stream.js.map +1 -1
  26. package/dist/api/index.d.ts +2 -0
  27. package/dist/api/index.js +3 -0
  28. package/dist/api/index.js.map +1 -1
  29. package/dist/api/io-stream.d.ts +3 -3
  30. package/dist/api/io-stream.js.map +1 -1
  31. package/dist/api/muxer.d.ts +10 -10
  32. package/dist/api/muxer.js +6 -6
  33. package/dist/api/muxer.js.map +1 -1
  34. package/dist/api/pipeline.d.ts +2 -2
  35. package/dist/api/pipeline.js +22 -22
  36. package/dist/api/pipeline.js.map +1 -1
  37. package/dist/api/rtp-stream.d.ts +2 -2
  38. package/dist/api/rtp-stream.js.map +1 -1
  39. package/dist/api/types.d.ts +63 -7
  40. package/dist/api/utilities/audio-sample.d.ts +10 -0
  41. package/dist/api/utilities/audio-sample.js +10 -0
  42. package/dist/api/utilities/audio-sample.js.map +1 -1
  43. package/dist/api/utilities/channel-layout.d.ts +1 -0
  44. package/dist/api/utilities/channel-layout.js +1 -0
  45. package/dist/api/utilities/channel-layout.js.map +1 -1
  46. package/dist/api/utilities/image.d.ts +38 -0
  47. package/dist/api/utilities/image.js +38 -0
  48. package/dist/api/utilities/image.js.map +1 -1
  49. package/dist/api/utilities/index.d.ts +1 -0
  50. package/dist/api/utilities/index.js +2 -0
  51. package/dist/api/utilities/index.js.map +1 -1
  52. package/dist/api/utilities/media-type.d.ts +1 -0
  53. package/dist/api/utilities/media-type.js +1 -0
  54. package/dist/api/utilities/media-type.js.map +1 -1
  55. package/dist/api/utilities/pixel-format.d.ts +3 -0
  56. package/dist/api/utilities/pixel-format.js +3 -0
  57. package/dist/api/utilities/pixel-format.js.map +1 -1
  58. package/dist/api/utilities/sample-format.d.ts +5 -0
  59. package/dist/api/utilities/sample-format.js +5 -0
  60. package/dist/api/utilities/sample-format.js.map +1 -1
  61. package/dist/api/utilities/scheduler.d.ts +21 -52
  62. package/dist/api/utilities/scheduler.js +20 -58
  63. package/dist/api/utilities/scheduler.js.map +1 -1
  64. package/dist/api/utilities/streaming.d.ts +32 -1
  65. package/dist/api/utilities/streaming.js +32 -1
  66. package/dist/api/utilities/streaming.js.map +1 -1
  67. package/dist/api/utilities/timestamp.d.ts +14 -0
  68. package/dist/api/utilities/timestamp.js +14 -0
  69. package/dist/api/utilities/timestamp.js.map +1 -1
  70. package/dist/api/utilities/whisper-model.d.ts +310 -0
  71. package/dist/api/utilities/whisper-model.js +528 -0
  72. package/dist/api/utilities/whisper-model.js.map +1 -0
  73. package/dist/api/whisper.d.ts +324 -0
  74. package/dist/api/whisper.js +362 -0
  75. package/dist/api/whisper.js.map +1 -0
  76. package/dist/constants/constants.d.ts +3 -1
  77. package/dist/constants/constants.js +1 -0
  78. package/dist/constants/constants.js.map +1 -1
  79. package/dist/ffmpeg/index.d.ts +3 -3
  80. package/dist/ffmpeg/index.js +3 -3
  81. package/dist/ffmpeg/utils.d.ts +27 -0
  82. package/dist/ffmpeg/utils.js +28 -16
  83. package/dist/ffmpeg/utils.js.map +1 -1
  84. package/dist/lib/binding.d.ts +4 -4
  85. package/dist/lib/binding.js.map +1 -1
  86. package/dist/lib/codec-parameters.d.ts +47 -1
  87. package/dist/lib/codec-parameters.js +55 -0
  88. package/dist/lib/codec-parameters.js.map +1 -1
  89. package/dist/lib/fifo.d.ts +416 -0
  90. package/dist/lib/fifo.js +453 -0
  91. package/dist/lib/fifo.js.map +1 -0
  92. package/dist/lib/frame.d.ts +96 -1
  93. package/dist/lib/frame.js +139 -1
  94. package/dist/lib/frame.js.map +1 -1
  95. package/dist/lib/index.d.ts +1 -0
  96. package/dist/lib/index.js +2 -0
  97. package/dist/lib/index.js.map +1 -1
  98. package/dist/lib/native-types.d.ts +29 -2
  99. package/dist/lib/rational.d.ts +18 -0
  100. package/dist/lib/rational.js +19 -0
  101. package/dist/lib/rational.js.map +1 -1
  102. package/dist/lib/types.d.ts +23 -1
  103. package/install/check.js +2 -2
  104. package/package.json +30 -20
@@ -0,0 +1,769 @@
1
+ import { Frame } from '../lib/frame.js';
2
+ import type { EOFSignal } from '../constants/index.js';
3
+ import type { IRational } from '../lib/types.js';
4
+ import type { FilterComplexOptions } from './types.js';
5
+ /**
6
+ * High-level filter_complex API for multi-input/output filtering.
7
+ *
8
+ * Provides simplified interface for complex FFmpeg filter graphs with multiple inputs and outputs.
9
+ * Supports both high-level generator API and low-level manual control.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // High-level API: Simple overlay with frames() generator
14
+ * using complex = FilterComplexAPI.create('[0:v][1:v]overlay=x=100:y=50[out]', {
15
+ * inputs: [{ label: '0:v' }, { label: '1:v' }],
16
+ * outputs: [{ label: 'out' }]
17
+ * });
18
+ *
19
+ * // Process multiple input streams automatically
20
+ * for await (using frame of complex.frames('out', {
21
+ * '0:v': decoder1.frames(packets1),
22
+ * '1:v': decoder2.frames(packets2)
23
+ * })) {
24
+ * await encoder.encode(frame);
25
+ * }
26
+ * ```
27
+ *
28
+ * @see {@link FilterAPI} For simple single-input/output filtering
29
+ * @see {@link FilterGraph} For low-level filter graph API
30
+ * @see {@link frames} For high-level stream processing
31
+ * @see {@link process} For low-level manual frame sending
32
+ * @see {@link receive} For low-level manual frame receiving
33
+ */
34
+ export declare class FilterComplexAPI implements Disposable {
35
+ private graph;
36
+ private description;
37
+ private options;
38
+ private inputs;
39
+ private outputs;
40
+ private initialized;
41
+ private isClosed;
42
+ private initializePromise;
43
+ private frame;
44
+ /**
45
+ * @param graph - Filter graph instance
46
+ *
47
+ * @param description - Filter description string
48
+ *
49
+ * @param options - Filter complex options
50
+ *
51
+ * @internal
52
+ */
53
+ private constructor();
54
+ /**
55
+ * Create a complex filter with specified configuration.
56
+ *
57
+ * Direct mapping to avfilter_graph_segment_parse() and avfilter_graph_config().
58
+ *
59
+ * @param description - Filter description string (e.g., '[0:v][1:v]overlay[out]')
60
+ *
61
+ * @param options - Filter complex configuration including inputs and outputs
62
+ *
63
+ * @returns Filter complex instance ready to process frames
64
+ *
65
+ * @throws {Error} If configuration is invalid (duplicate labels, no inputs/outputs)
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * // Simple overlay example
70
+ * using complex = FilterComplexAPI.create(
71
+ * '[0:v][1:v]overlay=x=100:y=50[out]',
72
+ * {
73
+ * inputs: [
74
+ * { label: '0:v' }, // Base video
75
+ * { label: '1:v' } // Overlay video
76
+ * ],
77
+ * outputs: [{ label: 'out' }]
78
+ * }
79
+ * );
80
+ *
81
+ * // Send frames manually
82
+ * await complex.process('0:v', baseFrame);
83
+ * await complex.process('1:v', overlayFrame);
84
+ * using outFrame = await complex.receive('out');
85
+ * ```
86
+ *
87
+ * @see {@link process} For sending frames to inputs
88
+ * @see {@link receive} For getting frames from outputs
89
+ */
90
+ static create(description: string, options: FilterComplexOptions): FilterComplexAPI;
91
+ /**
92
+ * Check if filter complex is open.
93
+ *
94
+ * @returns true if not closed
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * if (complex.isOpen) {
99
+ * // Can still consume frames
100
+ * }
101
+ * ```
102
+ */
103
+ get isOpen(): boolean;
104
+ /**
105
+ * Check if filter complex has been initialized.
106
+ *
107
+ * Returns true after first frame set has been processed from all inputs.
108
+ *
109
+ * @returns true if filter graph has been configured
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * if (!complex.isInitialized) {
114
+ * console.log('Filter will initialize on first frame set');
115
+ * }
116
+ * ```
117
+ */
118
+ get isInitialized(): boolean;
119
+ /**
120
+ * Get output frame rate.
121
+ *
122
+ * Returns frame rate from the first output's buffersink.
123
+ * Returns null if not initialized or frame rate is not set.
124
+ *
125
+ * @returns Frame rate as rational number or null
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const frameRate = complex.frameRate;
130
+ * if (frameRate) {
131
+ * console.log(`Output: ${frameRate.num}/${frameRate.den} fps`);
132
+ * }
133
+ * ```
134
+ *
135
+ * @see {@link FilterAPI.frameRate} For single-output filter frame rate
136
+ */
137
+ get frameRate(): IRational | null;
138
+ /**
139
+ * Get output time base.
140
+ *
141
+ * Returns time base from the first output's buffersink.
142
+ * Returns null if not initialized.
143
+ *
144
+ * @returns Time base as rational number or null
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const timeBase = complex.timeBase;
149
+ * if (timeBase) {
150
+ * console.log(`Output timeBase: ${timeBase.num}/${timeBase.den}`);
151
+ * }
152
+ * ```
153
+ *
154
+ * @see {@link FilterAPI.timeBase} For single-output filter time base
155
+ */
156
+ get timeBase(): IRational | null;
157
+ /**
158
+ * Process frame by sending to specified input.
159
+ *
160
+ * Sends a frame to the buffersrc of the specified input label.
161
+ * Automatically rescales timestamps to the input's calculated timeBase (CFR/VFR).
162
+ * Pass null to signal end-of-stream for that input.
163
+ *
164
+ * Direct mapping to av_buffersrc_add_frame().
165
+ *
166
+ * @param inLabel - Input label to send frame to
167
+ *
168
+ * @param frame - Frame to process
169
+ *
170
+ * @throws {Error} If input label not found or filter closed
171
+ *
172
+ * @throws {FFmpegError} If processing fails
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * // Process frames one at a time
177
+ * await complex.process('0:v', frame1);
178
+ * await complex.process('1:v', frame2);
179
+ * const outFrame = await complex.receive('out');
180
+ * ```
181
+ *
182
+ * @see {@link receive} For receiving output frames
183
+ * @see {@link flush} For flushing inputs
184
+ * @see {@link processSync} For synchronous version
185
+ */
186
+ process(inLabel: string, frame: Frame): Promise<void>;
187
+ /**
188
+ * Process frame by sending to specified input synchronously.
189
+ * Synchronous version of process.
190
+ *
191
+ * Sends a frame to the buffersrc of the specified input label.
192
+ * Automatically rescales timestamps to the input's calculated timeBase (CFR/VFR).
193
+ * Pass null to signal end-of-stream for that input.
194
+ *
195
+ * Direct mapping to av_buffersrc_add_frame().
196
+ *
197
+ * @param inLabel - Input label to send frame to
198
+ *
199
+ * @param frame - Frame to process
200
+ *
201
+ * @throws {Error} If input label not found or filter closed
202
+ *
203
+ * @throws {FFmpegError} If processing fails
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * // Process frames one at a time
208
+ * complex.processSync('0:v', frame1);
209
+ * complex.processSync('1:v', frame2);
210
+ * const outFrame = complex.receiveSync('out');
211
+ * ```
212
+ *
213
+ * @see {@link receiveSync} For receiving output frames
214
+ * @see {@link flushSync} For flushing inputs
215
+ * @see {@link process} For async version
216
+ */
217
+ processSync(inLabel: string, frame: Frame): void;
218
+ /**
219
+ * Process frame streams from multiple inputs and yield frames from specified output.
220
+ *
221
+ * High-level async generator for multi-input filtering.
222
+ * Filter is only flushed when EOF (null) is explicitly sent to any input.
223
+ *
224
+ * **EOF Handling:**
225
+ * - Filter is only flushed when EOF (null) is explicitly sent to ANY input
226
+ * - Generator yields null after flushing when null is received
227
+ * - No automatic flushing - filter stays open until EOF or close()
228
+ * - Iterator completion without null does not trigger flush
229
+ *
230
+ * @param outLabel - Output label to receive frames from
231
+ *
232
+ * @param inputs - Record mapping input labels to frame sources (AsyncIterable, single Frame, or null)
233
+ *
234
+ * @yields {Frame | null} Filtered frames from output, followed by null when flushed
235
+ *
236
+ * @throws {Error} If input label not found
237
+ *
238
+ * @throws {FFmpegError} If processing fails
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * // Stream processing: 2 inputs, 1 output
243
+ * using complex = FilterComplexAPI.create('[0:v][1:v]overlay[out]', {
244
+ * inputs: [{ label: '0:v' }, { label: '1:v' }],
245
+ * outputs: [{ label: 'out' }]
246
+ * });
247
+ *
248
+ * for await (using frame of complex.frames('out', {
249
+ * '0:v': decoder1.frames(packets1),
250
+ * '1:v': decoder2.frames(packets2)
251
+ * })) {
252
+ * await encoder.encode(frame);
253
+ * }
254
+ * ```
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * // Single frames - no automatic flush
259
+ * for await (using frame of complex.frames('out', {
260
+ * '0:v': frame1,
261
+ * '1:v': frame2
262
+ * })) {
263
+ * await encoder.encode(frame);
264
+ * }
265
+ * // Filter remains open, buffered frames not flushed
266
+ * ```
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * // Explicit flush with null
271
+ * for await (using frame of complex.frames('out', {
272
+ * '0:v': null,
273
+ * '1:v': null
274
+ * })) {
275
+ * await encoder.encode(frame);
276
+ * }
277
+ * ```
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * // Mixed: stream + single frame
282
+ * for await (using frame of complex.frames('out', {
283
+ * '0:v': decoder.frames(packets), // Stream
284
+ * '1:v': watermarkFrame // Single frame (used for all)
285
+ * })) {
286
+ * await encoder.encode(frame);
287
+ * }
288
+ * ```
289
+ *
290
+ * @see {@link process} For manual frame sending
291
+ * @see {@link receive} For manual frame receiving
292
+ * @see {@link framesSync} For sync version
293
+ */
294
+ frames(outLabel: string, inputs: Record<string, AsyncIterable<Frame | null> | Frame | null>): AsyncGenerator<Frame | null>;
295
+ /**
296
+ * Process frame streams from multiple inputs and yield frames from specified output synchronously.
297
+ * Synchronous version of frames.
298
+ *
299
+ * High-level sync generator for multi-input filtering.
300
+ * Filter is only flushed when EOF (null) is explicitly sent to any input.
301
+ *
302
+ * **EOF Handling:**
303
+ * - Filter is only flushed when EOF (null) is explicitly sent to ANY input
304
+ * - Generator yields null after flushing when null is received
305
+ * - No automatic flushing - filter stays open until EOF or close()
306
+ * - Iterator completion without null does not trigger flush
307
+ *
308
+ * @param outLabel - Output label to receive frames from
309
+ *
310
+ * @param inputs - Record mapping input labels to frame sources (Iterable, single Frame, or null)
311
+ *
312
+ * @yields {Frame | null} Filtered frames from output, followed by null when flushed
313
+ *
314
+ * @throws {Error} If input label not found or filter not initialized
315
+ *
316
+ * @throws {FFmpegError} If processing fails
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * // Stream processing: 2 inputs, 1 output
321
+ * using complex = FilterComplexAPI.create('[0:v][1:v]overlay[out]', {
322
+ * inputs: [{ label: '0:v' }, { label: '1:v' }],
323
+ * outputs: [{ label: 'out' }]
324
+ * });
325
+ *
326
+ * // Note: Sync version requires async initialization first
327
+ * await complex.process('0:v', firstFrame1);
328
+ * await complex.process('1:v', firstFrame2);
329
+ *
330
+ * for (using frame of complex.framesSync('out', {
331
+ * '0:v': decoder1.framesSync(packets1),
332
+ * '1:v': decoder2.framesSync(packets2)
333
+ * })) {
334
+ * encoder.encodeSync(frame);
335
+ * }
336
+ * ```
337
+ *
338
+ * @example
339
+ * ```typescript
340
+ * // Single frames
341
+ * for (using frame of complex.framesSync('out', {
342
+ * '0:v': frame1,
343
+ * '1:v': frame2
344
+ * })) {
345
+ * encoder.encodeSync(frame);
346
+ * }
347
+ * ```
348
+ *
349
+ * @example
350
+ * ```typescript
351
+ * // Explicit flush
352
+ * for (using frame of complex.framesSync('out', {
353
+ * '0:v': null,
354
+ * '1:v': null
355
+ * })) {
356
+ * encoder.encodeSync(frame);
357
+ * }
358
+ * ```
359
+ *
360
+ * @see {@link processSync} For manual frame sending
361
+ * @see {@link receiveSync} For manual frame receiving
362
+ * @see {@link frames} For async version with lazy initialization
363
+ */
364
+ framesSync(outLabel: string, inputs: Record<string, Iterable<Frame | null> | Frame | null>): Generator<Frame | null>;
365
+ /**
366
+ * Flush input(s) and signal end-of-stream.
367
+ *
368
+ * Sends null frame to buffersrc filter(s) to flush buffered data.
369
+ * Must call receive() on outputs to get flushed frames.
370
+ * Does nothing if filter is closed or was never initialized.
371
+ *
372
+ * Direct mapping to av_buffersrc_add_frame(NULL).
373
+ *
374
+ * @param inLabel - Input label to flush. If not specified, flushes all inputs.
375
+ *
376
+ * @throws {Error} If input label not found
377
+ *
378
+ * @throws {FFmpegError} If flush fails
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * // Flush specific input
383
+ * await complex.flush('0:v');
384
+ *
385
+ * // Flush all inputs
386
+ * await complex.flush();
387
+ *
388
+ * // Get remaining frames from output
389
+ * let frame;
390
+ * while ((frame = await complex.receive('out')) !== null) {
391
+ * frame.free();
392
+ * }
393
+ * ```
394
+ *
395
+ * @see {@link flushFrames} For async iteration
396
+ * @see {@link receive} For getting flushed frames
397
+ * @see {@link flushSync} For synchronous version
398
+ */
399
+ flush(inLabel?: string): Promise<void>;
400
+ /**
401
+ * Flush input(s) and signal end-of-stream synchronously.
402
+ * Synchronous version of flush.
403
+ *
404
+ * Sends null frame to buffersrc filter(s) to flush buffered data.
405
+ * Must call receiveSync() on outputs to get flushed frames.
406
+ * Does nothing if filter is closed or was never initialized.
407
+ *
408
+ * Direct mapping to av_buffersrc_add_frame(NULL).
409
+ *
410
+ * @param inLabel - Input label to flush. If not specified, flushes all inputs.
411
+ *
412
+ * @throws {Error} If input label not found
413
+ *
414
+ * @throws {FFmpegError} If flush fails
415
+ *
416
+ * @example
417
+ * ```typescript
418
+ * // Flush specific input
419
+ * complex.flushSync('0:v');
420
+ *
421
+ * // Flush all inputs
422
+ * complex.flushSync();
423
+ *
424
+ * // Get remaining frames from output
425
+ * let frame;
426
+ * while ((frame = complex.receiveSync('out')) !== null) {
427
+ * frame.free();
428
+ * }
429
+ * ```
430
+ *
431
+ * @see {@link flushFramesSync} For sync iteration
432
+ * @see {@link receiveSync} For getting flushed frames
433
+ * @see {@link flush} For async version
434
+ */
435
+ flushSync(inLabel?: string): void;
436
+ /**
437
+ * Flush all inputs and yield remaining frames from specified output.
438
+ *
439
+ * Convenience method that:
440
+ * 1. Calls flush() to send EOF to all inputs
441
+ * 2. Yields all remaining frames from the specified output
442
+ * 3. Continues until EOF is reached
443
+ *
444
+ * Automatically frees yielded frames after use (using declaration).
445
+ *
446
+ * @param outLabel - Output label to receive flushed frames from
447
+ *
448
+ * @yields {Frame} Remaining frames from filter after flush
449
+ *
450
+ * @throws {Error} If output label not found or filter not initialized
451
+ *
452
+ * @throws {FFmpegError} If flushing or receiving fails
453
+ *
454
+ * @example
455
+ * ```typescript
456
+ * // Process all frames, then flush
457
+ * for await (using frame of inputFrames) {
458
+ * await complex.process('0:v', frame);
459
+ * }
460
+ *
461
+ * // Get all remaining frames
462
+ * for await (using frame of complex.flushFrames('out')) {
463
+ * await encoder.encode(frame);
464
+ * }
465
+ * ```
466
+ *
467
+ * @see {@link flush} For flushing without iteration
468
+ * @see {@link receive} For manual frame retrieval
469
+ * @see {@link flushFramesSync} For synchronous version
470
+ */
471
+ flushFrames(outLabel: string): AsyncGenerator<Frame>;
472
+ /**
473
+ * Flush all inputs and yield remaining frames from specified output synchronously.
474
+ * Synchronous version of flushFrames.
475
+ *
476
+ * Convenience method that:
477
+ * 1. Calls flushSync() to send EOF to all inputs
478
+ * 2. Yields all remaining frames from the specified output
479
+ * 3. Continues until EOF is reached
480
+ *
481
+ * Automatically frees yielded frames after use (using declaration).
482
+ *
483
+ * @param outLabel - Output label to receive flushed frames from
484
+ *
485
+ * @yields {Frame} Remaining frames from filter after flush
486
+ *
487
+ * @throws {Error} If output label not found or filter not initialized
488
+ *
489
+ * @throws {FFmpegError} If flushing or receiving fails
490
+ *
491
+ * @example
492
+ * ```typescript
493
+ * // Process all frames, then flush
494
+ * for (using frame of inputFrames) {
495
+ * complex.processSync('0:v', frame);
496
+ * }
497
+ *
498
+ * // Get all remaining frames
499
+ * for (using frame of complex.flushFramesSync('out')) {
500
+ * encoder.encodeSync(frame);
501
+ * }
502
+ * ```
503
+ *
504
+ * @see {@link flushSync} For flushing without iteration
505
+ * @see {@link receiveSync} For manual frame retrieval
506
+ * @see {@link flushFrames} For async version
507
+ */
508
+ flushFramesSync(outLabel: string): Generator<Frame>;
509
+ /**
510
+ * Receive filtered frame from specified output.
511
+ *
512
+ * Pulls a single frame from the buffersink of the specified output.
513
+ * Automatically post-processes frame (sets timeBase, calculates duration).
514
+ * Returns cloned frame - caller must free it.
515
+ *
516
+ * Return values:
517
+ * - Frame: Successfully received frame (caller must free)
518
+ * - null: Need more input (AVERROR_EAGAIN) - call process() to send more frames
519
+ * - EOF: End of stream reached
520
+ *
521
+ * Direct mapping to av_buffersink_get_frame().
522
+ *
523
+ * @param outLabel - Output label to receive from
524
+ *
525
+ * @returns Frame on success, null if need more input, EOF if finished
526
+ *
527
+ * @throws {Error} If output label not found or filter not initialized
528
+ *
529
+ * @throws {FFmpegError} If receive fails with unexpected error
530
+ *
531
+ * @example
532
+ * ```typescript
533
+ * // Process frames one at a time
534
+ * await complex.process('0:v', frame1);
535
+ * const outFrame = await complex.receive('out');
536
+ * if (outFrame && outFrame !== EOF) {
537
+ * // Use frame
538
+ * outFrame.free();
539
+ * }
540
+ * ```
541
+ *
542
+ * @see {@link process} For sending input frames
543
+ * @see {@link flush} For flushing after all input
544
+ * @see {@link receiveSync} For synchronous version
545
+ */
546
+ receive(outLabel: string): Promise<Frame | EOFSignal | null>;
547
+ /**
548
+ * Receive filtered frame from specified output synchronously.
549
+ * Synchronous version of receive.
550
+ *
551
+ * Pulls a single frame from the buffersink of the specified output.
552
+ * Automatically post-processes frame (sets timeBase, calculates duration).
553
+ * Returns cloned frame - caller must free it.
554
+ *
555
+ * Return values:
556
+ * - Frame: Successfully received frame (caller must free)
557
+ * - null: Need more input (AVERROR_EAGAIN) - call processSync() to send more frames
558
+ * - EOF: End of stream reached
559
+ *
560
+ * Direct mapping to av_buffersink_get_frame().
561
+ *
562
+ * @param outLabel - Output label to receive from
563
+ *
564
+ * @returns Frame on success, null if need more input, EOF if finished
565
+ *
566
+ * @throws {Error} If output label not found or filter not initialized
567
+ *
568
+ * @throws {FFmpegError} If receive fails with unexpected error
569
+ *
570
+ * @example
571
+ * ```typescript
572
+ * // Process frames one at a time
573
+ * complex.processSync('0:v', frame1);
574
+ * const outFrame = complex.receiveSync('out');
575
+ * if (outFrame && outFrame !== EOF) {
576
+ * // Use frame
577
+ * outFrame.free();
578
+ * }
579
+ * ```
580
+ *
581
+ * @see {@link processSync} For sending input frames
582
+ * @see {@link flushSync} For flushing after all input
583
+ * @see {@link receive} For async version
584
+ */
585
+ receiveSync(outLabel: string): Frame | EOFSignal | null;
586
+ /**
587
+ * Check if all inputs have received at least one frame (have format information).
588
+ *
589
+ * @returns true if all inputs have format info (first frame received)
590
+ *
591
+ * @internal
592
+ */
593
+ private hasAllInputFormats;
594
+ /**
595
+ * Initialize filter graph from queued frames.
596
+ *
597
+ * Implements FFmpeg's configure_filtergraph() logic:
598
+ * 1. Create buffersrc filters from first queued frame of each input
599
+ * 2. Parse filter description
600
+ * 3. Create buffersink filters
601
+ * 4. Configure graph with avfilter_graph_config()
602
+ * 5. Send all queued frames to buffersrc
603
+ *
604
+ * @throws {Error} If initialization fails
605
+ *
606
+ * @throws {FFmpegError} If configuration fails
607
+ *
608
+ * @internal
609
+ */
610
+ private initializeFromQueuedFrames;
611
+ /**
612
+ * Initialize filter graph from queued frames synchronously.
613
+ * Synchronous version of initializeFromQueuedFrames.
614
+ *
615
+ * @throws {Error} If closed or inputs have no queued frames
616
+ *
617
+ * @throws {FFmpegError} If graph configuration or frame processing fails
618
+ *
619
+ * @internal
620
+ */
621
+ private initializeFromQueuedFramesSync;
622
+ /**
623
+ * Calculate timeBase from frame based on media type and CFR option.
624
+ *
625
+ * Implements FFmpeg's ifilter_parameters_from_frame logic:
626
+ * - Audio: Always { 1, sample_rate }
627
+ * - Video CFR: 1/framerate (inverse of framerate)
628
+ * - Video VFR: Use frame.timeBase
629
+ *
630
+ * @param frame - Input frame
631
+ *
632
+ * @returns Calculated timeBase
633
+ *
634
+ * @internal
635
+ */
636
+ private calculateTimeBase;
637
+ /**
638
+ * Rescale frame timestamps to calculated timeBase.
639
+ *
640
+ * Helper to avoid code duplication when rescaling timestamps.
641
+ * Modifies the frame in-place.
642
+ *
643
+ * @param frame - Frame to rescale
644
+ *
645
+ * @param calculatedTimeBase - Target timeBase
646
+ *
647
+ * @internal
648
+ */
649
+ private rescaleFrameTimestamps;
650
+ /**
651
+ * Create buffer source for an input.
652
+ *
653
+ * @param label - Input label
654
+ *
655
+ * @param frame - First frame from this input
656
+ *
657
+ * @param timeBase - Calculated timeBase for this input (from calculateTimeBase)
658
+ *
659
+ * @returns BufferSrc filter context
660
+ *
661
+ * @throws {Error} If creation fails
662
+ *
663
+ * @internal
664
+ */
665
+ private createBufferSource;
666
+ /**
667
+ * Create buffer sink for an output.
668
+ *
669
+ * @param label - Output label
670
+ *
671
+ * @param isVideo - Whether this is a video output
672
+ *
673
+ * @returns BufferSink filter context
674
+ *
675
+ * @throws {Error} If creation fails
676
+ *
677
+ * @internal
678
+ */
679
+ private createBufferSink;
680
+ /**
681
+ * Parse filter description and build graph using segment API.
682
+ *
683
+ * @throws {Error} If parsing fails
684
+ *
685
+ * @throws {FFmpegError} If graph construction fails
686
+ *
687
+ * @internal
688
+ */
689
+ private parseFilterDescription;
690
+ /**
691
+ * Link buffersrc filters to segment inputs.
692
+ *
693
+ * Iterates through FilterInOut chain and links by label.
694
+ *
695
+ * @param inputs - FilterInOut chain of segment inputs
696
+ *
697
+ * @throws {Error} If linking fails
698
+ *
699
+ * @internal
700
+ */
701
+ private linkBufferSources;
702
+ /**
703
+ * Link segment outputs to buffersink filters.
704
+ *
705
+ * Iterates through FilterInOut chain and links by label.
706
+ *
707
+ * @param outputs - FilterInOut chain of segment outputs
708
+ *
709
+ * @throws {Error} If linking fails
710
+ *
711
+ * @internal
712
+ */
713
+ private linkBufferSinks;
714
+ /**
715
+ * Post-process output frame from buffersink.
716
+ *
717
+ * Applies FFmpeg's fg_output_step() behavior:
718
+ * 1. Sets frame.timeBase from buffersink (filters can change timeBase)
719
+ * 2. Calculates video frame duration from frame rate if not set
720
+ *
721
+ * This must be called AFTER buffersinkGetFrame() for every output frame.
722
+ *
723
+ * @param frame - Output frame from buffersink
724
+ *
725
+ * @param buffersink - The buffersink context
726
+ *
727
+ * @internal
728
+ */
729
+ private postProcessOutputFrame;
730
+ /**
731
+ * Close filter complex and release resources.
732
+ *
733
+ * Frees queued frames, filter graph and all filter contexts.
734
+ * Safe to call multiple times.
735
+ *
736
+ * @example
737
+ * ```typescript
738
+ * complex.close();
739
+ * ```
740
+ *
741
+ * @example
742
+ * ```typescript
743
+ * // Automatic cleanup with using
744
+ * {
745
+ * using complex = FilterComplexAPI.create('[0:v]scale=640:480[out]', { ... });
746
+ * // Use complex...
747
+ * } // Automatically freed
748
+ * ```
749
+ *
750
+ * @see {@link Symbol.dispose} For automatic cleanup
751
+ */
752
+ close(): void;
753
+ /**
754
+ * Dispose of filter complex.
755
+ *
756
+ * Implements Disposable interface for automatic cleanup.
757
+ *
758
+ * @example
759
+ * ```typescript
760
+ * {
761
+ * using complex = FilterComplexAPI.create('[0:v]scale=640:480[out]', { ... });
762
+ * // Use complex...
763
+ * } // Automatically freed
764
+ * ```
765
+ *
766
+ * @see {@link close} For manual cleanup
767
+ */
768
+ [Symbol.dispose](): void;
769
+ }