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
@@ -1,6 +1,6 @@
1
1
  import { Frame } from '../lib/frame.js';
2
2
  import { Scheduler } from './utilities/scheduler.js';
3
- import type { AVColorRange, AVColorSpace, AVFilterCmdFlag, AVPixelFormat, AVSampleFormat } from '../constants/index.js';
3
+ import type { AVColorRange, AVColorSpace, AVFilterCmdFlag, AVPixelFormat, AVSampleFormat, EOFSignal } from '../constants/index.js';
4
4
  import type { FilterContext } from '../lib/filter-context.js';
5
5
  import type { ChannelLayout, IDimension, IRational } from '../lib/types.js';
6
6
  import type { Encoder } from './encoder.js';
@@ -72,11 +72,6 @@ export declare class FilterAPI implements Disposable {
72
72
  /**
73
73
  * Create a filter with specified description and configuration.
74
74
  *
75
- * Creates and allocates filter graph immediately.
76
- * Filter configuration is completed on first frame with frame properties.
77
- * TimeBase is automatically calculated from first frame based on CFR option.
78
- * Hardware frames context is automatically detected from input frames.
79
- *
80
75
  * Direct mapping to avfilter_graph_parse_ptr() and avfilter_graph_config().
81
76
  *
82
77
  * @param description - Filter graph description
@@ -163,7 +158,6 @@ export declare class FilterAPI implements Disposable {
163
158
  * Output frame rate from filter graph.
164
159
  *
165
160
  * Returns the frame rate determined by the filter graph output.
166
- * Matches FFmpeg CLI's av_buffersink_get_frame_rate() behavior.
167
161
  * Returns null if filter is not initialized or frame rate is not set.
168
162
  *
169
163
  * Direct mapping to av_buffersink_get_frame_rate().
@@ -372,32 +366,33 @@ export declare class FilterAPI implements Disposable {
372
366
  */
373
367
  getGraphDescription(): string | null;
374
368
  /**
375
- * Process a frame through the filter.
369
+ * Send a frame to the filter.
376
370
  *
377
- * Applies filter operations to input frame.
371
+ * Sends a frame to the filter for processing.
372
+ * Does not return filtered frames - use {@link receive} to retrieve frames.
378
373
  * On first frame, automatically builds filter graph with frame properties.
379
- * May buffer frames internally before producing output.
380
- * Hardware frames context is automatically detected from frame.
381
- * Returns null if filter is closed and frame is null.
382
- *
383
- * **Note**: This method receives only ONE frame per call.
384
- * A single input frame can produce multiple output frames (e.g., fps filter, deinterlace).
385
- * To receive all frames from an input, use {@link processAll} or {@link frames} instead.
374
+ * A single input frame can produce zero, one, or multiple output frames.
386
375
  *
387
- * Direct mapping to av_buffersrc_add_frame() and av_buffersink_get_frame().
376
+ * **Important**: This method only SENDS the frame to the filter.
377
+ * You must call {@link receive} separately (potentially multiple times) to get filtered frames.
388
378
  *
389
- * @param frame - Input frame to process (or null to flush)
379
+ * Direct mapping to av_buffersrc_add_frame().
390
380
  *
391
- * @returns Filtered frame or null if buffered
381
+ * @param frame - Input frame to send to filter
392
382
  *
393
383
  * @throws {Error} If filter could not be initialized
394
384
  *
395
- * @throws {FFmpegError} If processing fails
385
+ * @throws {FFmpegError} If sending frame fails
396
386
  *
397
387
  * @example
398
388
  * ```typescript
399
- * const output = await filter.process(inputFrame);
400
- * if (output) {
389
+ * // Send frame and receive filtered frames
390
+ * await filter.process(inputFrame);
391
+ *
392
+ * // Receive all available filtered frames
393
+ * while (true) {
394
+ * const output = await filter.receive();
395
+ * if (!output) break;
401
396
  * console.log(`Got filtered frame: pts=${output.pts}`);
402
397
  * output.free();
403
398
  * }
@@ -405,71 +400,67 @@ export declare class FilterAPI implements Disposable {
405
400
  *
406
401
  * @example
407
402
  * ```typescript
408
- * // Process frame - may buffer internally
409
- * const output = await filter.process(frame);
410
- * if (output) {
411
- * // Got output immediately
412
- * yield output;
403
+ * for await (const frame of decoder.frames(input.packets())) {
404
+ * // Send frame
405
+ * await filter.process(frame);
406
+ *
407
+ * // Receive available filtered frames
408
+ * let output;
409
+ * while ((output = await filter.receive())) {
410
+ * await encoder.encode(output);
411
+ * output.free();
412
+ * }
413
+ * frame.free();
413
414
  * }
414
- * // For buffered frames, use the frames() async generator
415
415
  * ```
416
416
  *
417
- * @see {@link processAll} For processing multiple output frames
417
+ * @see {@link receive} For receiving filtered frames
418
+ * @see {@link processAll} For combined send+receive operation
418
419
  * @see {@link frames} For processing frame streams
419
420
  * @see {@link flush} For end-of-stream handling
420
421
  * @see {@link processSync} For synchronous version
421
422
  */
422
- process(frame: Frame | null): Promise<Frame | null>;
423
+ process(frame: Frame): Promise<void>;
423
424
  /**
424
- * Process a frame through the filter synchronously.
425
+ * Send a frame to the filter synchronously.
425
426
  * Synchronous version of process.
426
427
  *
427
- * Applies filter operations to input frame.
428
+ * Sends a frame to the filter for processing.
429
+ * Does not return filtered frames - use {@link receiveSync} to retrieve frames.
428
430
  * On first frame, automatically builds filter graph with frame properties.
429
- * May buffer frames internally before producing output.
430
- * Hardware frames context is automatically detected from frame.
431
- * Returns null if filter is closed and frame is null.
432
- *
433
- * **Note**: This method receives only ONE frame per call.
434
- * A single input frame can produce multiple output frames (e.g., fps filter, deinterlace).
435
- * To receive all frames from an input, use {@link processAllSync} or {@link framesSync} instead.
431
+ * A single input frame can produce zero, one, or multiple output frames.
436
432
  *
437
- * Direct mapping to av_buffersrc_add_frame() and av_buffersink_get_frame().
433
+ * **Important**: This method only SENDS the frame to the filter.
434
+ * You must call {@link receiveSync} separately (potentially multiple times) to get filtered frames.
438
435
  *
439
- * @param frame - Input frame to process (or null to flush)
436
+ * Direct mapping to av_buffersrc_add_frame().
440
437
  *
441
- * @returns Filtered frame or null if buffered
438
+ * @param frame - Input frame to send to filter
442
439
  *
443
440
  * @throws {Error} If filter could not be initialized
444
441
  *
445
- * @throws {FFmpegError} If processing fails
442
+ * @throws {FFmpegError} If sending frame fails
446
443
  *
447
444
  * @example
448
445
  * ```typescript
449
- * const output = filter.processSync(inputFrame);
450
- * if (output) {
446
+ * // Send frame and receive filtered frames
447
+ * filter.processSync(inputFrame);
448
+ *
449
+ * // Receive all available filtered frames
450
+ * let output;
451
+ * while ((output = filter.receiveSync())) {
451
452
  * console.log(`Got filtered frame: pts=${output.pts}`);
452
453
  * output.free();
453
454
  * }
454
455
  * ```
455
456
  *
456
- * @example
457
- * ```typescript
458
- * // Process frame - may buffer internally
459
- * const output = filter.processSync(frame);
460
- * if (output) {
461
- * // Got output immediately
462
- * yield output;
463
- * }
464
- * // For buffered frames, use the framesSync() generator
465
- * ```
466
- *
467
- * @see {@link processAllSync} For processing multiple output frames
457
+ * @see {@link receiveSync} For receiving filtered frames
458
+ * @see {@link processAllSync} For combined send+receive operation
468
459
  * @see {@link framesSync} For processing frame streams
469
460
  * @see {@link flushSync} For end-of-stream handling
470
461
  * @see {@link process} For async version
471
462
  */
472
- processSync(frame: Frame | null): Frame | null;
463
+ processSync(frame: Frame): void;
473
464
  /**
474
465
  * Process a frame through the filter.
475
466
  *
@@ -481,7 +472,7 @@ export declare class FilterAPI implements Disposable {
481
472
  *
482
473
  * Direct mapping to av_buffersrc_add_frame() and av_buffersink_get_frame().
483
474
  *
484
- * @param frame - Input frame to process (or null to flush)
475
+ * @param frame - Input frame to process
485
476
  *
486
477
  * @returns Array of filtered frames (empty if buffered or filter closed)
487
478
  *
@@ -525,7 +516,7 @@ export declare class FilterAPI implements Disposable {
525
516
  *
526
517
  * Direct mapping to av_buffersrc_add_frame() and av_buffersink_get_frame().
527
518
  *
528
- * @param frame - Input frame to process (or null to flush)
519
+ * @param frame - Input frame to process
529
520
  *
530
521
  * @returns Array of filtered frames (empty if buffered or filter closed)
531
522
  *
@@ -556,17 +547,22 @@ export declare class FilterAPI implements Disposable {
556
547
  * @see {@link flushSync} For end-of-stream handling
557
548
  * @see {@link process} For async version
558
549
  */
559
- processAllSync(frame: Frame | null): Frame[];
550
+ processAllSync(frame: Frame): Frame[];
560
551
  /**
561
552
  * Process frame stream through filter.
562
553
  *
563
554
  * High-level async generator for filtering frame streams.
564
- * Automatically handles buffering and flushing.
565
- * Frees input frames after processing.
555
+ * Filter is only flushed when EOF (null) signal is explicitly received.
556
+ * Primary interface for stream-based filtering.
557
+ *
558
+ * **EOF Handling:**
559
+ * - Send null to flush filter and get remaining buffered frames
560
+ * - Generator yields null after flushing when null is received
561
+ * - No automatic flushing - filter stays open until EOF or close()
566
562
  *
567
- * @param frames - Async generator of input frames
563
+ * @param frames - Async iterable of frames, single frame, or null to flush
568
564
  *
569
- * @yields {Frame} Filtered frames
565
+ * @yields {Frame | null} Filtered frames, followed by null when explicitly flushed
570
566
  *
571
567
  * @throws {Error} If filter not ready
572
568
  *
@@ -574,8 +570,12 @@ export declare class FilterAPI implements Disposable {
574
570
  *
575
571
  * @example
576
572
  * ```typescript
577
- * // Filter decoded frames
573
+ * // Stream of frames with automatic EOF propagation
578
574
  * for await (const frame of filter.frames(decoder.frames(packets))) {
575
+ * if (frame === null) {
576
+ * console.log('Filter flushed');
577
+ * break;
578
+ * }
579
579
  * await encoder.encode(frame);
580
580
  * frame.free();
581
581
  * }
@@ -583,16 +583,23 @@ export declare class FilterAPI implements Disposable {
583
583
  *
584
584
  * @example
585
585
  * ```typescript
586
- * // Chain filters
587
- * const filter1 = FilterAPI.create('scale=640:480', {
588
- * timeBase: video.timeBase
589
- * });
590
- * const filter2 = FilterAPI.create('rotate=PI/4', {
591
- * timeBase: video.timeBase
592
- * });
586
+ * // Single frame - no automatic flush
587
+ * for await (const frame of filter.frames(singleFrame)) {
588
+ * await encoder.encode(frame);
589
+ * frame.free();
590
+ * }
591
+ * // Filter remains open, buffered frames not flushed
592
+ * ```
593
593
  *
594
- * for await (const frame of filter2.frames(filter1.frames(input))) {
595
- * // Process filtered frames
594
+ * @example
595
+ * ```typescript
596
+ * // Explicit flush with EOF
597
+ * for await (const frame of filter.frames(null)) {
598
+ * if (frame === null) {
599
+ * console.log('All buffered frames flushed');
600
+ * break;
601
+ * }
602
+ * console.log('Buffered frame:', frame.pts);
596
603
  * frame.free();
597
604
  * }
598
605
  * ```
@@ -601,18 +608,23 @@ export declare class FilterAPI implements Disposable {
601
608
  * @see {@link Decoder.frames} For frames source
602
609
  * @see {@link framesSync} For sync version
603
610
  */
604
- frames(frames: AsyncIterable<Frame | null>): AsyncGenerator<Frame | null>;
611
+ frames(frames: AsyncIterable<Frame | null> | Frame | null): AsyncGenerator<Frame | null>;
605
612
  /**
606
613
  * Process frame stream through filter synchronously.
607
614
  * Synchronous version of frames.
608
615
  *
609
616
  * High-level sync generator for filtering frame streams.
610
- * Automatically handles buffering and flushing.
611
- * Frees input frames after processing.
617
+ * Filter is only flushed when EOF (null) signal is explicitly received.
618
+ * Primary interface for stream-based filtering.
612
619
  *
613
- * @param frames - Generator of input frames
620
+ * **EOF Handling:**
621
+ * - Send null to flush filter and get remaining buffered frames
622
+ * - Generator yields null after flushing when null is received
623
+ * - No automatic flushing - filter stays open until EOF or close()
614
624
  *
615
- * @yields {Frame} Filtered frames
625
+ * @param frames - Iterable of frames, single frame, or null to flush
626
+ *
627
+ * @yields {Frame | null} Filtered frames, followed by null when explicitly flushed
616
628
  *
617
629
  * @throws {Error} If filter not ready
618
630
  *
@@ -620,8 +632,12 @@ export declare class FilterAPI implements Disposable {
620
632
  *
621
633
  * @example
622
634
  * ```typescript
623
- * // Filter decoded frames
635
+ * // Stream of frames with automatic EOF propagation
624
636
  * for (const frame of filter.framesSync(decoder.framesSync(packets))) {
637
+ * if (frame === null) {
638
+ * console.log('Filter flushed');
639
+ * break;
640
+ * }
625
641
  * encoder.encodeSync(frame);
626
642
  * frame.free();
627
643
  * }
@@ -629,16 +645,23 @@ export declare class FilterAPI implements Disposable {
629
645
  *
630
646
  * @example
631
647
  * ```typescript
632
- * // Chain filters
633
- * const filter1 = FilterAPI.create('scale=640:480', {
634
- * timeBase: video.timeBase
635
- * });
636
- * const filter2 = FilterAPI.create('rotate=PI/4', {
637
- * timeBase: video.timeBase
638
- * });
648
+ * // Single frame - no automatic flush
649
+ * for (const frame of filter.framesSync(singleFrame)) {
650
+ * encoder.encodeSync(frame);
651
+ * frame.free();
652
+ * }
653
+ * // Filter remains open, buffered frames not flushed
654
+ * ```
639
655
  *
640
- * for (const frame of filter2.framesSync(filter1.framesSync(input))) {
641
- * // Process filtered frames
656
+ * @example
657
+ * ```typescript
658
+ * // Explicit flush with EOF
659
+ * for (const frame of filter.framesSync(null)) {
660
+ * if (frame === null) {
661
+ * console.log('All buffered frames flushed');
662
+ * break;
663
+ * }
664
+ * console.log('Buffered frame:', frame.pts);
642
665
  * frame.free();
643
666
  * }
644
667
  * ```
@@ -647,7 +670,7 @@ export declare class FilterAPI implements Disposable {
647
670
  * @see {@link Decoder.framesSync} For frames source
648
671
  * @see {@link frames} For async version
649
672
  */
650
- framesSync(frames: Generator<Frame | null>): Generator<Frame | null>;
673
+ framesSync(frames: Iterable<Frame | null> | Frame | null): Generator<Frame | null>;
651
674
  /**
652
675
  * Flush filter and signal end-of-stream.
653
676
  *
@@ -754,57 +777,101 @@ export declare class FilterAPI implements Disposable {
754
777
  * Receive buffered frame from filter.
755
778
  *
756
779
  * Drains frames buffered by the filter.
757
- * Call repeatedly until null to get all buffered frames.
758
- * Returns null if filter is closed, not initialized, or no frames available.
780
+ * Call repeatedly until null or EOF to get all buffered frames.
781
+ * Implements FFmpeg's send/receive pattern.
782
+ *
783
+ * **Return Values:**
784
+ * - `Frame` - Successfully received frame (AVERROR >= 0)
785
+ * - `null` - Need more input data (AVERROR_EAGAIN), or filter not initialized
786
+ * - `undefined` - End of stream reached (AVERROR_EOF), or filter is closed
759
787
  *
760
788
  * Direct mapping to av_buffersink_get_frame().
761
789
  *
762
- * @returns Buffered frame or null if none available
790
+ * @returns Buffered frame, null if need more data, or undefined if stream ended
763
791
  *
764
792
  * @throws {FFmpegError} If receiving fails
765
793
  *
766
794
  * @example
767
795
  * ```typescript
768
- * let frame;
769
- * while ((frame = await filter.receive()) !== null) {
796
+ * // Process all buffered frames
797
+ * while (true) {
798
+ * const frame = await filter.receive();
799
+ * if (!frame) break; // Stop on EAGAIN or EOF
770
800
  * console.log(`Received frame: pts=${frame.pts}`);
771
801
  * frame.free();
772
802
  * }
773
803
  * ```
774
804
  *
805
+ * @example
806
+ * ```typescript
807
+ * // Handle each return value explicitly
808
+ * const frame = await filter.receive();
809
+ * if (frame === EOF) {
810
+ * console.log('Filter stream ended');
811
+ * } else if (frame === null) {
812
+ * console.log('Need more input data');
813
+ * } else {
814
+ * console.log(`Got frame: pts=${frame.pts}`);
815
+ * frame.free();
816
+ * }
817
+ * ```
818
+ *
775
819
  * @see {@link process} For frame processing
776
820
  * @see {@link flush} For flushing filter
777
821
  * @see {@link receiveSync} For synchronous version
822
+ * @see {@link EOF} For end-of-stream signal
778
823
  */
779
- receive(): Promise<Frame | null>;
824
+ receive(): Promise<Frame | EOFSignal | null>;
780
825
  /**
781
826
  * Receive buffered frame from filter synchronously.
782
827
  * Synchronous version of receive.
783
828
  *
784
829
  * Drains frames buffered by the filter.
785
- * Call repeatedly until null to get all buffered frames.
786
- * Returns null if filter is closed, not initialized, or no frames available.
830
+ * Call repeatedly until null or EOF to get all buffered frames.
831
+ * Implements FFmpeg's send/receive pattern.
832
+ *
833
+ * **Return Values:**
834
+ * - `Frame` - Successfully received frame (AVERROR >= 0)
835
+ * - `null` - Need more input data (AVERROR_EAGAIN), or filter not initialized
836
+ * - `undefined` - End of stream reached (AVERROR_EOF), or filter is closed
787
837
  *
788
838
  * Direct mapping to av_buffersink_get_frame().
789
839
  *
790
- * @returns Buffered frame or null if none available
840
+ * @returns Buffered frame, null if need more data, or undefined if stream ended
791
841
  *
792
842
  * @throws {FFmpegError} If receiving fails
793
843
  *
794
844
  * @example
795
845
  * ```typescript
796
- * let frame;
797
- * while ((frame = filter.receiveSync()) !== null) {
846
+ * // Process all buffered frames
847
+ * while (true) {
848
+ * const frame = filter.receiveSync();
849
+ * if (!frame) break; // Stop on EAGAIN or EOF
798
850
  * console.log(`Received frame: pts=${frame.pts}`);
799
851
  * frame.free();
800
852
  * }
801
853
  * ```
802
854
  *
855
+ * @example
856
+ * ```typescript
857
+ * // Handle each return value explicitly
858
+ * const frame = filter.receiveSync();
859
+ * if (frame === EOF) {
860
+ * console.log('Filter stream ended');
861
+ * } else if (frame === null) {
862
+ * console.log('Need more input data');
863
+ * } else {
864
+ * console.log(`Got frame: pts=${frame.pts}`);
865
+ * frame.free();
866
+ * }
867
+ * ```
868
+ *
803
869
  * @see {@link processSync} For frame processing
804
870
  * @see {@link flushSync} For flushing filter
805
871
  * @see {@link receive} For async version
872
+ * @see {@link EOF} For end-of-stream signal
806
873
  */
807
- receiveSync(): Frame | null;
874
+ receiveSync(): Frame | EOFSignal | null;
808
875
  /**
809
876
  * Send command to filter.
810
877
  *
@@ -903,9 +970,20 @@ export declare class FilterAPI implements Disposable {
903
970
  */
904
971
  private runWorker;
905
972
  /**
906
- * Send frame to input queue.
973
+ * Send frame to input queue or flush the pipeline.
974
+ *
975
+ * When frame is provided, queues it for filtering.
976
+ * When null is provided, triggers flush sequence:
977
+ * - Closes input queue
978
+ * - Waits for worker completion
979
+ * - Flushes filter and sends remaining frames to output queue
980
+ * - Closes output queue
981
+ * - Waits for pipeTo task completion
982
+ * - Propagates flush to next component (if any)
907
983
  *
908
- * @param frame - Frame to send
984
+ * Used by scheduler system for pipeline control.
985
+ *
986
+ * @param frame - Frame to send, or null to flush
909
987
  *
910
988
  * @internal
911
989
  */
@@ -918,14 +996,6 @@ export declare class FilterAPI implements Disposable {
918
996
  * @internal
919
997
  */
920
998
  private receiveFrame;
921
- /**
922
- * Flush the entire filter pipeline.
923
- *
924
- * Propagates flush through worker, output queue, and next component.
925
- *
926
- * @internal
927
- */
928
- private flushPipeline;
929
999
  /**
930
1000
  * Initialize filter graph from first frame.
931
1001
  *