node-av 6.2.0-beta.9 → 7.0.0-beta.1

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 (116) hide show
  1. package/README.md +7 -19
  2. package/dist/api/audio-frame-buffer.d.ts +378 -19
  3. package/dist/api/audio-frame-buffer.js +715 -101
  4. package/dist/api/audio-frame-buffer.js.map +1 -1
  5. package/dist/api/data/test_av1.ivf +0 -0
  6. package/dist/api/data/test_hevc.h265 +0 -0
  7. package/dist/api/data/test_vp9.ivf +0 -0
  8. package/dist/api/decoder.d.ts +117 -2
  9. package/dist/api/decoder.js +290 -23
  10. package/dist/api/decoder.js.map +1 -1
  11. package/dist/api/demuxer.d.ts +19 -3
  12. package/dist/api/demuxer.js +95 -29
  13. package/dist/api/demuxer.js.map +1 -1
  14. package/dist/api/encoder-pool.js +9 -1
  15. package/dist/api/encoder-pool.js.map +1 -1
  16. package/dist/api/encoder.d.ts +100 -6
  17. package/dist/api/encoder.js +249 -108
  18. package/dist/api/encoder.js.map +1 -1
  19. package/dist/api/filter-presets.d.ts +25 -1
  20. package/dist/api/filter-presets.js +67 -5
  21. package/dist/api/filter-presets.js.map +1 -1
  22. package/dist/api/filter.d.ts +62 -3
  23. package/dist/api/filter.js +118 -36
  24. package/dist/api/filter.js.map +1 -1
  25. package/dist/api/fmp4-stream.d.ts +179 -15
  26. package/dist/api/fmp4-stream.js +341 -120
  27. package/dist/api/fmp4-stream.js.map +1 -1
  28. package/dist/api/hardware.d.ts +2 -0
  29. package/dist/api/hardware.js +33 -10
  30. package/dist/api/hardware.js.map +1 -1
  31. package/dist/api/index.d.ts +2 -2
  32. package/dist/api/index.js.map +1 -1
  33. package/dist/api/io-stream.d.ts +3 -2
  34. package/dist/api/io-stream.js +23 -7
  35. package/dist/api/io-stream.js.map +1 -1
  36. package/dist/api/muxer.d.ts +276 -7
  37. package/dist/api/muxer.js +649 -116
  38. package/dist/api/muxer.js.map +1 -1
  39. package/dist/api/pipeline.d.ts +22 -0
  40. package/dist/api/pipeline.js +53 -0
  41. package/dist/api/pipeline.js.map +1 -1
  42. package/dist/api/rtp-stream.d.ts +54 -33
  43. package/dist/api/rtp-stream.js +232 -153
  44. package/dist/api/rtp-stream.js.map +1 -1
  45. package/dist/api/scaler.d.ts +39 -6
  46. package/dist/api/scaler.js +72 -18
  47. package/dist/api/scaler.js.map +1 -1
  48. package/dist/api/utilities/live-decoding.d.ts +15 -0
  49. package/dist/api/utilities/live-decoding.js +32 -0
  50. package/dist/api/utilities/live-decoding.js.map +1 -0
  51. package/dist/api/utilities/packet-age-watchdog.d.ts +198 -0
  52. package/dist/api/utilities/packet-age-watchdog.js +594 -0
  53. package/dist/api/utilities/packet-age-watchdog.js.map +1 -0
  54. package/dist/api/utilities/scale-size.d.ts +51 -0
  55. package/dist/api/utilities/scale-size.js +55 -0
  56. package/dist/api/utilities/scale-size.js.map +1 -0
  57. package/dist/api/utilities/video-transcode.d.ts +218 -0
  58. package/dist/api/utilities/video-transcode.js +624 -0
  59. package/dist/api/utilities/video-transcode.js.map +1 -0
  60. package/dist/constants/bsf-options.d.ts +32 -8
  61. package/dist/constants/constants.d.ts +36 -114
  62. package/dist/constants/constants.js +32 -95
  63. package/dist/constants/constants.js.map +1 -1
  64. package/dist/constants/decoders.d.ts +74 -74
  65. package/dist/constants/decoders.js +79 -77
  66. package/dist/constants/decoders.js.map +1 -1
  67. package/dist/constants/encoders.d.ts +20 -21
  68. package/dist/constants/encoders.js +25 -24
  69. package/dist/constants/encoders.js.map +1 -1
  70. package/dist/constants/filter-options.d.ts +1378 -194
  71. package/dist/constants/format-options.d.ts +1342 -83
  72. package/dist/constants/formats.d.ts +2 -2
  73. package/dist/constants/options.d.ts +2261 -125
  74. package/dist/ffmpeg/utils.js +7 -4
  75. package/dist/ffmpeg/utils.js.map +1 -1
  76. package/dist/ffmpeg/version.d.ts +1 -1
  77. package/dist/ffmpeg/version.js +1 -1
  78. package/dist/ffmpeg/version.js.map +1 -1
  79. package/dist/lib/binding.d.ts +10 -1
  80. package/dist/lib/binding.js +25 -16
  81. package/dist/lib/binding.js.map +1 -1
  82. package/dist/lib/bitstream-filter-context.d.ts +2 -0
  83. package/dist/lib/bitstream-filter-context.js +2 -0
  84. package/dist/lib/bitstream-filter-context.js.map +1 -1
  85. package/dist/lib/filter-context.d.ts +3 -0
  86. package/dist/lib/filter-context.js +3 -0
  87. package/dist/lib/filter-context.js.map +1 -1
  88. package/dist/lib/filter-graph-segment.d.ts +3 -2
  89. package/dist/lib/filter-graph-segment.js +3 -2
  90. package/dist/lib/filter-graph-segment.js.map +1 -1
  91. package/dist/lib/filter-graph.d.ts +4 -4
  92. package/dist/lib/filter-graph.js +4 -4
  93. package/dist/lib/filter-inout.d.ts +4 -0
  94. package/dist/lib/filter-inout.js +4 -0
  95. package/dist/lib/filter-inout.js.map +1 -1
  96. package/dist/lib/format-context.d.ts +27 -3
  97. package/dist/lib/format-context.js +30 -6
  98. package/dist/lib/format-context.js.map +1 -1
  99. package/dist/lib/frame.d.ts +6 -2
  100. package/dist/lib/frame.js +11 -3
  101. package/dist/lib/frame.js.map +1 -1
  102. package/dist/lib/io-context.d.ts +4 -2
  103. package/dist/lib/io-context.js +4 -2
  104. package/dist/lib/io-context.js.map +1 -1
  105. package/dist/lib/native-types.d.ts +7 -3
  106. package/dist/lib/output-format.d.ts +42 -0
  107. package/dist/lib/output-format.js +46 -0
  108. package/dist/lib/output-format.js.map +1 -1
  109. package/dist/lib/stream.d.ts +5 -0
  110. package/dist/lib/stream.js +5 -0
  111. package/dist/lib/stream.js.map +1 -1
  112. package/dist/lib/utilities.d.ts +26 -0
  113. package/dist/lib/utilities.js +28 -0
  114. package/dist/lib/utilities.js.map +1 -1
  115. package/install/check.js +14 -16
  116. package/package.json +28 -44
