node-av 3.1.2 → 4.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.
- package/README.md +65 -52
- package/binding.gyp +4 -0
- package/dist/api/audio-frame-buffer.d.ts +201 -0
- package/dist/api/audio-frame-buffer.js +275 -0
- package/dist/api/audio-frame-buffer.js.map +1 -0
- package/dist/api/bitstream-filter.d.ts +319 -78
- package/dist/api/bitstream-filter.js +680 -151
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/constants.d.ts +44 -0
- package/dist/api/constants.js +45 -0
- package/dist/api/constants.js.map +1 -0
- package/dist/api/data/test_av1.ivf +0 -0
- package/dist/api/data/test_mjpeg.mjpeg +0 -0
- package/dist/api/data/test_vp8.ivf +0 -0
- package/dist/api/data/test_vp9.ivf +0 -0
- package/dist/api/decoder.d.ts +279 -17
- package/dist/api/decoder.js +998 -209
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/{media-input.d.ts → demuxer.d.ts} +294 -44
- package/dist/api/demuxer.js +1968 -0
- package/dist/api/demuxer.js.map +1 -0
- package/dist/api/encoder.d.ts +308 -50
- package/dist/api/encoder.js +1133 -111
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter-presets.d.ts +12 -5
- package/dist/api/filter-presets.js +21 -7
- package/dist/api/filter-presets.js.map +1 -1
- package/dist/api/filter.d.ts +406 -40
- package/dist/api/filter.js +966 -139
- package/dist/api/filter.js.map +1 -1
- package/dist/api/{fmp4.d.ts → fmp4-stream.d.ts} +141 -140
- package/dist/api/fmp4-stream.js +539 -0
- package/dist/api/fmp4-stream.js.map +1 -0
- package/dist/api/hardware.d.ts +58 -6
- package/dist/api/hardware.js +127 -11
- package/dist/api/hardware.js.map +1 -1
- package/dist/api/index.d.ts +6 -4
- package/dist/api/index.js +14 -8
- package/dist/api/index.js.map +1 -1
- package/dist/api/io-stream.d.ts +3 -3
- package/dist/api/io-stream.js +5 -4
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/{media-output.d.ts → muxer.d.ts} +274 -60
- package/dist/api/muxer.js +1934 -0
- package/dist/api/muxer.js.map +1 -0
- package/dist/api/pipeline.d.ts +77 -29
- package/dist/api/pipeline.js +435 -425
- package/dist/api/pipeline.js.map +1 -1
- package/dist/api/rtp-stream.d.ts +312 -0
- package/dist/api/rtp-stream.js +630 -0
- package/dist/api/rtp-stream.js.map +1 -0
- package/dist/api/types.d.ts +476 -55
- package/dist/api/utilities/async-queue.d.ts +91 -0
- package/dist/api/utilities/async-queue.js +162 -0
- package/dist/api/utilities/async-queue.js.map +1 -0
- package/dist/api/utilities/audio-sample.d.ts +1 -1
- package/dist/api/utilities/image.d.ts +1 -1
- package/dist/api/utilities/index.d.ts +2 -0
- package/dist/api/utilities/index.js +4 -0
- package/dist/api/utilities/index.js.map +1 -1
- package/dist/api/utilities/media-type.d.ts +1 -1
- package/dist/api/utilities/pixel-format.d.ts +1 -1
- package/dist/api/utilities/sample-format.d.ts +1 -1
- package/dist/api/utilities/scheduler.d.ts +169 -0
- package/dist/api/utilities/scheduler.js +136 -0
- package/dist/api/utilities/scheduler.js.map +1 -0
- package/dist/api/utilities/streaming.d.ts +74 -15
- package/dist/api/utilities/streaming.js +170 -12
- package/dist/api/utilities/streaming.js.map +1 -1
- package/dist/api/utilities/timestamp.d.ts +1 -1
- package/dist/api/webrtc-stream.d.ts +288 -0
- package/dist/api/webrtc-stream.js +440 -0
- package/dist/api/webrtc-stream.js.map +1 -0
- package/dist/constants/constants.d.ts +51 -1
- package/dist/constants/constants.js +47 -1
- package/dist/constants/constants.js.map +1 -1
- package/dist/constants/encoders.d.ts +2 -1
- package/dist/constants/encoders.js +4 -3
- package/dist/constants/encoders.js.map +1 -1
- package/dist/constants/hardware.d.ts +26 -0
- package/dist/constants/hardware.js +27 -0
- package/dist/constants/hardware.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.js +1 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/lib/binding.d.ts +19 -8
- package/dist/lib/binding.js.map +1 -1
- package/dist/lib/codec-context.d.ts +87 -0
- package/dist/lib/codec-context.js +125 -4
- package/dist/lib/codec-context.js.map +1 -1
- package/dist/lib/codec-parameters.d.ts +183 -1
- package/dist/lib/codec-parameters.js +209 -0
- package/dist/lib/codec-parameters.js.map +1 -1
- package/dist/lib/codec-parser.d.ts +23 -0
- package/dist/lib/codec-parser.js +25 -0
- package/dist/lib/codec-parser.js.map +1 -1
- package/dist/lib/codec.d.ts +26 -4
- package/dist/lib/codec.js +35 -0
- package/dist/lib/codec.js.map +1 -1
- package/dist/lib/dictionary.js +1 -0
- package/dist/lib/dictionary.js.map +1 -1
- package/dist/lib/error.js +1 -1
- package/dist/lib/error.js.map +1 -1
- package/dist/lib/filter-context.d.ts +52 -11
- package/dist/lib/filter-context.js +56 -12
- package/dist/lib/filter-context.js.map +1 -1
- package/dist/lib/filter-graph.d.ts +9 -0
- package/dist/lib/filter-graph.js +13 -0
- package/dist/lib/filter-graph.js.map +1 -1
- package/dist/lib/filter.d.ts +21 -0
- package/dist/lib/filter.js +28 -0
- package/dist/lib/filter.js.map +1 -1
- package/dist/lib/format-context.d.ts +48 -14
- package/dist/lib/format-context.js +76 -7
- package/dist/lib/format-context.js.map +1 -1
- package/dist/lib/frame.d.ts +168 -0
- package/dist/lib/frame.js +212 -0
- package/dist/lib/frame.js.map +1 -1
- package/dist/lib/hardware-device-context.d.ts +3 -2
- package/dist/lib/hardware-device-context.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/input-format.d.ts +21 -0
- package/dist/lib/input-format.js +42 -2
- package/dist/lib/input-format.js.map +1 -1
- package/dist/lib/native-types.d.ts +48 -26
- package/dist/lib/option.d.ts +25 -13
- package/dist/lib/option.js +28 -0
- package/dist/lib/option.js.map +1 -1
- package/dist/lib/output-format.d.ts +22 -1
- package/dist/lib/output-format.js +28 -0
- package/dist/lib/output-format.js.map +1 -1
- package/dist/lib/packet.d.ts +35 -0
- package/dist/lib/packet.js +52 -2
- package/dist/lib/packet.js.map +1 -1
- package/dist/lib/stream.d.ts +126 -0
- package/dist/lib/stream.js +188 -5
- package/dist/lib/stream.js.map +1 -1
- package/dist/lib/sync-queue.d.ts +179 -0
- package/dist/lib/sync-queue.js +197 -0
- package/dist/lib/sync-queue.js.map +1 -0
- package/dist/lib/types.d.ts +27 -1
- package/dist/lib/utilities.d.ts +281 -53
- package/dist/lib/utilities.js +298 -55
- package/dist/lib/utilities.js.map +1 -1
- package/install/check.js +18 -7
- package/package.json +20 -19
- package/dist/api/fmp4.js +0 -710
- package/dist/api/fmp4.js.map +0 -1
- package/dist/api/media-input.js +0 -1075
- package/dist/api/media-input.js.map +0 -1
- package/dist/api/media-output.js +0 -1040
- package/dist/api/media-output.js.map +0 -1
- package/dist/api/webrtc.d.ts +0 -664
- package/dist/api/webrtc.js +0 -1132
- package/dist/api/webrtc.js.map +0 -1
package/README.md
CHANGED
|
@@ -90,10 +90,6 @@ decoderCtx.allocContext3(codec);
|
|
|
90
90
|
ret = decoderCtx.parametersToContext(videoStream.codecpar);
|
|
91
91
|
FFmpegError.throwIfError(ret, 'Could not copy codec parameters to decoder context');
|
|
92
92
|
|
|
93
|
-
// Inform the decoder about the timebase for packet timestamps and the frame rate
|
|
94
|
-
decoderCtx.pktTimebase = videoStream.timeBase;
|
|
95
|
-
decoderCtx.framerate = videoStream.rFrameRate || videoStream.avgFrameRate || new Rational(25, 1);
|
|
96
|
-
|
|
97
93
|
// Open decoder context
|
|
98
94
|
ret = await decoderCtx.open2(codec, null);
|
|
99
95
|
FFmpegError.throwIfError(ret, 'Could not open codec');
|
|
@@ -140,49 +136,45 @@ while (true) {
|
|
|
140
136
|
Higher-level abstractions for common tasks like decoding, encoding, filtering, and transcoding. Easier to use while still providing access to low-level details when needed.
|
|
141
137
|
|
|
142
138
|
```typescript
|
|
143
|
-
import { Decoder, Encoder,
|
|
139
|
+
import { Decoder, Demuxer, Encoder, HardwareContext, Muxer } from 'node-av/api';
|
|
144
140
|
import { FF_ENCODER_LIBX264 } from 'node-av/constants';
|
|
145
141
|
|
|
146
|
-
// Open
|
|
147
|
-
await using input = await
|
|
148
|
-
await using output = await MediaOutput.open('output.mp4');
|
|
142
|
+
// Open Demuxer
|
|
143
|
+
await using input = await Demuxer.open('input.mp4');
|
|
149
144
|
|
|
150
145
|
// Get video stream
|
|
151
146
|
const videoStream = input.video()!;
|
|
152
147
|
|
|
148
|
+
// Optional, setup hardware acceleration
|
|
149
|
+
using hw = HardwareContext.auto();
|
|
150
|
+
|
|
153
151
|
// Create decoder
|
|
154
|
-
using decoder = await Decoder.create(videoStream
|
|
152
|
+
using decoder = await Decoder.create(videoStream, {
|
|
153
|
+
hardware: hw, // Optional, use hardware acceleration if available
|
|
154
|
+
});
|
|
155
155
|
|
|
156
156
|
// Create encoder
|
|
157
157
|
using encoder = await Encoder.create(FF_ENCODER_LIBX264, {
|
|
158
|
-
|
|
159
|
-
frameRate: videoStream.avgFrameRate,
|
|
158
|
+
decoder, // Optional, copy settings from decoder
|
|
160
159
|
});
|
|
161
160
|
|
|
162
|
-
//
|
|
163
|
-
|
|
161
|
+
// Open Muxer
|
|
162
|
+
await using output = await Muxer.open('output.mp4', {
|
|
163
|
+
input, // Optional, used to copy global headers and metadata
|
|
164
|
+
});
|
|
164
165
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
using encoded = await encoder.encode(frame);
|
|
170
|
-
if (encoded) {
|
|
171
|
-
await output.writePacket(encoded, outputIndex);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
166
|
+
// Add stream to output
|
|
167
|
+
const outputIndex = output.addStream(encoder, {
|
|
168
|
+
inputStream: videoStream, // Optional, copy settings from input stream
|
|
169
|
+
});
|
|
175
170
|
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
await output.writePacket(encoded, outputIndex);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
171
|
+
// Create processing generators
|
|
172
|
+
const inputGenerator = input.packets(videoStream.index);
|
|
173
|
+
const decoderGenerator = decoder.frames(inputGenerator);
|
|
174
|
+
const encoderGenerator = encoder.packets(decoderGenerator);
|
|
183
175
|
|
|
184
|
-
//
|
|
185
|
-
for await (using packet of
|
|
176
|
+
// Process packets
|
|
177
|
+
for await (using packet of encoderGenerator) {
|
|
186
178
|
await output.writePacket(packet, outputIndex);
|
|
187
179
|
}
|
|
188
180
|
|
|
@@ -194,15 +186,33 @@ for await (using packet of encoder.flushPackets()) {
|
|
|
194
186
|
A simple way to chain together multiple processing steps like decoding, filtering, encoding, and muxing.
|
|
195
187
|
|
|
196
188
|
```typescript
|
|
197
|
-
import {
|
|
189
|
+
import { Decoder, Demuxer, Encoder, HardwareContext, Muxer, pipeline } from 'node-av/api';
|
|
190
|
+
import { FF_ENCODER_LIBX264 } from 'node-av/constants';
|
|
198
191
|
|
|
199
192
|
// Simple transcode pipeline: input → decoder → encoder → output
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
193
|
+
|
|
194
|
+
// Open Demuxer
|
|
195
|
+
await using input = await Demuxer.open('input.mp4');
|
|
196
|
+
|
|
197
|
+
// Get video stream
|
|
198
|
+
const videoStream = input.video()!;
|
|
199
|
+
|
|
200
|
+
// Optional, setup hardware acceleration
|
|
201
|
+
using hw = HardwareContext.auto();
|
|
202
|
+
|
|
203
|
+
// Create decoder
|
|
204
|
+
using decoder = await Decoder.create(videoStream, {
|
|
205
|
+
hardware: hw, // Optional, use hardware acceleration if available
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Create encoder
|
|
209
|
+
using encoder = await Encoder.create(FF_ENCODER_LIBX264, {
|
|
210
|
+
decoder, // Optional, copy settings from decoder
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Open Muxer
|
|
214
|
+
await using output = await Muxer.open('output.mp4', {
|
|
215
|
+
input, // Optional, used to copy global headers and metadata
|
|
206
216
|
});
|
|
207
217
|
|
|
208
218
|
const control = pipeline(input, decoder, encoder, output);
|
|
@@ -231,8 +241,7 @@ const decoder = await Decoder.create(stream, {
|
|
|
231
241
|
// Use with encoder (use hardware-specific codec)
|
|
232
242
|
const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_LIBX264;
|
|
233
243
|
const encoder = await Encoder.create(encoderCodec, {
|
|
234
|
-
|
|
235
|
-
frameRate: videoStream.avgFrameRate,
|
|
244
|
+
decoder,
|
|
236
245
|
});
|
|
237
246
|
```
|
|
238
247
|
|
|
@@ -252,7 +261,7 @@ The library provides multiple entry points for optimal tree shaking:
|
|
|
252
261
|
|
|
253
262
|
```typescript
|
|
254
263
|
// High-Level API only - Recommended for most use cases
|
|
255
|
-
import {
|
|
264
|
+
import { Muxer, Muxer, Decoder, Encoder } from 'node-av/api';
|
|
256
265
|
|
|
257
266
|
// Low-Level API only - Direct FFmpeg bindings
|
|
258
267
|
import { FormatContext, CodecContext, Frame, Packet } from 'node-av/lib';
|
|
@@ -272,11 +281,11 @@ import * as ffmpeg from 'node-av';
|
|
|
272
281
|
### From Files or Network
|
|
273
282
|
|
|
274
283
|
```typescript
|
|
275
|
-
const media = await
|
|
284
|
+
const media = await Muxer.open('input.mp4');
|
|
276
285
|
|
|
277
286
|
// or
|
|
278
287
|
|
|
279
|
-
const media = await
|
|
288
|
+
const media = await Muxer.open('rtsp://example.com/stream');
|
|
280
289
|
```
|
|
281
290
|
|
|
282
291
|
### From Buffers
|
|
@@ -285,7 +294,7 @@ const media = await MediaInput.open('rtsp://example.com/stream');
|
|
|
285
294
|
import { readFile } from 'fs/promises';
|
|
286
295
|
|
|
287
296
|
const buffer = await readFile('input.mp4');
|
|
288
|
-
const media = await
|
|
297
|
+
const media = await Muxer.open(buffer);
|
|
289
298
|
```
|
|
290
299
|
|
|
291
300
|
### Custom I/O Callbacks
|
|
@@ -305,7 +314,7 @@ const inputCallbacks: IOInputCallbacks = {
|
|
|
305
314
|
}
|
|
306
315
|
};
|
|
307
316
|
|
|
308
|
-
await using input = await
|
|
317
|
+
await using input = await Muxer.open(inputCallbacks, {
|
|
309
318
|
format: 'mp4'
|
|
310
319
|
});
|
|
311
320
|
```
|
|
@@ -314,7 +323,7 @@ await using input = await MediaInput.open(inputCallbacks, {
|
|
|
314
323
|
|
|
315
324
|
```typescript
|
|
316
325
|
// Raw video input
|
|
317
|
-
const rawVideo = await
|
|
326
|
+
const rawVideo = await Muxer.open({
|
|
318
327
|
type: 'video',
|
|
319
328
|
input: 'input.yuv',
|
|
320
329
|
width: 1280,
|
|
@@ -324,7 +333,7 @@ const rawVideo = await MediaInput.open({
|
|
|
324
333
|
});
|
|
325
334
|
|
|
326
335
|
// Raw audio input
|
|
327
|
-
const rawAudio = await
|
|
336
|
+
const rawAudio = await Muxer.open({
|
|
328
337
|
type: 'audio',
|
|
329
338
|
input: 'input.pcm',
|
|
330
339
|
sampleRate: 48000,
|
|
@@ -342,13 +351,13 @@ The library supports automatic resource cleanup using the Disposable pattern:
|
|
|
342
351
|
```typescript
|
|
343
352
|
// Automatic cleanup with 'using'
|
|
344
353
|
{
|
|
345
|
-
await using media = await
|
|
354
|
+
await using media = await Muxer.open('input.mp4');
|
|
346
355
|
using decoder = await Decoder.create(media.video());
|
|
347
356
|
// Resources automatically cleaned up at end of scope
|
|
348
357
|
}
|
|
349
358
|
|
|
350
359
|
// Manual cleanup
|
|
351
|
-
const media = await
|
|
360
|
+
const media = await Muxer.open('input.mp4');
|
|
352
361
|
try {
|
|
353
362
|
// Process media
|
|
354
363
|
} finally {
|
|
@@ -420,18 +429,22 @@ NodeAV provides direct bindings to FFmpeg's C APIs, which work with raw memory p
|
|
|
420
429
|
| `browser-webrtc` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/browser/webrtc) |
|
|
421
430
|
| `api-dash` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-dash.ts) |
|
|
422
431
|
| `api-encode-decode` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-encode-decode.ts) |
|
|
432
|
+
| `api-fmp4` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-fmp4.ts) |
|
|
423
433
|
| `api-frame-extract` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-frame-extract.ts) |
|
|
434
|
+
| `api-hw-codecs` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-codecs.ts) |
|
|
424
435
|
| `api-hw-decode-sw-encode` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-decode-sw-encode.ts) |
|
|
425
436
|
| `api-hw-raw` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-raw.ts) |
|
|
426
437
|
| `api-hw-raw-output` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-raw-output.ts) |
|
|
427
|
-
| `api-hw-rtsp-custom-io` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-rtsp-custom-io.ts) |
|
|
428
438
|
| `api-hw-rtsp` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-rtsp.ts) |
|
|
439
|
+
| `api-hw-stream-custom-io` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-stream-custom-io.ts) |
|
|
429
440
|
| `api-hw-transcode` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-transcode.ts) |
|
|
430
441
|
| `api-hw-filter-sync` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-hw-filter-sync.ts) |
|
|
431
442
|
| `api-muxing` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-muxing.ts) |
|
|
432
443
|
| `api-pipeline-hw-rtsp` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-pipeline-hw-rtsp.ts) |
|
|
433
444
|
| `api-pipeline-raw-muxing` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-pipeline-raw-muxing.ts) |
|
|
434
|
-
| `api-
|
|
445
|
+
| `api-rtp` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-rtp.ts) |
|
|
446
|
+
| `api-sdp-custom` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-sdp-custom.ts) |
|
|
447
|
+
| `api-sdp-input` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-sdp-input.ts) |
|
|
435
448
|
| `api-stream-input` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-stream-input.ts) |
|
|
436
449
|
| `api-sw-decode-hw-encode` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-sw-decode-hw-encode.ts) |
|
|
437
450
|
| `api-sw-transcode` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-sw-transcode.ts) |
|
package/binding.gyp
CHANGED
|
@@ -57,11 +57,14 @@
|
|
|
57
57
|
"src/bindings/bitstream_filter_context_async.cc",
|
|
58
58
|
"src/bindings/bitstream_filter_context_sync.cc",
|
|
59
59
|
"src/bindings/option.cc",
|
|
60
|
+
"src/bindings/sync_queue.cc",
|
|
61
|
+
"externals/jellyfin-ffmpeg/fftools/sync_queue.c",
|
|
60
62
|
],
|
|
61
63
|
"include_dirs": [
|
|
62
64
|
"<!@(node -p \"require('node-addon-api').include\")",
|
|
63
65
|
"/opt/ffbuild/prefix/include",
|
|
64
66
|
"<(module_root_dir)/externals/jellyfin-ffmpeg",
|
|
67
|
+
"<(module_root_dir)/externals/jellyfin-ffmpeg/libavcodec",
|
|
65
68
|
],
|
|
66
69
|
"library_dirs": ["/opt/ffbuild/prefix/lib"],
|
|
67
70
|
"dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
|
|
@@ -102,6 +105,7 @@
|
|
|
102
105
|
"/opt/ffbuild/prefix/lib/libudfread.a",
|
|
103
106
|
"/opt/ffbuild/prefix/lib/libz.a",
|
|
104
107
|
"/opt/ffbuild/prefix/lib/liblzma.a",
|
|
108
|
+
"/opt/ffbuild/prefix/lib/libfdk-aac.a",
|
|
105
109
|
"<!@(ls /opt/ffbuild/prefix/lib/libNE10.a 2>/dev/null || echo '')",
|
|
106
110
|
"<!@(ls /opt/ffbuild/prefix/lib/libwebpdemux.a 2>/dev/null || echo '')",
|
|
107
111
|
"<!@(ls /opt/ffbuild/prefix/lib/libchromaprint.a 2>/dev/null || echo '')",
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { Frame } from '../lib/frame.js';
|
|
2
|
+
import type { AVSampleFormat } from '../constants/index.js';
|
|
3
|
+
import type { ChannelLayout } from '../lib/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Audio frame buffering utility for encoders with fixed frame size requirements.
|
|
6
|
+
*
|
|
7
|
+
* Many audio encoders (Opus, AAC, MP3, etc.) require frames with a specific number
|
|
8
|
+
* of samples (frame_size). This class buffers incoming frames and outputs frames
|
|
9
|
+
* with exactly the required size.
|
|
10
|
+
*
|
|
11
|
+
* Uses FFmpeg's AVAudioFifo internally for efficient sample buffering.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { AudioFrameBuffer } from 'node-av/api';
|
|
16
|
+
*
|
|
17
|
+
* // Create buffer for 480-sample frames (e.g., Opus at 24kHz)
|
|
18
|
+
* using buffer = AudioFrameBuffer.create(480, AV_SAMPLE_FMT_FLT, 48000, 'mono', 1);
|
|
19
|
+
*
|
|
20
|
+
* // Push variable-sized frames from filter
|
|
21
|
+
* for await (const frame of filterOutput) {
|
|
22
|
+
* await buffer.push(frame);
|
|
23
|
+
*
|
|
24
|
+
* // Pull fixed-size frames for encoder
|
|
25
|
+
* let outputFrame;
|
|
26
|
+
* while ((outputFrame = await buffer.pull()) !== null) {
|
|
27
|
+
* await encoder.encode(outputFrame);
|
|
28
|
+
* outputFrame.free();
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* // Flush remaining samples
|
|
33
|
+
* let outputFrame;
|
|
34
|
+
* while ((outputFrame = await buffer.pull()) !== null) {
|
|
35
|
+
* await encoder.encode(outputFrame);
|
|
36
|
+
* outputFrame.free();
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class AudioFrameBuffer implements Disposable {
|
|
41
|
+
private fifo;
|
|
42
|
+
private frame;
|
|
43
|
+
private frameSize;
|
|
44
|
+
private nextPts;
|
|
45
|
+
private firstFramePts;
|
|
46
|
+
/**
|
|
47
|
+
* @param fifo - Underlying AudioFifo instance
|
|
48
|
+
*
|
|
49
|
+
* @param frameSize - Number of samples per output frame
|
|
50
|
+
*
|
|
51
|
+
* @param sampleFormat - Audio sample format
|
|
52
|
+
*
|
|
53
|
+
* @param sampleRate - Sample rate in Hz
|
|
54
|
+
*
|
|
55
|
+
* @param channelLayout - Channel layout
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
private constructor();
|
|
60
|
+
/**
|
|
61
|
+
* Create an audio frame buffer.
|
|
62
|
+
*
|
|
63
|
+
* @param frameSize - Required frame size in samples
|
|
64
|
+
*
|
|
65
|
+
* @param sampleFormat - Audio sample format
|
|
66
|
+
*
|
|
67
|
+
* @param sampleRate - Sample rate in Hz
|
|
68
|
+
*
|
|
69
|
+
* @param channelLayout - Channel layout (e.g., 'mono', 'stereo')
|
|
70
|
+
*
|
|
71
|
+
* @param channels - Number of audio channels
|
|
72
|
+
*
|
|
73
|
+
* @returns Configured audio frame buffer
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // For Opus encoder at 48kHz with 20ms frames
|
|
78
|
+
* const buffer = AudioFrameBuffer.create(960, AV_SAMPLE_FMT_FLT, 48000, 'mono', 1);
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
static create(frameSize: number, sampleFormat: AVSampleFormat, sampleRate: number, channelLayout: ChannelLayout, channels: number): AudioFrameBuffer;
|
|
82
|
+
/**
|
|
83
|
+
* Get number of samples currently in buffer.
|
|
84
|
+
*
|
|
85
|
+
* @returns Number of buffered samples
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* console.log(`Buffer contains ${buffer.size} samples`);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
get size(): number;
|
|
93
|
+
/**
|
|
94
|
+
* Check if a complete frame is available.
|
|
95
|
+
*
|
|
96
|
+
* Returns true if the FIFO contains at least frameSize samples.
|
|
97
|
+
*
|
|
98
|
+
* @returns True if a full frame can be pulled
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* while (buffer.hasFrame()) {
|
|
103
|
+
* const frame = buffer.pull();
|
|
104
|
+
* // Process frame...
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
hasFrame(): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Push an audio frame into the buffer asynchronously.
|
|
111
|
+
*
|
|
112
|
+
* The frame's samples are added to the internal FIFO.
|
|
113
|
+
* Call hasFrame() and pull() to retrieve fixed-size output frames.
|
|
114
|
+
*
|
|
115
|
+
* @param frame - Audio frame to buffer
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* await buffer.push(filterFrame);
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @see {@link pushSync} For synchronous version
|
|
123
|
+
*/
|
|
124
|
+
push(frame: Frame): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Push an audio frame into the buffer synchronously.
|
|
127
|
+
* Synchronous version of push.
|
|
128
|
+
*
|
|
129
|
+
* The frame's samples are added to the internal FIFO.
|
|
130
|
+
* Call hasFrame() and pullSync() to retrieve fixed-size output frames.
|
|
131
|
+
*
|
|
132
|
+
* @param frame - Audio frame to buffer
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* buffer.pushSync(filterFrame);
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @see {@link push} For async version
|
|
140
|
+
*/
|
|
141
|
+
pushSync(frame: Frame): void;
|
|
142
|
+
/**
|
|
143
|
+
* Pull a fixed-size audio frame from the buffer asynchronously.
|
|
144
|
+
*
|
|
145
|
+
* Reads exactly frameSize samples from the FIFO and returns a cloned Frame.
|
|
146
|
+
* Returns null if not enough samples are available.
|
|
147
|
+
* Reuses internal frame buffer for efficiency (like Decoder does).
|
|
148
|
+
*
|
|
149
|
+
* @returns Audio frame with exactly frameSize samples, or null if insufficient samples
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* using frame = await buffer.pull();
|
|
154
|
+
* if (frame) {
|
|
155
|
+
* await encoder.encode(frame);
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @see {@link pullSync} For synchronous version
|
|
160
|
+
*/
|
|
161
|
+
pull(): Promise<Frame | null>;
|
|
162
|
+
/**
|
|
163
|
+
* Pull a fixed-size audio frame from the buffer synchronously.
|
|
164
|
+
* Synchronous version of pull.
|
|
165
|
+
*
|
|
166
|
+
* Reads exactly frameSize samples from the FIFO and returns a cloned Frame.
|
|
167
|
+
* Returns null if not enough samples are available.
|
|
168
|
+
* Reuses internal frame buffer for efficiency (like Decoder does).
|
|
169
|
+
*
|
|
170
|
+
* @returns Audio frame with exactly frameSize samples, or null if insufficient samples
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* using frame = buffer.pullSync();
|
|
175
|
+
* if (frame) {
|
|
176
|
+
* encoder.encodeSync(frame);
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
179
|
+
*
|
|
180
|
+
* @see {@link pull} For async version
|
|
181
|
+
*/
|
|
182
|
+
pullSync(): Frame | null;
|
|
183
|
+
/**
|
|
184
|
+
* Reset the buffer, discarding all buffered samples.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* buffer.reset();
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
reset(): void;
|
|
192
|
+
/**
|
|
193
|
+
* Free the buffer and all resources.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* buffer.free();
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
[Symbol.dispose](): void;
|
|
201
|
+
}
|