node-av 1.2.0 → 2.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 (99) hide show
  1. package/README.md +37 -59
  2. package/dist/api/bitstream-filter.d.ts +5 -2
  3. package/dist/api/bitstream-filter.js +7 -4
  4. package/dist/api/bitstream-filter.js.map +1 -1
  5. package/dist/api/decoder.d.ts +135 -119
  6. package/dist/api/decoder.js +195 -202
  7. package/dist/api/decoder.js.map +1 -1
  8. package/dist/api/encoder.d.ts +141 -78
  9. package/dist/api/encoder.js +241 -193
  10. package/dist/api/encoder.js.map +1 -1
  11. package/dist/api/filter-presets.d.ts +699 -573
  12. package/dist/api/filter-presets.js +1157 -840
  13. package/dist/api/filter-presets.js.map +1 -1
  14. package/dist/api/filter.d.ts +180 -157
  15. package/dist/api/filter.js +314 -366
  16. package/dist/api/filter.js.map +1 -1
  17. package/dist/api/hardware.d.ts +28 -29
  18. package/dist/api/hardware.js +80 -74
  19. package/dist/api/hardware.js.map +1 -1
  20. package/dist/api/index.d.ts +1 -1
  21. package/dist/api/index.js +1 -1
  22. package/dist/api/index.js.map +1 -1
  23. package/dist/api/io-stream.d.ts +6 -0
  24. package/dist/api/io-stream.js +6 -0
  25. package/dist/api/io-stream.js.map +1 -1
  26. package/dist/api/media-input.d.ts +2 -1
  27. package/dist/api/media-input.js +3 -8
  28. package/dist/api/media-input.js.map +1 -1
  29. package/dist/api/media-output.d.ts +37 -126
  30. package/dist/api/media-output.js +138 -206
  31. package/dist/api/media-output.js.map +1 -1
  32. package/dist/api/pipeline.d.ts +193 -0
  33. package/dist/api/pipeline.js +36 -42
  34. package/dist/api/pipeline.js.map +1 -1
  35. package/dist/api/types.d.ts +22 -57
  36. package/dist/api/utilities/audio-sample.d.ts +0 -8
  37. package/dist/api/utilities/audio-sample.js +0 -8
  38. package/dist/api/utilities/audio-sample.js.map +1 -1
  39. package/dist/api/utilities/channel-layout.d.ts +0 -8
  40. package/dist/api/utilities/channel-layout.js +0 -8
  41. package/dist/api/utilities/channel-layout.js.map +1 -1
  42. package/dist/api/utilities/image.d.ts +0 -8
  43. package/dist/api/utilities/image.js +0 -8
  44. package/dist/api/utilities/image.js.map +1 -1
  45. package/dist/api/utilities/index.d.ts +3 -3
  46. package/dist/api/utilities/index.js +3 -3
  47. package/dist/api/utilities/index.js.map +1 -1
  48. package/dist/api/utilities/media-type.d.ts +1 -9
  49. package/dist/api/utilities/media-type.js +1 -9
  50. package/dist/api/utilities/media-type.js.map +1 -1
  51. package/dist/api/utilities/pixel-format.d.ts +1 -9
  52. package/dist/api/utilities/pixel-format.js +1 -9
  53. package/dist/api/utilities/pixel-format.js.map +1 -1
  54. package/dist/api/utilities/sample-format.d.ts +1 -9
  55. package/dist/api/utilities/sample-format.js +1 -9
  56. package/dist/api/utilities/sample-format.js.map +1 -1
  57. package/dist/api/utilities/streaming.d.ts +0 -8
  58. package/dist/api/utilities/streaming.js +0 -8
  59. package/dist/api/utilities/streaming.js.map +1 -1
  60. package/dist/api/utilities/timestamp.d.ts +0 -8
  61. package/dist/api/utilities/timestamp.js +0 -8
  62. package/dist/api/utilities/timestamp.js.map +1 -1
  63. package/dist/api/utils.js +2 -0
  64. package/dist/api/utils.js.map +1 -1
  65. package/dist/constants/constants.d.ts +1 -1
  66. package/dist/constants/constants.js +2 -0
  67. package/dist/constants/constants.js.map +1 -1
  68. package/dist/lib/binding.d.ts +1 -0
  69. package/dist/lib/binding.js +2 -0
  70. package/dist/lib/binding.js.map +1 -1
  71. package/dist/lib/codec.d.ts +4 -4
  72. package/dist/lib/codec.js +4 -4
  73. package/dist/lib/dictionary.d.ts +2 -2
  74. package/dist/lib/dictionary.js +2 -2
  75. package/dist/lib/dictionary.js.map +1 -1
  76. package/dist/lib/error.d.ts +1 -1
  77. package/dist/lib/error.js +1 -1
  78. package/dist/lib/filter-context.d.ts +19 -2
  79. package/dist/lib/filter-context.js +15 -0
  80. package/dist/lib/filter-context.js.map +1 -1
  81. package/dist/lib/format-context.d.ts +18 -18
  82. package/dist/lib/format-context.js +20 -20
  83. package/dist/lib/format-context.js.map +1 -1
  84. package/dist/lib/frame.d.ts +43 -1
  85. package/dist/lib/frame.js +53 -0
  86. package/dist/lib/frame.js.map +1 -1
  87. package/dist/lib/index.d.ts +1 -1
  88. package/dist/lib/index.js +1 -1
  89. package/dist/lib/index.js.map +1 -1
  90. package/dist/lib/native-types.d.ts +1 -0
  91. package/dist/lib/option.d.ts +176 -0
  92. package/dist/lib/option.js +176 -0
  93. package/dist/lib/option.js.map +1 -1
  94. package/dist/lib/utilities.d.ts +64 -1
  95. package/dist/lib/utilities.js +65 -0
  96. package/dist/lib/utilities.js.map +1 -1
  97. package/install/ffmpeg.js +0 -11
  98. package/package.json +16 -18
  99. package/release_notes.md +0 -48
