node-av 6.2.0-beta.2 → 6.2.0-beta.21
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/README.md +13 -8
- package/dist/api/audio-frame-buffer.d.ts +73 -1
- package/dist/api/audio-frame-buffer.js +127 -1
- package/dist/api/audio-frame-buffer.js.map +1 -1
- package/dist/api/bitstream-filter.d.ts +82 -4
- package/dist/api/bitstream-filter.js +197 -100
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/decoder.d.ts +5 -0
- package/dist/api/decoder.js +13 -6
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/demuxer.d.ts +15 -1
- package/dist/api/demuxer.js +165 -54
- package/dist/api/demuxer.js.map +1 -1
- package/dist/api/encoder-pool.d.ts +43 -1
- package/dist/api/encoder-pool.js +121 -9
- package/dist/api/encoder-pool.js.map +1 -1
- package/dist/api/encoder.d.ts +19 -0
- package/dist/api/encoder.js +112 -45
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter.js +15 -6
- package/dist/api/filter.js.map +1 -1
- package/dist/api/fmp4-stream.d.ts +167 -3
- package/dist/api/fmp4-stream.js +423 -90
- package/dist/api/fmp4-stream.js.map +1 -1
- package/dist/api/hardware.d.ts +2 -0
- package/dist/api/hardware.js +25 -4
- package/dist/api/hardware.js.map +1 -1
- package/dist/api/io-stream.d.ts +3 -2
- package/dist/api/io-stream.js +61 -5
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/muxer.d.ts +14 -0
- package/dist/api/muxer.js +131 -51
- package/dist/api/muxer.js.map +1 -1
- package/dist/api/pipeline.d.ts +24 -0
- package/dist/api/pipeline.js +76 -5
- package/dist/api/pipeline.js.map +1 -1
- package/dist/api/rtp-stream.d.ts +56 -6
- package/dist/api/rtp-stream.js +252 -80
- package/dist/api/rtp-stream.js.map +1 -1
- package/dist/api/scaler.d.ts +105 -17
- package/dist/api/scaler.js +326 -108
- package/dist/api/scaler.js.map +1 -1
- package/dist/api/utilities/async-queue.d.ts +3 -0
- package/dist/api/utilities/async-queue.js +8 -0
- package/dist/api/utilities/async-queue.js.map +1 -1
- package/dist/api/webrtc-stream.d.ts +2 -0
- package/dist/api/webrtc-stream.js +46 -12
- package/dist/api/webrtc-stream.js.map +1 -1
- package/dist/api/whisper.d.ts +2 -0
- package/dist/api/whisper.js +63 -23
- package/dist/api/whisper.js.map +1 -1
- package/dist/constants/constants.d.ts +1 -0
- package/dist/constants/constants.js +1 -0
- package/dist/constants/constants.js.map +1 -1
- package/dist/constants/filter-options.d.ts +2 -0
- package/dist/ffmpeg/install.js +115 -29
- package/dist/ffmpeg/install.js.map +1 -1
- package/dist/ffmpeg/utils.js +7 -4
- package/dist/ffmpeg/utils.js.map +1 -1
- package/dist/lib/binding.d.ts +1 -0
- package/dist/lib/binding.js +12 -16
- package/dist/lib/binding.js.map +1 -1
- package/dist/lib/codec-context.d.ts +0 -2
- package/dist/lib/codec-context.js +4 -22
- package/dist/lib/codec-context.js.map +1 -1
- package/dist/lib/filter-context.d.ts +0 -1
- package/dist/lib/filter-context.js +2 -11
- package/dist/lib/filter-context.js.map +1 -1
- package/dist/lib/format-context.d.ts +63 -7
- package/dist/lib/format-context.js +70 -21
- package/dist/lib/format-context.js.map +1 -1
- package/dist/lib/frame.d.ts +11 -11
- package/dist/lib/frame.js +13 -20
- package/dist/lib/frame.js.map +1 -1
- package/dist/lib/hardware-frames-context.d.ts +0 -1
- package/dist/lib/hardware-frames-context.js +2 -8
- package/dist/lib/hardware-frames-context.js.map +1 -1
- package/dist/lib/io-context.d.ts +4 -2
- package/dist/lib/io-context.js +4 -2
- package/dist/lib/io-context.js.map +1 -1
- package/dist/lib/native-types.d.ts +4 -4
- package/dist/lib/option.d.ts +26 -0
- package/dist/lib/option.js +42 -18
- package/dist/lib/option.js.map +1 -1
- package/dist/lib/packet.d.ts +5 -0
- package/dist/lib/packet.js +5 -0
- package/dist/lib/packet.js.map +1 -1
- package/dist/lib/stream.d.ts +3 -4
- package/dist/lib/stream.js +17 -24
- package/dist/lib/stream.js.map +1 -1
- package/install/check.js +40 -79
- package/package.json +43 -32
- package/build_mac_local.sh +0 -69
|
@@ -10,9 +10,9 @@ export type MP4BoxType = 'ftyp' | 'styp' | 'moov' | 'moof' | 'mdat' | 'free' | '
|
|
|
10
10
|
export interface MP4Box {
|
|
11
11
|
/** Four-character code identifying the box type (e.g., 'ftyp', 'moov', 'moof') */
|
|
12
12
|
type: MP4BoxType;
|
|
13
|
-
/** Total size of the box in bytes (including 8-byte header) */
|
|
13
|
+
/** Total size of the box in bytes (including the 8-byte header, or 16-byte for 64-bit boxes) */
|
|
14
14
|
size: number;
|
|
15
|
-
/** Box payload data (excluding the 8-byte header) */
|
|
15
|
+
/** Box payload data (excluding the 8-byte header, or 16-byte for 64-bit boxes) */
|
|
16
16
|
data: Buffer;
|
|
17
17
|
/** Offset of this box in the original buffer */
|
|
18
18
|
offset: number;
|
|
@@ -66,12 +66,53 @@ export interface FMP4StreamOptions {
|
|
|
66
66
|
supportedCodecs?: string;
|
|
67
67
|
/**
|
|
68
68
|
* Fragment duration in microseconds.
|
|
69
|
+
*
|
|
70
|
+
* Passed to the mp4 muxer as `frag_duration`, which creates a new fragment
|
|
71
|
+
* whenever the current one exceeds this duration (in addition to any cuts
|
|
72
|
+
* requested via movFlags such as `frag_keyframe`).
|
|
69
73
|
* Smaller values reduce latency but increase overhead.
|
|
70
74
|
* Set to 1 to send data as soon as possible.
|
|
71
75
|
*
|
|
72
76
|
* @default 1
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const stream = FMP4Stream.create('rtsp://camera.local/stream', {
|
|
81
|
+
* supportedCodecs: 'avc1.640029,mp4a.40.2',
|
|
82
|
+
* fragDuration: 2_000_000, // 2 seconds in microseconds
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
73
85
|
*/
|
|
74
86
|
fragDuration?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Maximum number of media fragments buffered for a {@link FMP4Stream.fragments}
|
|
89
|
+
* consumer before the oldest are dropped.
|
|
90
|
+
*
|
|
91
|
+
* Live sources (RTSP cameras) produce fragments at a fixed rate regardless of
|
|
92
|
+
* consumer speed. Without a bound, a slow or stalled consumer would grow the
|
|
93
|
+
* queue until the process runs out of memory. When the backlog exceeds this
|
|
94
|
+
* limit, the oldest media fragments are dropped (never the init segment,
|
|
95
|
+
* which is kept separately via {@link FMP4Stream.initSegment}) and
|
|
96
|
+
* {@link FMP4Stream.droppedFragments} is incremented.
|
|
97
|
+
*
|
|
98
|
+
* @default 16
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const stream = FMP4Stream.create('rtsp://camera.local/stream', {
|
|
103
|
+
* supportedCodecs: 'avc1.640029,mp4a.40.2',
|
|
104
|
+
* boxMode: true,
|
|
105
|
+
* maxQueuedFragments: 8,
|
|
106
|
+
* });
|
|
107
|
+
*
|
|
108
|
+
* await stream.start();
|
|
109
|
+
* for await (const fragment of stream.fragments()) {
|
|
110
|
+
* await sendToClient(fragment.data); // Slow consumer - oldest fragments dropped
|
|
111
|
+
* }
|
|
112
|
+
* console.log(`Dropped ${stream.droppedFragments} fragments`);
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
maxQueuedFragments?: number;
|
|
75
116
|
/**
|
|
76
117
|
* Hardware acceleration configuration for video transcoding.
|
|
77
118
|
*
|
|
@@ -96,6 +137,7 @@ export interface FMP4StreamOptions {
|
|
|
96
137
|
fps?: number;
|
|
97
138
|
width?: number;
|
|
98
139
|
height?: number;
|
|
140
|
+
bitrate?: number;
|
|
99
141
|
encoderOptions?: EncoderOptions['options'];
|
|
100
142
|
};
|
|
101
143
|
/**
|
|
@@ -112,7 +154,10 @@ export interface FMP4StreamOptions {
|
|
|
112
154
|
bufferSize?: number;
|
|
113
155
|
/**
|
|
114
156
|
* Enable box mode - buffers data until complete MP4 boxes are available.
|
|
115
|
-
* When true, onData receives complete boxes with parsed box information
|
|
157
|
+
* When true, onData receives complete boxes with parsed box information,
|
|
158
|
+
* and media fragments are emitted fragment-aligned: a callback that contains
|
|
159
|
+
* a `moof` always contains its `mdat` too, regardless of how the muxer's
|
|
160
|
+
* I/O buffer split the write (large fragments arrive in several chunks).
|
|
116
161
|
* When false, onData receives raw chunks as they arrive from FFmpeg.
|
|
117
162
|
*
|
|
118
163
|
* @default false
|
|
@@ -204,9 +249,17 @@ export declare class FMP4Stream {
|
|
|
204
249
|
private signal?;
|
|
205
250
|
private supportedCodecs;
|
|
206
251
|
private incompleteBoxBuffer;
|
|
252
|
+
private pendingFragment;
|
|
253
|
+
private abortHandler?;
|
|
254
|
+
private stopRequested;
|
|
255
|
+
private stopPromise?;
|
|
256
|
+
private startAbort?;
|
|
257
|
+
private stopSignal;
|
|
207
258
|
private fragmentQueue;
|
|
259
|
+
private _droppedFragments;
|
|
208
260
|
private _initSegment;
|
|
209
261
|
private _initSegmentResolve;
|
|
262
|
+
private _initSegmentReject;
|
|
210
263
|
private _initSegmentPromise;
|
|
211
264
|
private _ftypData;
|
|
212
265
|
private _moovData;
|
|
@@ -257,10 +310,32 @@ export declare class FMP4Stream {
|
|
|
257
310
|
*
|
|
258
311
|
* Only available when boxMode is enabled.
|
|
259
312
|
* Resolves once the first ftyp and moov boxes have been received.
|
|
313
|
+
* Rejects if the stream fails or is stopped before the init segment
|
|
314
|
+
* was produced, so awaiting it never hangs.
|
|
260
315
|
*
|
|
261
316
|
* @throws {Error} If boxMode is not enabled
|
|
262
317
|
*/
|
|
263
318
|
get initSegment(): Promise<Buffer>;
|
|
319
|
+
/**
|
|
320
|
+
* Number of media fragments dropped due to consumer backpressure.
|
|
321
|
+
*
|
|
322
|
+
* Incremented whenever the {@link fragments} backlog exceeds
|
|
323
|
+
* `maxQueuedFragments` and the oldest fragment is discarded.
|
|
324
|
+
* Reset to 0 when the stream is (re)started.
|
|
325
|
+
*
|
|
326
|
+
* @returns Total dropped fragments for the current run
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```typescript
|
|
330
|
+
* for await (const fragment of stream.fragments()) {
|
|
331
|
+
* await sendToClient(fragment.data);
|
|
332
|
+
* if (stream.droppedFragments > 0) {
|
|
333
|
+
* console.warn(`Consumer too slow: ${stream.droppedFragments} fragments dropped`);
|
|
334
|
+
* }
|
|
335
|
+
* }
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
get droppedFragments(): number;
|
|
264
339
|
/**
|
|
265
340
|
* Get the demuxer instance.
|
|
266
341
|
*
|
|
@@ -334,6 +409,35 @@ export declare class FMP4Stream {
|
|
|
334
409
|
* @internal
|
|
335
410
|
*/
|
|
336
411
|
private doStart;
|
|
412
|
+
/**
|
|
413
|
+
* Abort an in-flight startup once stop() was requested.
|
|
414
|
+
*
|
|
415
|
+
* Checked after every await in the startup path: the resources created so
|
|
416
|
+
* far are all assigned to instance fields, so the stop() that is waiting on
|
|
417
|
+
* this startup tears them down the moment it unwinds.
|
|
418
|
+
*
|
|
419
|
+
* @throws {Error} If stop() was called while starting
|
|
420
|
+
*
|
|
421
|
+
* @internal
|
|
422
|
+
*/
|
|
423
|
+
private throwIfStopRequested;
|
|
424
|
+
/**
|
|
425
|
+
* Cap the video bitrate on the encoder context.
|
|
426
|
+
*
|
|
427
|
+
* Applies a VBV rate cap (maxrate + a 1s buffer) WITHOUT setting a target
|
|
428
|
+
* bitrate, so the encoder keeps its default constant-quality mode but can
|
|
429
|
+
* never exceed the negotiated ceiling. Setting the bitrate as an ABR target
|
|
430
|
+
* instead would push a normally-lighter stream UP to fill it, overshooting on
|
|
431
|
+
* bursts - the opposite of what strict rate-capped consumers want.
|
|
432
|
+
* No-op when no bitrate was requested.
|
|
433
|
+
*
|
|
434
|
+
* @param ctx - Encoder codec context
|
|
435
|
+
*
|
|
436
|
+
* @param bitrate - Maximum bitrate in bits per second, or undefined
|
|
437
|
+
*
|
|
438
|
+
* @internal
|
|
439
|
+
*/
|
|
440
|
+
private applyBitrate;
|
|
337
441
|
/**
|
|
338
442
|
* Create the fMP4 output muxer with the fragment-emitting write callback.
|
|
339
443
|
*
|
|
@@ -356,6 +460,16 @@ export declare class FMP4Stream {
|
|
|
356
460
|
* @internal
|
|
357
461
|
*/
|
|
358
462
|
private attachCompletion;
|
|
463
|
+
/**
|
|
464
|
+
* Whether a pipeline rejection was caused by an intentional shutdown.
|
|
465
|
+
*
|
|
466
|
+
* @param error - The pipeline rejection reason
|
|
467
|
+
*
|
|
468
|
+
* @returns True when stop() is in flight or the owner's signal aborted
|
|
469
|
+
*
|
|
470
|
+
* @internal
|
|
471
|
+
*/
|
|
472
|
+
private isDeliberateStop;
|
|
359
473
|
/**
|
|
360
474
|
* Set up encoders and the fMP4 muxer for a pre-composited frame source and
|
|
361
475
|
* start encoding. No demuxer or decoder is involved - the provided frames are
|
|
@@ -388,6 +502,12 @@ export declare class FMP4Stream {
|
|
|
388
502
|
* ```
|
|
389
503
|
*/
|
|
390
504
|
stop(): Promise<void>;
|
|
505
|
+
/**
|
|
506
|
+
* Perform the actual teardown (see {@link stop}).
|
|
507
|
+
*
|
|
508
|
+
* @internal
|
|
509
|
+
*/
|
|
510
|
+
private doStop;
|
|
391
511
|
/**
|
|
392
512
|
* Async generator that yields media fragments (moof+mdat chunks).
|
|
393
513
|
*
|
|
@@ -399,8 +519,16 @@ export declare class FMP4Stream {
|
|
|
399
519
|
*
|
|
400
520
|
* The generator completes when the stream stops or the pipeline ends.
|
|
401
521
|
*
|
|
522
|
+
* Only a single consumer is supported: a second concurrent fragments() call
|
|
523
|
+
* would silently strand the first consumer, so it throws instead. The
|
|
524
|
+
* backlog is bounded by `maxQueuedFragments` - if the consumer falls behind
|
|
525
|
+
* a live source, the oldest fragments are dropped (see
|
|
526
|
+
* {@link droppedFragments}).
|
|
527
|
+
*
|
|
402
528
|
* @yields {FMP4Fragment} Media fragment with data buffer and box info
|
|
403
529
|
*
|
|
530
|
+
* @throws {Error} If another fragments() iterator is already active
|
|
531
|
+
*
|
|
404
532
|
* @example
|
|
405
533
|
* ```typescript
|
|
406
534
|
* const stream = FMP4Stream.create('rtsp://camera/stream', {
|
|
@@ -446,11 +574,35 @@ export declare class FMP4Stream {
|
|
|
446
574
|
/**
|
|
447
575
|
* Process buffer in box mode - buffers until complete boxes are available.
|
|
448
576
|
*
|
|
577
|
+
* The muxer splits writes at arbitrary positions, so a chunk may end
|
|
578
|
+
* anywhere - including inside a box header. Any trailing partial box
|
|
579
|
+
* (header or body) is buffered for the next chunk; the parser never
|
|
580
|
+
* loses bytes regardless of where the split falls.
|
|
581
|
+
*
|
|
582
|
+
* Emission is fragment-aligned: a `moof` is held back until its `mdat` has
|
|
583
|
+
* arrived, then both are emitted as ONE onData call. The avio buffer flushes
|
|
584
|
+
* at arbitrary points (a fragment larger than the buffer always splits), so
|
|
585
|
+
* without this a consumer would see a bare `moof` followed by a detached
|
|
586
|
+
* `mdat` - unplayable framing for fMP4 consumers.
|
|
587
|
+
* Non-fragment boxes (ftyp, moov, mfra, ...) are emitted as they complete.
|
|
588
|
+
*
|
|
449
589
|
* @param chunk - Incoming data chunk from FFmpeg
|
|
450
590
|
*
|
|
451
591
|
* @internal
|
|
452
592
|
*/
|
|
453
593
|
private processBoxMode;
|
|
594
|
+
/**
|
|
595
|
+
* Emit a group of complete boxes as one onData call.
|
|
596
|
+
*
|
|
597
|
+
* Concatenates the raw box bytes, rebuilds the box list with offsets
|
|
598
|
+
* relative to the emitted buffer, tracks the init segment, and feeds the
|
|
599
|
+
* fragments() queue when the group is a media fragment.
|
|
600
|
+
*
|
|
601
|
+
* @param entries - Complete boxes in stream order
|
|
602
|
+
*
|
|
603
|
+
* @internal
|
|
604
|
+
*/
|
|
605
|
+
private emitBoxGroup;
|
|
454
606
|
/**
|
|
455
607
|
* Push a fragment to the fragment queue for the async generator.
|
|
456
608
|
*
|
|
@@ -461,6 +613,18 @@ export declare class FMP4Stream {
|
|
|
461
613
|
* @internal
|
|
462
614
|
*/
|
|
463
615
|
private pushFragment;
|
|
616
|
+
/**
|
|
617
|
+
* Reject a pending initSegment promise so consumers never hang.
|
|
618
|
+
*
|
|
619
|
+
* No-op when the promise was never requested or has already settled. The
|
|
620
|
+
* promise is marked as handled to avoid an unhandled rejection when no
|
|
621
|
+
* consumer is currently awaiting it.
|
|
622
|
+
*
|
|
623
|
+
* @param error - Rejection reason (pipeline error or stop-before-init)
|
|
624
|
+
*
|
|
625
|
+
* @internal
|
|
626
|
+
*/
|
|
627
|
+
private rejectInitSegment;
|
|
464
628
|
/**
|
|
465
629
|
* Signal the fragment queue that no more fragments will arrive.
|
|
466
630
|
*
|