node-av 3.1.3 → 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.
Files changed (156) hide show
  1. package/README.md +65 -52
  2. package/binding.gyp +4 -0
  3. package/dist/api/audio-frame-buffer.d.ts +201 -0
  4. package/dist/api/audio-frame-buffer.js +275 -0
  5. package/dist/api/audio-frame-buffer.js.map +1 -0
  6. package/dist/api/bitstream-filter.d.ts +319 -78
  7. package/dist/api/bitstream-filter.js +680 -151
  8. package/dist/api/bitstream-filter.js.map +1 -1
  9. package/dist/api/constants.d.ts +44 -0
  10. package/dist/api/constants.js +45 -0
  11. package/dist/api/constants.js.map +1 -0
  12. package/dist/api/data/test_av1.ivf +0 -0
  13. package/dist/api/data/test_mjpeg.mjpeg +0 -0
  14. package/dist/api/data/test_vp8.ivf +0 -0
  15. package/dist/api/data/test_vp9.ivf +0 -0
  16. package/dist/api/decoder.d.ts +279 -17
  17. package/dist/api/decoder.js +998 -209
  18. package/dist/api/decoder.js.map +1 -1
  19. package/dist/api/{media-input.d.ts → demuxer.d.ts} +294 -44
  20. package/dist/api/demuxer.js +1968 -0
  21. package/dist/api/demuxer.js.map +1 -0
  22. package/dist/api/encoder.d.ts +308 -50
  23. package/dist/api/encoder.js +1133 -111
  24. package/dist/api/encoder.js.map +1 -1
  25. package/dist/api/filter-presets.d.ts +12 -5
  26. package/dist/api/filter-presets.js +21 -7
  27. package/dist/api/filter-presets.js.map +1 -1
  28. package/dist/api/filter.d.ts +406 -40
  29. package/dist/api/filter.js +966 -139
  30. package/dist/api/filter.js.map +1 -1
  31. package/dist/api/{fmp4.d.ts → fmp4-stream.d.ts} +141 -140
  32. package/dist/api/fmp4-stream.js +539 -0
  33. package/dist/api/fmp4-stream.js.map +1 -0
  34. package/dist/api/hardware.d.ts +58 -6
  35. package/dist/api/hardware.js +127 -11
  36. package/dist/api/hardware.js.map +1 -1
  37. package/dist/api/index.d.ts +6 -4
  38. package/dist/api/index.js +14 -8
  39. package/dist/api/index.js.map +1 -1
  40. package/dist/api/io-stream.d.ts +3 -3
  41. package/dist/api/io-stream.js +5 -4
  42. package/dist/api/io-stream.js.map +1 -1
  43. package/dist/api/{media-output.d.ts → muxer.d.ts} +274 -60
  44. package/dist/api/muxer.js +1934 -0
  45. package/dist/api/muxer.js.map +1 -0
  46. package/dist/api/pipeline.d.ts +77 -29
  47. package/dist/api/pipeline.js +435 -425
  48. package/dist/api/pipeline.js.map +1 -1
  49. package/dist/api/rtp-stream.d.ts +312 -0
  50. package/dist/api/rtp-stream.js +630 -0
  51. package/dist/api/rtp-stream.js.map +1 -0
  52. package/dist/api/types.d.ts +476 -55
  53. package/dist/api/utilities/async-queue.d.ts +91 -0
  54. package/dist/api/utilities/async-queue.js +162 -0
  55. package/dist/api/utilities/async-queue.js.map +1 -0
  56. package/dist/api/utilities/audio-sample.d.ts +1 -1
  57. package/dist/api/utilities/image.d.ts +1 -1
  58. package/dist/api/utilities/index.d.ts +2 -0
  59. package/dist/api/utilities/index.js +4 -0
  60. package/dist/api/utilities/index.js.map +1 -1
  61. package/dist/api/utilities/media-type.d.ts +1 -1
  62. package/dist/api/utilities/pixel-format.d.ts +1 -1
  63. package/dist/api/utilities/sample-format.d.ts +1 -1
  64. package/dist/api/utilities/scheduler.d.ts +169 -0
  65. package/dist/api/utilities/scheduler.js +136 -0
  66. package/dist/api/utilities/scheduler.js.map +1 -0
  67. package/dist/api/utilities/streaming.d.ts +74 -15
  68. package/dist/api/utilities/streaming.js +170 -12
  69. package/dist/api/utilities/streaming.js.map +1 -1
  70. package/dist/api/utilities/timestamp.d.ts +1 -1
  71. package/dist/api/webrtc-stream.d.ts +288 -0
  72. package/dist/api/webrtc-stream.js +440 -0
  73. package/dist/api/webrtc-stream.js.map +1 -0
  74. package/dist/constants/constants.d.ts +51 -1
  75. package/dist/constants/constants.js +47 -1
  76. package/dist/constants/constants.js.map +1 -1
  77. package/dist/constants/encoders.d.ts +2 -1
  78. package/dist/constants/encoders.js +4 -3
  79. package/dist/constants/encoders.js.map +1 -1
  80. package/dist/constants/hardware.d.ts +26 -0
  81. package/dist/constants/hardware.js +27 -0
  82. package/dist/constants/hardware.js.map +1 -0
  83. package/dist/constants/index.d.ts +1 -0
  84. package/dist/constants/index.js +1 -0
  85. package/dist/constants/index.js.map +1 -1
  86. package/dist/lib/binding.d.ts +19 -8
  87. package/dist/lib/binding.js.map +1 -1
  88. package/dist/lib/codec-context.d.ts +87 -0
  89. package/dist/lib/codec-context.js +125 -4
  90. package/dist/lib/codec-context.js.map +1 -1
  91. package/dist/lib/codec-parameters.d.ts +183 -1
  92. package/dist/lib/codec-parameters.js +209 -0
  93. package/dist/lib/codec-parameters.js.map +1 -1
  94. package/dist/lib/codec-parser.d.ts +23 -0
  95. package/dist/lib/codec-parser.js +25 -0
  96. package/dist/lib/codec-parser.js.map +1 -1
  97. package/dist/lib/codec.d.ts +26 -4
  98. package/dist/lib/codec.js +35 -0
  99. package/dist/lib/codec.js.map +1 -1
  100. package/dist/lib/dictionary.js +1 -0
  101. package/dist/lib/dictionary.js.map +1 -1
  102. package/dist/lib/error.js +1 -1
  103. package/dist/lib/error.js.map +1 -1
  104. package/dist/lib/filter-context.d.ts +52 -11
  105. package/dist/lib/filter-context.js +56 -12
  106. package/dist/lib/filter-context.js.map +1 -1
  107. package/dist/lib/filter-graph.d.ts +9 -0
  108. package/dist/lib/filter-graph.js +13 -0
  109. package/dist/lib/filter-graph.js.map +1 -1
  110. package/dist/lib/filter.d.ts +21 -0
  111. package/dist/lib/filter.js +28 -0
  112. package/dist/lib/filter.js.map +1 -1
  113. package/dist/lib/format-context.d.ts +48 -14
  114. package/dist/lib/format-context.js +76 -7
  115. package/dist/lib/format-context.js.map +1 -1
  116. package/dist/lib/frame.d.ts +168 -0
  117. package/dist/lib/frame.js +212 -0
  118. package/dist/lib/frame.js.map +1 -1
  119. package/dist/lib/hardware-device-context.d.ts +3 -2
  120. package/dist/lib/hardware-device-context.js.map +1 -1
  121. package/dist/lib/index.d.ts +1 -0
  122. package/dist/lib/index.js +2 -0
  123. package/dist/lib/index.js.map +1 -1
  124. package/dist/lib/input-format.d.ts +21 -0
  125. package/dist/lib/input-format.js +42 -2
  126. package/dist/lib/input-format.js.map +1 -1
  127. package/dist/lib/native-types.d.ts +48 -26
  128. package/dist/lib/option.d.ts +25 -13
  129. package/dist/lib/option.js +28 -0
  130. package/dist/lib/option.js.map +1 -1
  131. package/dist/lib/output-format.d.ts +22 -1
  132. package/dist/lib/output-format.js +28 -0
  133. package/dist/lib/output-format.js.map +1 -1
  134. package/dist/lib/packet.d.ts +35 -0
  135. package/dist/lib/packet.js +52 -2
  136. package/dist/lib/packet.js.map +1 -1
  137. package/dist/lib/stream.d.ts +126 -0
  138. package/dist/lib/stream.js +188 -5
  139. package/dist/lib/stream.js.map +1 -1
  140. package/dist/lib/sync-queue.d.ts +179 -0
  141. package/dist/lib/sync-queue.js +197 -0
  142. package/dist/lib/sync-queue.js.map +1 -0
  143. package/dist/lib/types.d.ts +27 -1
  144. package/dist/lib/utilities.d.ts +281 -53
  145. package/dist/lib/utilities.js +298 -55
  146. package/dist/lib/utilities.js.map +1 -1
  147. package/package.json +20 -19
  148. package/dist/api/fmp4.js +0 -710
  149. package/dist/api/fmp4.js.map +0 -1
  150. package/dist/api/media-input.js +0 -1075
  151. package/dist/api/media-input.js.map +0 -1
  152. package/dist/api/media-output.js +0 -1040
  153. package/dist/api/media-output.js.map +0 -1
  154. package/dist/api/webrtc.d.ts +0 -664
  155. package/dist/api/webrtc.js +0 -1132
  156. 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, MediaInput, MediaOutput } from 'node-av/api';
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 media
147
- await using input = await MediaInput.open('input.mp4');
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
- timeBase: videoStream.timeBase,
159
- frameRate: videoStream.avgFrameRate,
158
+ decoder, // Optional, copy settings from decoder
160
159
  });