@@ -54,6 +54,12 @@ export interface FMP4StreamOptions {
54
54
  /**
55
55
  * Callback invoked when the stream is closed or encounters an error.
56
56
  *
57
+ * Called once per started session. On an error the stream has already been
58
+ * stopped and its resources (including the input connection) released.
59
+ * Output the muxer still held at the error is discarded, so no `onData` call
60
+ * follows the failure. Exceptions thrown by the callback are logged and do
61
+ * not propagate.
62
+ *
57
63
  * @param error - Optional error if stream closed due to an error
58
64
  */
59
65
  onClose?: (error?: Error) => void;
@@ -72,6 +78,9 @@ export interface FMP4StreamOptions {
72
78
  * requested via movFlags such as `frag_keyframe`).
73
79
  * Smaller values reduce latency but increase overhead.
74
80
  * Set to 1 to send data as soon as possible.
81
+ * Transcoded video gets a GOP of the fragment duration from 0.5 s on, so
82
+ * every fragment starts with a keyframe; below that, and with 0, it gets a
83
+ * 2 s GOP.
75
84
  *
76
85
  * @default 1
77
86
  *
@@ -138,6 +147,14 @@ export interface FMP4StreamOptions {
138
147
  width?: number;
139
148
  height?: number;
140
149
  bitrate?: number;
150
+ /**
151
+ * Transcode to H.264 even when the source codec is one of `supportedCodecs`, so `width`, `height`, `fps` and `bitrate` apply.
152
+ */
153
+ transcode?: boolean;
154
+ /**
155
+ * FourCC sample entry tag for the HEVC video stream, e.g. `hvc1`. Only applied to HEVC output.
156
+ */
157
+ tag?: string;
141
158
  encoderOptions?: EncoderOptions['options'];
142
159
  };
143
160
  /**
@@ -169,6 +186,60 @@ export interface FMP4StreamOptions {
169
186
  * @default '+frag_keyframe+separate_moof+default_base_moof+empty_moov'
170
187
  */
171
188
  movFlags?: string;
189
+ /**
190
+ * Backward DTS jump in seconds above which the stream ends with an error.
191
+ *
192
+ * A live source that restarts its clock (a camera reboot behind a restreamer)
193
+ * would otherwise leave every following packet clamped to one tick past the
194
+ * previous one, so fragments carry no media for as long as the jump. The stream
195
+ * instead stops and reports the error through `onClose(error)`, and the owner
196
+ * can restart it on a fresh timeline. Smaller jumps are clamped. `0` disables
197
+ * the check. Same semantics as the `Muxer` option of the same name.
198
+ *
199
+ * @default 10
200
+ */
201
+ dtsBackwardThreshold?: number;
202
+ /**
203
+ * Forward DTS jump in seconds, beyond the real time that passed, above which
204
+ * the stream ends with an error.
205
+ *
206
+ * A live source that restarts its clock (a camera reboot behind a
207
+ * restreamer) can continue with timestamps far ahead of the time that
208
+ * passed. Muxing that would leave a sample spanning the jump, or, when the
209
+ * timeline later returns, a stream clamped behind it. The stream instead
210
+ * stops and reports the error through `onClose(error)`, and the owner can
211
+ * restart it on a fresh timeline. Gaps in the source come with a matching
212
+ * wait and pass. Only meaningful for inputs read in real time, so it is off
213
+ * for files, a pre-opened Demuxer and frame sources unless set; pass it for
214
+ * live inputs read over HTTP (HLS, HTTP-FLV) as well. Same semantics as the
215
+ * `Muxer` option of the same name; `0` disables the check.
216
+ *
217
+ * @default 10 for rtsp, rtsps, rtmp (and rtmps, rtmpt, rtmpe, rtmpte, rtmpts), rtp, srtp, udp, srt, tcp, tls and sctp URLs, 0 otherwise
218
+ */
219
+ dtsForwardThreshold?: number;
220
+ /**
221
+ * Longest time in seconds a packet may wait inside the muxer before it is
222
+ * emitted in a fragment.
223
+ *
224
+ * The mp4 muxer holds packets back to interleave the streams by timestamp.
225
+ * When a stream's timestamps stop advancing or run far ahead of a silent
226
+ * stream (a camera restarting its clock behind a restreamer, missing
227
+ * timestamps), packets can pile up without ever being emitted while memory
228
+ * grows. The age is measured per stream in real time while the input
229
+ * delivers packets and is independent of the timestamps; once the oldest
230
+ * pending packet of any stream is older than this, the stream stops and
231
+ * reports the error through `onClose(error)`. A pause of the whole input
232
+ * counts at most 2 s, so a source that goes quiet and resumes does not end
233
+ * the session. Healthy sessions stay below the default: up to the fragment
234
+ * duration (the GOP length with `fragDuration: 0`) plus about 10 s of
235
+ * interleaving delay while a stream is silent. Inputs read faster than real
236
+ * time can pile up correspondingly more media before it fires, inputs that
237
+ * deliver packets more than 2 s apart take correspondingly longer. `0`
238
+ * disables the check.
239
+ *
240
+ * @default 60
241
+ */
242
+ maxPacketAge?: number;
172
243
  /**
173
244
  * AbortSignal for cancellation.
174
245
  *
@@ -177,6 +248,19 @@ export interface FMP4StreamOptions {
177
248
  */
178
249
  signal?: AbortSignal;
179
250
  }