@@ -2,7 +2,7 @@ import { Codec, CodecContext, Packet } from '../lib/index.js';
2
2
  import type { AVCodecID } from '../constants/constants.js';
3
3
  import type { FFEncoderCodec } from '../constants/encoders.js';
4
4
  import type { Frame } from '../lib/index.js';
5
- import type { EncoderOptions, StreamInfo } from './types.js';
5
+ import type { EncoderOptions } from './types.js';
6
6
  /**
7
7
  * High-level encoder for audio and video streams.
8
8
  *
@@ -14,10 +14,10 @@ import type { EncoderOptions, StreamInfo } from './types.js';
14
14
  * @example
15
15
  * ```typescript
16
16
  * import { Encoder } from 'node-av/api';
17
- * import { AV_CODEC_ID_H264 } from 'node-av/constants';
17
+ * import { AV_CODEC_ID_H264, FF_ENCODER_LIBX264 } from 'node-av/constants';
18
18
  *
19
19
  * // Create H.264 encoder
20
- * const encoder = await Encoder.create('libx264', {
20
+ * const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
21
21
  * type: 'video',
22
22
  * width: 1920,
23
23
  * height: 1080,
@@ -39,17 +39,18 @@ import type { EncoderOptions, StreamInfo } from './types.js';
39
39
  *
40
40
  * @example
41
41
  * ```typescript
42
- * // Hardware-accelerated encoding
42
+ * // Hardware-accelerated encoding with lazy initialization
43
43
  * import { HardwareContext } from 'node-av/api';
44
- * import { AV_HWDEVICE_TYPE_CUDA } from 'node-av/constants';
44
+ * import { FF_ENCODER_H264_VIDEOTOOLBOX } from 'node-av/constants';
45
45
  *
46
- * const hw = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);
47
- * const encoder = await Encoder.create('h264_nvenc', streamInfo, {
48
- * hardware: hw,
46
+ * const hw = HardwareContext.auto();
47
+ * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_H264_VIDEOTOOLBOX;
48
+ * const encoder = await Encoder.create(encoderCodec, {
49
+ * timeBase: video.timeBase,
49
50
  * bitrate: '10M'
50
51
  * });
51
52
  *
52
- * // Frames with hw_frames_ctx will be encoded on GPU
53
+ * // Hardware context will be detected from first frame's hw_frames_ctx
53
54
  * for await (const packet of encoder.packets(frames)) {
54
55
  * await output.writePacket(packet);
55
56
  * packet.free();
@@ -64,12 +65,13 @@ export declare class Encoder implements Disposable {
64
65
  private codecContext;
65
66
  private packet;
66
67
  private codec;
67
- private isOpen;
68
- private hardware?;
68
+ private initialized;
69
+ private isClosed;
70
+ private opts?;
69
71
  /**
70
72
  * @param codecContext - Configured codec context
71
73
  * @param codec - Encoder codec
72
- * @param hardware - Optional hardware context
74
+ * @param opts - Encoder options as Dictionary
73
75
  * @internal
74
76
  */