161
160
 
162
- // Add stream to output
163
- const outputIndex = output.addStream(encoder);
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
- // Process packets
166
- for await (using packet of input.packets(videoStream.index)) {
167
- using frame = await decoder.decode(packet);
168
- if (frame) {
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
- // Flush decoder
177
- for await (using frame of decoder.flushFrames()) {
178
- using encoded = await encoder.encode(frame);
179
- if (encoded) {
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
- // Flush encoder
185
- for await (using packet of encoder.flushPackets()) {
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 { pipeline, MediaInput, MediaOutput, Decoder, Encoder } from 'node-av/api';
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
- const input = await MediaInput.open('input.mp4');
201
- const output = await MediaOutput.open('output.mp4');
202
- const decoder = await Decoder.create(input.video());
203
- const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
204
- timeBase: videoStream.timeBase,
205
- frameRate: videoStream.avgFrameRate,
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
- timeBase: videoStream.timeBase,
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 { MediaInput, MediaOutput, Decoder, Encoder } from 'node-av/api';
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 MediaInput.open('input.mp4');
284
+ const media = await Muxer.open('input.mp4');
276
285
 
277
286
  // or
278
287
 
279
- const media = await MediaInput.open('rtsp://example.com/stream');
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 MediaInput.open(buffer);
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 MediaInput.open(inputCallbacks, {
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 MediaInput.open({
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 MediaInput.open({
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 MediaInput.open('input.mp4');
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 MediaInput.open('input.mp4');
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-sdp` | | | [✓](https://github.com/seydx/node-av/tree/main/examples/api-sdp.ts) |
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
+ }