node-av 6.2.0-beta.3 → 6.2.0-beta.30
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 +438 -7
- package/dist/api/audio-frame-buffer.js +792 -52
- 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 +29 -4
- package/dist/api/demuxer.js +209 -60
- 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 +58 -2
- package/dist/api/encoder.js +173 -57
- 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 +327 -8
- package/dist/api/fmp4-stream.js +663 -123
- 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/index.d.ts +2 -2
- package/dist/api/index.js.map +1 -1
- package/dist/api/io-stream.d.ts +3 -2
- package/dist/api/io-stream.js +76 -5
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/muxer.d.ts +289 -7
- package/dist/api/muxer.js +696 -109
- 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 +77 -8
- package/dist/api/rtp-stream.js +316 -88
- package/dist/api/rtp-stream.js.map +1 -1
- package/dist/api/scaler.d.ts +124 -21
- package/dist/api/scaler.js +347 -114
- 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/utilities/packet-age-watchdog.d.ts +198 -0
- package/dist/api/utilities/packet-age-watchdog.js +594 -0
- package/dist/api/utilities/packet-age-watchdog.js.map +1 -0
- 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 +104 -26
- 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 +10 -1
- package/dist/lib/binding.js +25 -16
- package/dist/lib/binding.js.map +1 -1
- package/dist/lib/bitstream-filter-context.d.ts +2 -0
- package/dist/lib/bitstream-filter-context.js +2 -0
- package/dist/lib/bitstream-filter-context.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 +70 -7
- package/dist/lib/format-context.js +77 -21
- package/dist/lib/format-context.js.map +1 -1
- package/dist/lib/frame.d.ts +17 -13
- package/dist/lib/frame.js +24 -23
- 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 +7 -5
- 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 +8 -4
- package/dist/lib/stream.js +22 -24
- package/dist/lib/stream.js.map +1 -1
- package/install/check.js +40 -79
- package/package.json +45 -34
- 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;
|
|
@@ -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;
|
|
@@ -66,12 +72,56 @@ export interface FMP4StreamOptions {
|
|
|
66
72
|
supportedCodecs?: string;
|
|
67
73
|
/**
|
|
68
74
|
* Fragment duration in microseconds.
|
|
75
|
+
*
|
|
76
|
+
* Passed to the mp4 muxer as `frag_duration`, which creates a new fragment
|
|
77
|
+
* whenever the current one exceeds this duration (in addition to any cuts
|
|
78
|
+
* requested via movFlags such as `frag_keyframe`).
|
|
69
79
|
* Smaller values reduce latency but increase overhead.
|
|
70
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.
|
|
71
84
|
*
|
|
72
85
|
* @default 1
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const stream = FMP4Stream.create('rtsp://camera.local/stream', {
|
|
90
|
+
* supportedCodecs: 'avc1.640029,mp4a.40.2',
|
|
91
|
+
* fragDuration: 2_000_000, // 2 seconds in microseconds
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
73
94
|
*/
|
|
74
95
|
fragDuration?: number;
|
|
96
|
+
/**
|
|
97
|
+
* Maximum number of media fragments buffered for a {@link FMP4Stream.fragments}
|
|
98
|
+
* consumer before the oldest are dropped.
|
|
99
|
+
*
|
|
100
|
+
* Live sources (RTSP cameras) produce fragments at a fixed rate regardless of
|
|
101
|
+
* consumer speed. Without a bound, a slow or stalled consumer would grow the
|
|
102
|
+
* queue until the process runs out of memory. When the backlog exceeds this
|
|
103
|
+
* limit, the oldest media fragments are dropped (never the init segment,
|
|
104
|
+
* which is kept separately via {@link FMP4Stream.initSegment}) and
|
|
105
|
+
* {@link FMP4Stream.droppedFragments} is incremented.
|
|
106
|
+
*
|
|
107
|
+
* @default 16
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const stream = FMP4Stream.create('rtsp://camera.local/stream', {
|
|
112
|
+
* supportedCodecs: 'avc1.640029,mp4a.40.2',
|
|
113
|
+
* boxMode: true,
|
|
114
|
+
* maxQueuedFragments: 8,
|
|
115
|
+
* });
|
|
116
|
+
*
|
|
117
|
+
* await stream.start();
|
|
118
|
+
* for await (const fragment of stream.fragments()) {
|
|
119
|
+
* await sendToClient(fragment.data); // Slow consumer - oldest fragments dropped
|
|
120
|
+
* }
|
|
121
|
+
* console.log(`Dropped ${stream.droppedFragments} fragments`);
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
maxQueuedFragments?: number;
|
|
75
125
|
/**
|
|
76
126
|
* Hardware acceleration configuration for video transcoding.
|
|
77
127
|
*
|
|
@@ -96,6 +146,11 @@ export interface FMP4StreamOptions {
|
|
|
96
146
|
fps?: number;
|
|
97
147
|
width?: number;
|
|
98
148
|
height?: number;
|
|
149
|
+
bitrate?: number;
|
|
150
|
+
/**
|
|
151
|
+
* FourCC sample entry tag for the HEVC video stream, e.g. `hvc1`. Only applied to HEVC output.
|
|
152
|
+
*/
|
|
153
|
+
tag?: string;
|
|
99
154
|
encoderOptions?: EncoderOptions['options'];
|
|
100
155
|
};
|
|
101
156
|
/**
|
|
@@ -112,7 +167,10 @@ export interface FMP4StreamOptions {
|
|
|
112
167
|
bufferSize?: number;
|
|
113
168
|
/**
|
|
114
169
|
* Enable box mode - buffers data until complete MP4 boxes are available.
|
|
115
|
-
* When true, onData receives complete boxes with parsed box information
|
|
170
|
+
* When true, onData receives complete boxes with parsed box information,
|
|
171
|
+
* and media fragments are emitted fragment-aligned: a callback that contains
|
|
172
|
+
* a `moof` always contains its `mdat` too, regardless of how the muxer's
|
|
173
|
+
* I/O buffer split the write (large fragments arrive in several chunks).
|
|
116
174
|
* When false, onData receives raw chunks as they arrive from FFmpeg.
|
|
117
175
|
*
|
|
118
176
|
* @default false
|
|
@@ -124,6 +182,60 @@ export interface FMP4StreamOptions {
|
|
|
124
182
|
* @default '+frag_keyframe+separate_moof+default_base_moof+empty_moov'
|
|
125
183
|
*/
|
|
126
184
|
movFlags?: string;
|
|
185
|
+
/**
|
|
186
|
+
* Backward DTS jump in seconds above which the stream ends with an error.
|
|
187
|
+
*
|
|
188
|
+
* A live source that restarts its clock (a camera reboot behind a restreamer)
|
|
189
|
+
* would otherwise leave every following packet clamped to one tick past the
|
|
190
|
+
* previous one, so fragments carry no media for as long as the jump. The stream
|
|
191
|
+
* instead stops and reports the error through `onClose(error)`, and the owner
|
|
192
|
+
* can restart it on a fresh timeline. Smaller jumps are clamped. `0` disables
|
|
193
|
+
* the check. Same semantics as the `Muxer` option of the same name.
|
|
194
|
+
*
|
|
195
|
+
* @default 10
|
|
196
|
+
*/
|
|
197
|
+
dtsBackwardThreshold?: number;
|
|
198
|
+
/**
|
|
199
|
+
* Forward DTS jump in seconds, beyond the real time that passed, above which
|
|
200
|
+
* the stream ends with an error.
|
|
201
|
+
*
|
|
202
|
+
* A live source that restarts its clock (a camera reboot behind a
|
|
203
|
+
* restreamer) can continue with timestamps far ahead of the time that
|
|
204
|
+
* passed. Muxing that would leave a sample spanning the jump, or, when the
|
|
205
|
+
* timeline later returns, a stream clamped behind it. The stream instead
|
|
206
|
+
* stops and reports the error through `onClose(error)`, and the owner can
|
|
207
|
+
* restart it on a fresh timeline. Gaps in the source come with a matching
|
|
208
|
+
* wait and pass. Only meaningful for inputs read in real time, so it is off
|
|
209
|
+
* for files, a pre-opened Demuxer and frame sources unless set; pass it for
|
|
210
|
+
* live inputs read over HTTP (HLS, HTTP-FLV) as well. Same semantics as the
|
|
211
|
+
* `Muxer` option of the same name; `0` disables the check.
|
|
212
|
+
*
|
|
213
|
+
* @default 10 for rtsp, rtsps, rtmp (and rtmps, rtmpt, rtmpe, rtmpte, rtmpts), rtp, srtp, udp, srt, tcp, tls and sctp URLs, 0 otherwise
|
|
214
|
+
*/
|
|
215
|
+
dtsForwardThreshold?: number;
|
|
216
|
+
/**
|
|
217
|
+
* Longest time in seconds a packet may wait inside the muxer before it is
|
|
218
|
+
* emitted in a fragment.
|
|
219
|
+
*
|
|
220
|
+
* The mp4 muxer holds packets back to interleave the streams by timestamp.
|
|
221
|
+
* When a stream's timestamps stop advancing or run far ahead of a silent
|
|
222
|
+
* stream (a camera restarting its clock behind a restreamer, missing
|
|
223
|
+
* timestamps), packets can pile up without ever being emitted while memory
|
|
224
|
+
* grows. The age is measured per stream in real time while the input
|
|
225
|
+
* delivers packets and is independent of the timestamps; once the oldest
|
|
226
|
+
* pending packet of any stream is older than this, the stream stops and
|
|
227
|
+
* reports the error through `onClose(error)`. A pause of the whole input
|
|
228
|
+
* counts at most 2 s, so a source that goes quiet and resumes does not end
|
|
229
|
+
* the session. Healthy sessions stay below the default: up to the fragment
|
|
230
|
+
* duration (the GOP length with `fragDuration: 0`) plus about 10 s of
|
|
231
|
+
* interleaving delay while a stream is silent. Inputs read faster than real
|
|
232
|
+
* time can pile up correspondingly more media before it fires, inputs that
|
|
233
|
+
* deliver packets more than 2 s apart take correspondingly longer. `0`
|
|
234
|
+
* disables the check.
|
|
235
|
+
*
|
|
236
|
+
* @default 60
|
|
237
|
+
*/
|
|
238
|
+
maxPacketAge?: number;
|
|
127
239
|
/**
|
|
128
240
|
* AbortSignal for cancellation.
|
|
129
241
|
*
|
|
@@ -132,6 +244,19 @@ export interface FMP4StreamOptions {
|
|
|
132
244
|
*/
|
|
133
245
|
signal?: AbortSignal;
|
|
134
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Video description of the muxed fMP4 output.
|
|
249
|
+
*/
|
|
250
|
+
export interface FMP4VideoInfo {
|
|
251
|
+
/** Output codec family. */
|
|
252
|
+
codec: 'h264' | 'hevc' | 'av1' | 'unknown';
|
|
253
|
+
/** RFC 6381 codec string of the output (e.g. `hvc1.1.6.L120.B0`). */
|
|
254
|
+
codecString: string;
|
|
255
|
+
width: number;
|
|
256
|
+
height: number;
|
|
257
|
+
/** Frames per second, 0 when unknown. */
|
|
258
|
+
fps: number;
|
|
259
|
+
}
|
|
135
260
|
/**
|
|
136
261
|
* Target codec strings for fMP4 streaming.
|
|
137
262
|
*/
|
|
@@ -147,7 +272,8 @@ export declare const FMP4_CODECS: {
|
|
|
147
272
|
* High-level fMP4 streaming with automatic codec detection and transcoding.
|
|
148
273
|
*
|
|
149
274
|
* Provides fragmented MP4 streaming for clients.
|
|
150
|
-
* Automatically transcodes video to H.264 and audio to AAC
|
|
275
|
+
* Automatically transcodes video to H.264 and audio to AAC (Opus when the client
|
|
276
|
+
* lists Opus but not AAC) if not supported by client.
|
|
151
277
|
* Client sends supported codecs, server transcodes accordingly.
|
|
152
278
|
* Essential component for building adaptive streaming servers.
|
|
153
279
|
*
|
|
@@ -204,9 +330,19 @@ export declare class FMP4Stream {
|
|
|
204
330
|
private signal?;
|
|
205
331
|
private supportedCodecs;
|
|
206
332
|
private incompleteBoxBuffer;
|
|
333
|
+
private pendingFragment;
|
|
334
|
+
private abortHandler?;
|
|
335
|
+
private stopRequested;
|
|
336
|
+
private discardOutput;
|
|
337
|
+
private stopPromise?;
|
|
338
|
+
private startAbort?;
|
|
339
|
+
private stopSignal;
|
|
207
340
|
private fragmentQueue;
|
|
341
|
+
private packetAgeWatchdog?;
|
|
342
|
+
private _droppedFragments;
|
|
208
343
|
private _initSegment;
|
|
209
344
|
private _initSegmentResolve;
|
|
345
|
+
private _initSegmentReject;
|
|
210
346
|
private _initSegmentPromise;
|
|
211
347
|
private _ftypData;
|
|
212
348
|
private _moovData;
|
|
@@ -217,6 +353,8 @@ export declare class FMP4Stream {
|
|
|
217
353
|
*
|
|
218
354
|
* Use {@link create} factory method
|
|
219
355
|
*
|
|
356
|
+
* @throws {RangeError} If dtsBackwardThreshold, dtsForwardThreshold or maxPacketAge is not a finite number >= 0
|
|
357
|
+
*
|
|
220
358
|
* @internal
|
|
221
359
|
*/
|
|
222
360
|
private constructor();
|
|
@@ -232,6 +370,8 @@ export declare class FMP4Stream {
|
|
|
232
370
|
*
|
|
233
371
|
* @returns Configured fMP4 stream instance
|
|
234
372
|
*
|
|
373
|
+
* @throws {RangeError} If dtsBackwardThreshold, dtsForwardThreshold or maxPacketAge is not a finite number >= 0
|
|
374
|
+
*
|
|
235
375
|
* @example
|
|
236
376
|
* ```typescript
|
|
237
377
|
* // Stream from file with codec negotiation
|
|
@@ -257,10 +397,32 @@ export declare class FMP4Stream {
|
|
|
257
397
|
*
|
|
258
398
|
* Only available when boxMode is enabled.
|
|
259
399
|
* Resolves once the first ftyp and moov boxes have been received.
|
|
400
|
+
* Rejects if the stream fails or is stopped before the init segment
|
|
401
|
+
* was produced, so awaiting it never hangs.
|
|
260
402
|
*
|
|
261
403
|
* @throws {Error} If boxMode is not enabled
|
|
262
404
|
*/
|
|
263
405
|
get initSegment(): Promise<Buffer>;
|
|
406
|
+
/**
|
|
407
|
+
* Number of media fragments dropped due to consumer backpressure.
|
|
408
|
+
*
|
|
409
|
+
* Incremented whenever the {@link fragments} backlog exceeds
|
|
410
|
+
* `maxQueuedFragments` and the oldest fragment is discarded.
|
|
411
|
+
* Reset to 0 when the stream is (re)started.
|
|
412
|
+
*
|
|
413
|
+
* @returns Total dropped fragments for the current run
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```typescript
|
|
417
|
+
* for await (const fragment of stream.fragments()) {
|
|
418
|
+
* await sendToClient(fragment.data);
|
|
419
|
+
* if (stream.droppedFragments > 0) {
|
|
420
|
+
* console.warn(`Consumer too slow: ${stream.droppedFragments} fragments dropped`);
|
|
421
|
+
* }
|
|
422
|
+
* }
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
425
|
+
get droppedFragments(): number;
|
|
264
426
|
/**
|
|
265
427
|
* Get the demuxer instance.
|
|
266
428
|
*
|
|
@@ -300,13 +462,29 @@ export declare class FMP4Stream {
|
|
|
300
462
|
* ```
|
|
301
463
|
*/
|
|
302
464
|
getCodecString(): string;
|
|
465
|
+
/**
|
|
466
|
+
* Video description of the muxed fMP4 output (output codec, RFC 6381 codec string, resolution, fps).
|
|
467
|
+
*
|
|
468
|
+
* Available after {@link start} has opened the input.
|
|
469
|
+
*
|
|
470
|
+
* @returns The output video info, or `undefined` when there is no video track.
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* ```typescript
|
|
474
|
+
* const videoInfo = stream.getVideoInfo();
|
|
475
|
+
* if (videoInfo) {
|
|
476
|
+
* console.log(`Codec: ${videoInfo.codec}, Resolution: ${videoInfo.width}x${videoInfo.height}, FPS: ${videoInfo.fps}`);
|
|
477
|
+
* }
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
480
|
+
getVideoInfo(): FMP4VideoInfo | undefined;
|
|
303
481
|
/**
|
|
304
482
|
* Start streaming media to fMP4 chunks.
|
|
305
483
|
*
|
|
306
484
|
* Begins the media processing pipeline, reading packets from input,
|
|
307
485
|
* transcoding based on supported codecs, and generating fMP4 chunks.
|
|
308
486
|
* Video transcodes to H.264 if H.264/H.265 not supported.
|
|
309
|
-
* Audio transcodes to AAC
|
|
487
|
+
* Audio transcodes to AAC (Opus when only Opus is listed) if the input codec is not supported.
|
|
310
488
|
* This method returns immediately after starting the pipeline.
|
|
311
489
|
*
|
|
312
490
|
* @returns Promise that resolves when pipeline is started
|
|
@@ -334,11 +512,57 @@ export declare class FMP4Stream {
|
|
|
334
512
|
* @internal
|
|
335
513
|
*/
|
|
336
514
|
private doStart;
|
|
515
|
+
/**
|
|
516
|
+
* Abort an in-flight startup once stop() was requested.
|
|
517
|
+
*
|
|
518
|
+
* Checked after every await in the startup path: the resources created so
|
|
519
|
+
* far are all assigned to instance fields, so the stop() that is waiting on
|
|
520
|
+
* this startup tears them down the moment it unwinds.
|
|
521
|
+
*
|
|
522
|
+
* @throws {Error} If stop() was called while starting
|
|
523
|
+
*
|
|
524
|
+
* @internal
|
|
525
|
+
*/
|
|
526
|
+
private throwIfStopRequested;
|
|
527
|
+
/**
|
|
528
|
+
* Cap the video bitrate on the encoder context.
|
|
529
|
+
*
|
|
530
|
+
* Applies a VBV rate cap (maxrate + a 1s buffer) WITHOUT setting a target
|
|
531
|
+
* bitrate, so the encoder keeps its default constant-quality mode but can
|
|
532
|
+
* never exceed the negotiated ceiling. Setting the bitrate as an ABR target
|
|
533
|
+
* instead would push a normally-lighter stream UP to fill it, overshooting on
|
|
534
|
+
* bursts - the opposite of what strict rate-capped consumers want.
|
|
535
|
+
* No-op when no bitrate was requested.
|
|
536
|
+
*
|
|
537
|
+
* @param ctx - Encoder codec context
|
|
538
|
+
*
|
|
539
|
+
* @param bitrate - Maximum bitrate in bits per second, or undefined
|
|
540
|
+
*
|
|
541
|
+
* @internal
|
|
542
|
+
*/
|
|
543
|
+
private applyBitrate;
|
|
544
|
+
/**
|
|
545
|
+
* GOP size for the video encoder that starts every fragment with a keyframe.
|
|
546
|
+
*
|
|
547
|
+
* frag_duration flushes a fragment once it is that long, mid-GOP on a
|
|
548
|
+
* P-frame unless the GOP has the same length, and strict consumers reject
|
|
549
|
+
* such fragments. Shorter fragments (the 1 µs default flushes after every
|
|
550
|
+
* frame) are not matched: a GOP of a few frames multiplies the bitrate, so
|
|
551
|
+
* below MIN_FRAGMENT_GOP the GOP is 2 s, as with a fragDuration of 0.
|
|
552
|
+
*
|
|
553
|
+
* @param fps - Output frame rate
|
|
554
|
+
*
|
|
555
|
+
* @returns GOP size in frames
|
|
556
|
+
*
|
|
557
|
+
* @internal
|
|
558
|
+
*/
|
|
559
|
+
private gopSize;
|
|
337
560
|
/**
|
|
338
561
|
* Create the fMP4 output muxer with the fragment-emitting write callback.
|
|
339
562
|
*
|
|
340
563
|
* Uses `this.input` when present (demuxer path) and no input for the
|
|
341
|
-
* frame-source path.
|
|
564
|
+
* frame-source path. Attaches a fresh packet age watchdog unless
|
|
565
|
+
* `maxPacketAge` is 0.
|
|
342
566
|
*
|
|
343
567
|
* @returns The configured muxer
|
|
344
568
|
*
|
|
@@ -349,13 +573,36 @@ export declare class FMP4Stream {
|
|
|
349
573
|
* Wire the pipeline completion to the fragment/close callbacks.
|
|
350
574
|
*
|
|
351
575
|
* On success ends the fragment iterator and invokes `onClose()`; on error
|
|
352
|
-
* stops the stream
|
|
576
|
+
* stops the stream, discarding the output the muxer still holds, and invokes
|
|
577
|
+
* `onClose(error)`. Either way `onClose` runs exactly once and the detached
|
|
578
|
+
* chain never rejects. Runs in the background.
|
|
353
579
|
*
|
|
354
580
|
* @param completion - The pipeline completion promise
|
|
355
581
|
*
|
|
356
582
|
* @internal
|
|
357
583
|
*/
|
|
358
584
|
private attachCompletion;
|
|
585
|
+
/**
|
|
586
|
+
* Invoke the owner's onClose callback.
|
|
587
|
+
*
|
|
588
|
+
* The completion chain runs detached, so an exception from the callback
|
|
589
|
+
* could only surface as an unhandled rejection - it is logged instead.
|
|
590
|
+
*
|
|
591
|
+
* @param error - Pipeline error, or undefined for a clean end
|
|
592
|
+
*
|
|
593
|
+
* @internal
|
|
594
|
+
*/
|
|
595
|
+
private emitClose;
|
|
596
|
+
/**
|
|
597
|
+
* Whether a pipeline rejection was caused by an intentional shutdown.
|
|
598
|
+
*
|
|
599
|
+
* @param error - The pipeline rejection reason
|
|
600
|
+
*
|
|
601
|
+
* @returns True when stop() is in flight or the owner's signal aborted
|
|
602
|
+
*
|
|
603
|
+
* @internal
|
|
604
|
+
*/
|
|
605
|
+
private isDeliberateStop;
|
|
359
606
|
/**
|
|
360
607
|
* Set up encoders and the fMP4 muxer for a pre-composited frame source and
|
|
361
608
|
* start encoding. No demuxer or decoder is involved - the provided frames are
|
|
@@ -374,7 +621,8 @@ export declare class FMP4Stream {
|
|
|
374
621
|
*
|
|
375
622
|
* Stops the pipeline, closes output, and releases all FFmpeg resources.
|
|
376
623
|
* Safe to call multiple times. After stopping, you can call start() again
|
|
377
|
-
* to restart the stream.
|
|
624
|
+
* to restart the stream. Resolves even if the pipeline had failed; that
|
|
625
|
+
* error is reported through `onClose(error)`.
|
|
378
626
|
*
|
|
379
627
|
* @example
|
|
380
628
|
* ```typescript
|
|
@@ -388,6 +636,12 @@ export declare class FMP4Stream {
|
|
|
388
636
|
* ```
|
|
389
637
|
*/
|
|
390
638
|
stop(): Promise<void>;
|
|
639
|
+
/**
|
|
640
|
+
* Perform the actual teardown (see {@link stop}).
|
|
641
|
+
*
|
|
642
|
+
* @internal
|
|
643
|
+
*/
|
|
644
|
+
private doStop;
|
|
391
645
|
/**
|
|
392
646
|
* Async generator that yields media fragments (moof+mdat chunks).
|
|
393
647
|
*
|
|
@@ -399,8 +653,16 @@ export declare class FMP4Stream {
|
|
|
399
653
|
*
|
|
400
654
|
* The generator completes when the stream stops or the pipeline ends.
|
|
401
655
|
*
|
|
656
|
+
* Only a single consumer is supported: a second concurrent fragments() call
|
|
657
|
+
* would silently strand the first consumer, so it throws instead. The
|
|
658
|
+
* backlog is bounded by `maxQueuedFragments` - if the consumer falls behind
|
|
659
|
+
* a live source, the oldest fragments are dropped (see
|
|
660
|
+
* {@link droppedFragments}).
|
|
661
|
+
*
|
|
402
662
|
* @yields {FMP4Fragment} Media fragment with data buffer and box info
|
|
403
663
|
*
|
|
664
|
+
* @throws {Error} If another fragments() iterator is already active
|
|
665
|
+
*
|
|
404
666
|
* @example
|
|
405
667
|
* ```typescript
|
|
406
668
|
* const stream = FMP4Stream.create('rtsp://camera/stream', {
|
|
@@ -433,6 +695,27 @@ export declare class FMP4Stream {
|
|
|
433
695
|
* @internal
|
|
434
696
|
*/
|
|
435
697
|
private isVideoCodecSupported;
|
|
698
|
+
/**
|
|
699
|
+
* Codec that unsupported audio is transcoded to.
|
|
700
|
+
*
|
|
701
|
+
* @returns Opus when the client lists Opus but not AAC, otherwise AAC
|
|
702
|
+
*
|
|
703
|
+
* @internal
|
|
704
|
+
*/
|
|
705
|
+
private audioTranscodeTarget;
|
|
706
|
+
/**
|
|
707
|
+
* Create the audio filter and encoder for the transcode target.
|
|
708
|
+
*
|
|
709
|
+
* AAC is resampled to 44.1 kHz stereo. Opus is resampled to 48 kHz, the only
|
|
710
|
+
* rate it transmits, keeps mono input mono and uses 20 ms frames.
|
|
711
|
+
*
|
|
712
|
+
* @param decoder - Input audio decoder, absent for a frame source
|
|
713
|
+
*
|
|
714
|
+
* @param channels - Input channel count, 0 when unknown
|
|
715
|
+
*
|
|
716
|
+
* @internal
|
|
717
|
+
*/
|
|
718
|
+
private createAudioEncoder;
|
|
436
719
|
/**
|
|
437
720
|
* Check if audio codec is supported.
|
|
438
721
|
*
|
|
@@ -446,11 +729,35 @@ export declare class FMP4Stream {
|
|
|
446
729
|
/**
|
|
447
730
|
* Process buffer in box mode - buffers until complete boxes are available.
|
|
448
731
|
*
|
|
732
|
+
* The muxer splits writes at arbitrary positions, so a chunk may end
|
|
733
|
+
* anywhere - including inside a box header. Any trailing partial box
|
|
734
|
+
* (header or body) is buffered for the next chunk; the parser never
|
|
735
|
+
* loses bytes regardless of where the split falls.
|
|
736
|
+
*
|
|
737
|
+
* Emission is fragment-aligned: a `moof` is held back until its `mdat` has
|
|
738
|
+
* arrived, then both are emitted as ONE onData call. The avio buffer flushes
|
|
739
|
+
* at arbitrary points (a fragment larger than the buffer always splits), so
|
|
740
|
+
* without this a consumer would see a bare `moof` followed by a detached
|
|
741
|
+
* `mdat` - unplayable framing for fMP4 consumers.
|
|
742
|
+
* Non-fragment boxes (ftyp, moov, mfra, ...) are emitted as they complete.
|
|
743
|
+
*
|
|
449
744
|
* @param chunk - Incoming data chunk from FFmpeg
|
|
450
745
|
*
|
|
451
746
|
* @internal
|
|
452
747
|
*/
|
|
453
748
|
private processBoxMode;
|
|
749
|
+
/**
|
|
750
|
+
* Emit a group of complete boxes as one onData call.
|
|
751
|
+
*
|
|
752
|
+
* Concatenates the raw box bytes, rebuilds the box list with offsets
|
|
753
|
+
* relative to the emitted buffer, tracks the init segment, and feeds the
|
|
754
|
+
* fragments() queue when the group is a media fragment.
|
|
755
|
+
*
|
|
756
|
+
* @param entries - Complete boxes in stream order
|
|
757
|
+
*
|
|
758
|
+
* @internal
|
|
759
|
+
*/
|
|
760
|
+
private emitBoxGroup;
|
|
454
761
|
/**
|
|
455
762
|
* Push a fragment to the fragment queue for the async generator.
|
|
456
763
|
*
|
|
@@ -461,6 +768,18 @@ export declare class FMP4Stream {
|
|
|
461
768
|
* @internal
|
|
462
769
|
*/
|
|
463
770
|
private pushFragment;
|
|
771
|
+
/**
|
|
772
|
+
* Reject a pending initSegment promise so consumers never hang.
|
|
773
|
+
*
|
|
774
|
+
* No-op when the promise was never requested or has already settled. The
|
|
775
|
+
* promise is marked as handled to avoid an unhandled rejection when no
|
|
776
|
+
* consumer is currently awaiting it.
|
|
777
|
+
*
|
|
778
|
+
* @param error - Rejection reason (pipeline error or stop-before-init)
|
|
779
|
+
*
|
|
780
|
+
* @internal
|
|
781
|
+
*/
|
|
782
|
+
private rejectInitSegment;
|
|
464
783
|
/**
|
|
465
784
|
* Signal the fragment queue that no more fragments will arrive.
|
|
466
785
|
*
|