75
77
  private constructor();
@@ -77,24 +79,24 @@ export declare class Encoder implements Disposable {
77
79
  * Create an encoder with specified codec and options.
78
80
  *
79
81
  * Initializes an encoder with the appropriate codec and configuration.
80
- * Automatically configures parameters based on input stream info.
81
- * Handles hardware acceleration setup if provided.
82
+ * Uses lazy initialization - encoder is opened when first frame is received.
83
+ * Hardware context will be automatically detected from first frame if not provided.
82
84
  *
83
85
  * Direct mapping to avcodec_find_encoder_by_name() or avcodec_find_encoder().
84
86
  *
85
87
  * @param encoderCodec - Codec name, ID, or instance to use for encoding
86
- * @param input - Stream information to configure encoder
87
- * @param options - Encoder configuration options
88
+ * @param options - Encoder configuration options including required timeBase
88
89
  * @returns Configured encoder instance
89
90
  *
90
- * @throws {Error} If encoder not found or unsupported format
91
- * @throws {FFmpegError} If codec initialization fails
91
+ * @throws {Error} If encoder not found or timeBase not provided
92
+ *
93
+ * @throws {FFmpegError} If codec allocation fails
92
94
  *
93
95
  * @example
94
96
  * ```typescript
95
97
  * // From decoder stream info
96
- * const streamInfo = decoder.getOutputStreamInfo();
97
- * const encoder = await Encoder.create('libx264', streamInfo, {
98
+ * const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
99
+ * timeBase: video.timeBase,
98
100
  * bitrate: '5M',
99
101
  * gopSize: 60,
100
102
  * options: {
@@ -107,13 +109,8 @@ export declare class Encoder implements Disposable {
107
109
  * @example
108
110
  * ```typescript
109
111
  * // With custom stream info
110
- * const encoder = await Encoder.create('aac', {
111
- * type: 'audio',
112
- * sampleRate: 48000,
113
- * sampleFormat: AV_SAMPLE_FMT_FLTP,
114
- * channelLayout: AV_CH_LAYOUT_STEREO,
115
- * timeBase: { num: 1, den: 48000 }
116
- * }, {
112
+ * const encoder = await Encoder.create(FF_ENCODER_AAC, {
113
+ * timeBase: audio.timeBase,
117
114
  * bitrate: '192k'
118
115
  * });
119
116
  * ```
@@ -122,16 +119,16 @@ export declare class Encoder implements Disposable {
122
119
  * ```typescript
123
120
  * // Hardware encoder
124
121
  * const hw = HardwareContext.auto();
125
- * const encoder = await Encoder.create('hevc_videotoolbox', streamInfo, {
126
- * hardware: hw,
122
+ * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_H264_VIDEOTOOLBOX;
123
+ * const encoder = await Encoder.create(encoderCodec, {
124
+ * timeBase: video.timeBase,
127
125
  * bitrate: '8M'
128
126
  * });
129
127
  * ```
130
128
  *
131
- * @see {@link Decoder.getOutputStreamInfo} For stream info source
132
129
  * @see {@link EncoderOptions} For configuration options
133
130
  */
134
- static create(encoderCodec: FFEncoderCodec | AVCodecID | Codec, input: StreamInfo, options?: EncoderOptions): Promise<Encoder>;
131
+ static create(encoderCodec: FFEncoderCodec | AVCodecID | Codec, options: EncoderOptions): Promise<Encoder>;
135
132
  /**
136
133
  * Check if encoder is open.
137
134
  *
@@ -143,6 +140,22 @@ export declare class Encoder implements Disposable {
143
140
  * ```
144
141
  */
145
142
  get isEncoderOpen(): boolean;
143
+ /**
144
+ * Check if encoder has been initialized.
145
+ *
146
+ * Returns true after first frame has been processed and encoder opened.
147
+ * Useful for checking if encoder has received frame properties.
148
+ *
149
+ * @returns true if encoder has been initialized with frame data
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * if (!encoder.isEncoderInitialized) {
154
+ * console.log('Encoder will initialize on first frame');
155
+ * }
156
+ * ```
157
+ */
158
+ get isEncoderInitialized(): boolean;
146
159
  /**
147
160
  * Check if encoder uses hardware acceleration.
148
161
  *
@@ -158,12 +171,25 @@ export declare class Encoder implements Disposable {
158
171
  * @see {@link HardwareContext} For hardware setup
159
172
  */
160
173
  isHardware(): boolean;
174
+ /**
175
+ * Check if encoder is ready for processing.
176
+ *
177
+ * @returns true if initialized and ready
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * if (encoder.isReady()) {
182
+ * const packet = await encoder.encode(frame);
183
+ * }
184
+ * ```
185
+ */
186
+ isReady(): boolean;
161
187
  /**
162
188
  * Encode a frame to a packet.
163
189
  *
164
190
  * Sends a frame to the encoder and attempts to receive an encoded packet.
191
+ * On first frame, automatically initializes encoder with frame properties.
165
192
  * Handles internal buffering - may return null if more frames needed.
166
- * Automatically manages encoder state and hardware context binding.
167
193
  *
168
194
  * Direct mapping to avcodec_send_frame() and avcodec_receive_packet().
169
195
  *
@@ -171,6 +197,7 @@ export declare class Encoder implements Disposable {
171
197
  * @returns Encoded packet or null if more data needed
172
198
  *
173
199
  * @throws {Error} If encoder is closed
200
+ *
174
201
  * @throws {FFmpegError} If encoding fails
175
202
  *
176
203
  * @example
@@ -209,8 +236,9 @@ export declare class Encoder implements Disposable {
209
236
  * Primary interface for stream-based encoding.
210
237
  *
211
238
  * @param frames - Async iterable of frames (freed automatically)
212
- * @yields Encoded packets (caller must free)
239
+ * @yields {Packet} Encoded packets (caller must free)
213
240
  * @throws {Error} If encoder is closed
241
+ *
214
242
  * @throws {FFmpegError} If encoding fails
215
243
  *
216
244
  * @example
@@ -227,11 +255,11 @@ export declare class Encoder implements Disposable {
227
255
  * // With frame filtering
228
256
  * async function* filteredFrames() {
229
257
  * for await (const frame of decoder.frames(input.packets())) {
230
- * await filter.filterFrame(frame);
231
- * const filtered = await filter.getFrame();
258
+ * const filtered = await filter.process(frame);
232
259
  * if (filtered) {
233
260
  * yield filtered;
234
261
  * }
262
+ * frame.free();
235
263
  * }
236
264
  * }
237
265
  *
@@ -260,23 +288,22 @@ export declare class Encoder implements Disposable {
260
288
  */
261
289
  packets(frames: AsyncIterable<Frame>): AsyncGenerator<Packet>;
262
290
  /**
263
- * Flush encoder and get buffered packet.
291
+ * Flush encoder and signal end-of-stream.
264
292
  *
265
- * Signals end-of-stream and retrieves remaining packets.
266
- * Call repeatedly until null to get all buffered packets.
267
- * Essential for ensuring all frames are encoded.
293
+ * Sends null frame to encoder to signal end-of-stream.
294
+ * Does nothing if encoder was never initialized or is closed.
295
+ * Must call receive() to get remaining buffered packets.
268
296
  *
269
297
  * Direct mapping to avcodec_send_frame(NULL).
270
298
  *
271
- * @returns Buffered packet or null if none remaining
272
- *
273
- * @throws {Error} If encoder is closed
274
- *
275
299
  * @example
276
300
  * ```typescript
277
- * // Flush remaining packets
301
+ * // Signal end of stream
302
+ * await encoder.flush();
303
+ *
304
+ * // Then get remaining packets
278
305
  * let packet;
279
- * while ((packet = await encoder.flush()) !== null) {
306
+ * while ((packet = await encoder.receive()) !== null) {
280
307
  * console.log('Got buffered packet');
281
308
  * await output.writePacket(packet);
282
309
  * packet.free();
@@ -284,18 +311,17 @@ export declare class Encoder implements Disposable {
284
311
  * ```
285
312
  *
286
313
  * @see {@link flushPackets} For async iteration
287
- * @see {@link packets} For complete encoding pipeline
314
+ * @see {@link receive} For getting buffered packets
288
315
  */
289
- flush(): Promise<Packet | null>;
316
+ flush(): Promise<void>;
290
317
  /**
291
318
  * Flush all buffered packets as async generator.
292
319
  *
293
320
  * Convenient async iteration over remaining packets.
294
- * Automatically handles repeated flush calls.
295
- * Useful for end-of-stream processing.
321
+ * Automatically handles flush and repeated receive calls.
322
+ * Returns immediately if encoder was never initialized or is closed.
296
323
  *
297
- * @yields Buffered packets
298
- * @throws {Error} If encoder is closed
324
+ * @yields {Packet} Buffered packets
299
325
  *
300
326
  * @example
301
327
  * ```typescript
@@ -307,21 +333,59 @@ export declare class Encoder implements Disposable {
307
333
  * }
308
334
  * ```
309
335
  *
310
- * @see {@link flush} For single packet flush
336
+ * @see {@link flush} For signaling end-of-stream
311
337
  * @see {@link packets} For complete pipeline
312
338
  */
313
339
  flushPackets(): AsyncGenerator<Packet>;
340
+ /**
341
+ * Receive packet from encoder.
342
+ *
343
+ * Gets encoded packets from the codec's internal buffer.
344
+ * Handles packet cloning and error checking.
345
+ * Returns null if encoder is closed, not initialized, or no packets available.
346
+ * Call repeatedly until null to drain all buffered packets.
347
+ *
348
+ * Direct mapping to avcodec_receive_packet().
349
+ *
350
+ * @returns Cloned packet or null if no packets available
351
+ *
352
+ * @throws {FFmpegError} If receive fails with error other than AVERROR_EAGAIN or AVERROR_EOF
353
+ *
354
+ * @example
355
+ * ```typescript
356
+ * const packet = await encoder.receive();
357
+ * if (packet) {
358
+ * console.log(`Got packet with PTS: ${packet.pts}`);
359
+ * await output.writePacket(packet);
360
+ * packet.free();
361
+ * }
362
+ * ```
363
+ *
364
+ * @example
365
+ * ```typescript
366
+ * // Drain all buffered packets
367
+ * let packet;
368
+ * while ((packet = await encoder.receive()) !== null) {
369
+ * console.log(`Packet size: ${packet.size}`);
370
+ * await output.writePacket(packet);
371
+ * packet.free();
372
+ * }
373
+ * ```
374
+ *
375
+ * @see {@link encode} For sending frames and receiving packets
376
+ * @see {@link flush} For signaling end-of-stream
377
+ */
378
+ receive(): Promise<Packet | null>;
314
379
  /**
315
380
  * Close encoder and free resources.
316
381
  *
317
382
  * Releases codec context and internal packet buffer.
318
383
  * Safe to call multiple times.
319
- * Does NOT dispose hardware context - caller is responsible.
320
384
  * Automatically called by Symbol.dispose.
321
385
  *
322
386
  * @example
323
387
  * ```typescript
324
- * const encoder = await Encoder.create('libx264', streamInfo);
388
+ * const encoder = await Encoder.create(FF_ENCODER_LIBX264, { ... });
325
389
  * try {
326
390
  * // Use encoder
327
391
  * } finally {
@@ -332,6 +396,20 @@ export declare class Encoder implements Disposable {
332
396
  * @see {@link Symbol.dispose} For automatic cleanup
333
397
  */
334
398
  close(): void;
399
+ /**
400
+ * Initialize encoder from first frame.
401
+ *
402
+ * Sets codec context parameters from frame properties.
403
+ * Configures hardware context if present in frame.
404
+ * Opens encoder with accumulated options.
405
+ *
406
+ * @param frame - First frame to encode
407
+ *
408
+ * @throws {FFmpegError} If encoder open fails
409
+ *
410
+ * @internal
411
+ */
412
+ private initialize;
335
413
  /**
336
414
  * Get encoder codec.
337
415
  *
@@ -340,40 +418,25 @@ export declare class Encoder implements Disposable {
340
418
  *
341
419
  * @returns Codec instance
342
420
  *
343
- * @example
344
- * ```typescript
345
- * const codec = encoder.getCodec();
346
- * console.log(`Using codec: ${codec.name}`);
347
- * console.log(`Capabilities: ${codec.capabilities}`);
348
- * ```
421
+ * @internal
349
422
  *
350
- * @see {@link Codec} For codec properties
423
+ * @see {@link Codec} For codec details
351
424
  */
352
425
  getCodec(): Codec;
353
426
  /**
354
427
  * Get underlying codec context.
355
428
  *
356
- * Returns the internal codec context for advanced operations.
357
- * Returns null if encoder is closed.
429
+ * Returns the codec context for advanced operations.
430
+ * Useful for accessing low-level codec properties and settings.
431
+ * Returns null if encoder is closed or not initialized.
358
432
  *
359
- * @returns Codec context or null
433
+ * @returns Codec context or null if closed/not initialized
360
434
  *
361
435
  * @internal
362
- */
363
- getCodecContext(): CodecContext | null;
364
- /**
365
- * Receive packet from encoder.
366
436
  *
367
- * Internal method to get encoded packets from codec.
368
- * Handles packet cloning and error checking.
369
- *
370
- * Direct mapping to avcodec_receive_packet().
371
- *
372
- * @returns Cloned packet or null
373
- *
374
- * @throws {FFmpegError} If receive fails with error other than AVERROR_EAGAIN or AVERROR_EOF
437
+ * @see {@link CodecContext} For context details
375
438
  */
376
- private receivePacket;
439
+ getCodecContext(): CodecContext | null;
377
440
  /**
378
441
  * Dispose of encoder.
379
442
  *
@@ -383,7 +446,7 @@ export declare class Encoder implements Disposable {
383
446
  * @example
384
447
  * ```typescript
385
448
  * {
386
- * using encoder = await Encoder.create('libx264', streamInfo);
449
+ * using encoder = await Encoder.create(FF_ENCODER_LIBX264, { ... });
387
450
  * // Encode frames...
388
451
  * } // Automatically closed
389
452
  * ```