251
+ /**
252
+ * Video description of the muxed fMP4 output.
253
+ */
254
+ export interface FMP4VideoInfo {
255
+ /** Output codec family. */
256
+ codec: 'h264' | 'hevc' | 'av1' | 'unknown';
257
+ /** RFC 6381 codec string of the output (e.g. `hvc1.1.6.L120.B0`). */
258
+ codecString: string;
259
+ width: number;
260
+ height: number;
261
+ /** Frames per second, 0 when unknown. */
262
+ fps: number;
263
+ }
180
264
  /**
181
265
  * Target codec strings for fMP4 streaming.
182
266
  */
@@ -192,7 +276,8 @@ export declare const FMP4_CODECS: {
192
276
  * High-level fMP4 streaming with automatic codec detection and transcoding.
193
277
  *
194
278
  * Provides fragmented MP4 streaming for clients.
195
- * Automatically transcodes video to H.264 and audio to AAC if not supported by client.
279
+ * Automatically transcodes video to H.264 and audio to AAC (Opus when the client
280
+ * lists Opus but not AAC) if not supported by client.
196
281
  * Client sends supported codecs, server transcodes accordingly.
197
282
  * Essential component for building adaptive streaming servers.
198
283
  *
@@ -234,6 +319,7 @@ export declare class FMP4Stream {
234
319
  private options;
235
320
  private inputUrl;
236
321
  private inputOptions;
322
+ private liveInput;
237
323
  private input?;
238
324
  private source?;
239
325
  private output?;
@@ -252,9 +338,12 @@ export declare class FMP4Stream {
252
338
  private pendingFragment;
253
339
  private abortHandler?;
254
340
  private stopRequested;
341
+ private discardOutput;
255
342
  private stopPromise?;
256
343
  private startAbort?;
344
+ private stopSignal;
257
345
  private fragmentQueue;
346
+ private packetAgeWatchdog?;
258
347
  private _droppedFragments;
259
348
  private _initSegment;
260
349
  private _initSegmentResolve;
@@ -269,6 +358,8 @@ export declare class FMP4Stream {
269
358
  *
270
359
  * Use {@link create} factory method
271
360
  *
361
+ * @throws {RangeError} If dtsBackwardThreshold, dtsForwardThreshold or maxPacketAge is not a finite number >= 0
362
+ *
272
363
  * @internal
273
364
  */
274
365
  private constructor();
@@ -284,6 +375,8 @@ export declare class FMP4Stream {
284
375
  *
285
376
  * @returns Configured fMP4 stream instance
286
377
  *
378
+ * @throws {RangeError} If dtsBackwardThreshold, dtsForwardThreshold or maxPacketAge is not a finite number >= 0
379
+ *
287
380
  * @example
288
381
  * ```typescript
289
382
  * // Stream from file with codec negotiation
@@ -374,13 +467,29 @@ export declare class FMP4Stream {
374
467
  * ```
375
468
  */
376
469
  getCodecString(): string;
470
+ /**
471
+ * Video description of the muxed fMP4 output (output codec, RFC 6381 codec string, resolution, fps).
472
+ *
473
+ * Available after {@link start} has opened the input.
474
+ *
475
+ * @returns The output video info, or `undefined` when there is no video track.
476
+ *
477
+ * @example
478
+ * ```typescript
479
+ * const videoInfo = stream.getVideoInfo();
480
+ * if (videoInfo) {
481
+ * console.log(`Codec: ${videoInfo.codec}, Resolution: ${videoInfo.width}x${videoInfo.height}, FPS: ${videoInfo.fps}`);
482
+ * }
483
+ * ```
484
+ */
485
+ getVideoInfo(): FMP4VideoInfo | undefined;
377
486
  /**
378
487
  * Start streaming media to fMP4 chunks.
379
488
  *
380
489
  * Begins the media processing pipeline, reading packets from input,
381
490
  * transcoding based on supported codecs, and generating fMP4 chunks.
382
491
  * Video transcodes to H.264 if H.264/H.265 not supported.
383
- * Audio transcodes to AAC if AAC/FLAC/Opus not supported.
492
+ * Audio transcodes to AAC (Opus when only Opus is listed) if the input codec is not supported.
384
493
  * This method returns immediately after starting the pipeline.
385
494
  *
386
495
  * @returns Promise that resolves when pipeline is started
@@ -421,27 +530,27 @@ export declare class FMP4Stream {
421
530
  */
422
531
  private throwIfStopRequested;
423
532
  /**
424
- * Cap the video bitrate on the encoder context.
533
+ * GOP size for the video encoder that starts every fragment with a keyframe.
425
534
  *
426
- * Applies a VBV rate cap (maxrate + a 1s buffer) WITHOUT setting a target
427
- * bitrate, so the encoder keeps its default constant-quality mode but can
428
- * never exceed the negotiated ceiling. Setting the bitrate as an ABR target
429
- * instead would push a normally-lighter stream UP to fill it, overshooting on
430
- * bursts - the opposite of what strict rate-capped consumers want.
431
- * No-op when no bitrate was requested.
535
+ * frag_duration flushes a fragment once it is that long, mid-GOP on a
536
+ * P-frame unless the GOP has the same length, and strict consumers reject
537
+ * such fragments. Shorter fragments (the 1 µs default flushes after every
538
+ * frame) are not matched: a GOP of a few frames multiplies the bitrate, so
539
+ * below MIN_FRAGMENT_GOP the GOP is 2 s, as with a fragDuration of 0.
432
540
  *
433
- * @param ctx - Encoder codec context
541
+ * @param fps - Output frame rate
434
542
  *
435
- * @param bitrate - Maximum bitrate in bits per second, or undefined
543
+ * @returns GOP size in frames
436
544
  *
437
545
  * @internal
438
546
  */
439
- private applyBitrate;
547
+ private gopSize;
440
548
  /**
441
549
  * Create the fMP4 output muxer with the fragment-emitting write callback.
442
550
  *
443
551
  * Uses `this.input` when present (demuxer path) and no input for the
444
- * frame-source path.
552
+ * frame-source path. Attaches a fresh packet age watchdog unless
553
+ * `maxPacketAge` is 0.
445
554
  *
446
555
  * @returns The configured muxer
447
556
  *
@@ -452,13 +561,36 @@ export declare class FMP4Stream {
452
561
  * Wire the pipeline completion to the fragment/close callbacks.
453
562
  *
454
563
  * On success ends the fragment iterator and invokes `onClose()`; on error
455
- * stops the stream and invokes `onClose(error)`. Runs in the background.
564
+ * stops the stream, discarding the output the muxer still holds, and invokes
565
+ * `onClose(error)`. Either way `onClose` runs exactly once and the detached
566
+ * chain never rejects. Runs in the background.
456
567
  *
457
568
  * @param completion - The pipeline completion promise
458
569
  *
459
570
  * @internal
460
571
  */
461
572
  private attachCompletion;
573
+ /**
574
+ * Invoke the owner's onClose callback.
575
+ *
576
+ * The completion chain runs detached, so an exception from the callback
577
+ * could only surface as an unhandled rejection - it is logged instead.
578
+ *
579
+ * @param error - Pipeline error, or undefined for a clean end
580
+ *
581
+ * @internal
582
+ */
583
+ private emitClose;
584
+ /**
585
+ * Whether a pipeline rejection was caused by an intentional shutdown.
586
+ *
587
+ * @param error - The pipeline rejection reason
588
+ *
589
+ * @returns True when stop() is in flight or the owner's signal aborted
590
+ *
591
+ * @internal
592
+ */
593
+ private isDeliberateStop;
462
594
  /**
463
595
  * Set up encoders and the fMP4 muxer for a pre-composited frame source and
464
596
  * start encoding. No demuxer or decoder is involved - the provided frames are
@@ -477,7 +609,8 @@ export declare class FMP4Stream {
477
609
  *
478
610
  * Stops the pipeline, closes output, and releases all FFmpeg resources.
479
611
  * Safe to call multiple times. After stopping, you can call start() again
480
- * to restart the stream.
612
+ * to restart the stream. Resolves even if the pipeline had failed; that
613
+ * error is reported through `onClose(error)`.
481
614
  *
482
615
  * @example
483
616
  * ```typescript
@@ -540,6 +673,16 @@ export declare class FMP4Stream {
540
673
  * @internal
541
674
  */
542
675
  private runPipeline;
676
+ /**
677
+ * Check if the video is encoded again instead of passed through.
678
+ *
679
+ * @param codecId - Codec ID of the source video
680
+ *
681
+ * @returns True if `video.transcode` is set or the codec is not in supported codecs
682
+ *
683
+ * @internal
684
+ */
685
+ private transcodesVideo;
543
686
  /**
544
687
  * Check if video codec is supported.
545
688
  *
@@ -550,6 +693,27 @@ export declare class FMP4Stream {
550
693
  * @internal
551
694
  */
552
695
  private isVideoCodecSupported;
696
+ /**
697
+ * Codec that unsupported audio is transcoded to.
698
+ *
699
+ * @returns Opus when the client lists Opus but not AAC, otherwise AAC
700
+ *
701
+ * @internal
702
+ */
703
+ private audioTranscodeTarget;
704
+ /**
705
+ * Create the audio filter and encoder for the transcode target.
706
+ *
707
+ * AAC is resampled to 44.1 kHz stereo. Opus is resampled to 48 kHz, the only
708
+ * rate it transmits, keeps mono input mono and uses 20 ms frames.
709
+ *
710
+ * @param decoder - Input audio decoder, absent for a frame source
711
+ *
712
+ * @param channels - Input channel count, 0 when unknown
713
+ *
714
+ * @internal
715
+ */
716
+ private createAudioEncoder;
553
717
  /**
554
718
  * Check if audio codec is supported.
555
719
  *