node-av 1.3.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 (45) hide show
  1. package/README.md +37 -38
  2. package/dist/api/bitstream-filter.d.ts +2 -2
  3. package/dist/api/bitstream-filter.js +2 -2
  4. package/dist/api/decoder.d.ts +131 -120
  5. package/dist/api/decoder.js +191 -203
  6. package/dist/api/decoder.js.map +1 -1
  7. package/dist/api/encoder.d.ts +135 -77
  8. package/dist/api/encoder.js +235 -192
  9. package/dist/api/encoder.js.map +1 -1
  10. package/dist/api/filter-presets.d.ts +408 -1534
  11. package/dist/api/filter-presets.js +1005 -2058
  12. package/dist/api/filter-presets.js.map +1 -1
  13. package/dist/api/filter.d.ts +160 -165
  14. package/dist/api/filter.js +294 -374
  15. package/dist/api/filter.js.map +1 -1
  16. package/dist/api/hardware.d.ts +8 -31
  17. package/dist/api/hardware.js +19 -70
  18. package/dist/api/hardware.js.map +1 -1
  19. package/dist/api/index.d.ts +1 -1
  20. package/dist/api/index.js +1 -1
  21. package/dist/api/index.js.map +1 -1
  22. package/dist/api/media-input.d.ts +1 -1
  23. package/dist/api/media-input.js +3 -8
  24. package/dist/api/media-input.js.map +1 -1
  25. package/dist/api/media-output.d.ts +35 -128
  26. package/dist/api/media-output.js +136 -208
  27. package/dist/api/media-output.js.map +1 -1
  28. package/dist/api/pipeline.d.ts +17 -17
  29. package/dist/api/pipeline.js +19 -42
  30. package/dist/api/pipeline.js.map +1 -1
  31. package/dist/api/types.d.ts +17 -57
  32. package/dist/lib/dictionary.d.ts +2 -2
  33. package/dist/lib/dictionary.js +2 -2
  34. package/dist/lib/dictionary.js.map +1 -1
  35. package/dist/lib/filter-context.d.ts +19 -2
  36. package/dist/lib/filter-context.js +15 -0
  37. package/dist/lib/filter-context.js.map +1 -1
  38. package/dist/lib/format-context.d.ts +18 -18
  39. package/dist/lib/format-context.js +20 -20
  40. package/dist/lib/format-context.js.map +1 -1
  41. package/dist/lib/frame.d.ts +43 -1
  42. package/dist/lib/frame.js +53 -0
  43. package/dist/lib/frame.js.map +1 -1
  44. package/package.json +17 -17
  45. package/release_notes.md +0 -29
@@ -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
  *
@@ -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,25 +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 {Error} If encoder not found or timeBase not provided
91
92
  *
92
- * @throws {FFmpegError} If codec initialization fails
93
+ * @throws {FFmpegError} If codec allocation fails
93
94
  *
94
95
  * @example
95
96
  * ```typescript
96
97
  * // From decoder stream info
97
- * const streamInfo = decoder.getOutputStreamInfo();
98
- * const encoder = await Encoder.create(FF_ENCODER_LIBX264, streamInfo, {
98
+ * const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
99
+ * timeBase: video.timeBase,
99
100
  * bitrate: '5M',
100
101
  * gopSize: 60,
101
102
  * options: {
@@ -109,12 +110,7 @@ export declare class Encoder implements Disposable {
109
110
  * ```typescript
110
111
  * // With custom stream info
111
112
  * const encoder = await Encoder.create(FF_ENCODER_AAC, {
112
- * type: 'audio',
113
- * sampleRate: 48000,
114
- * sampleFormat: AV_SAMPLE_FMT_FLTP,
115
- * channelLayout: AV_CH_LAYOUT_STEREO,
116
- * timeBase: { num: 1, den: 48000 }
117
- * }, {
113
+ * timeBase: audio.timeBase,
118
114
  * bitrate: '192k'
119
115
  * });
120
116
  * ```
@@ -123,16 +119,16 @@ export declare class Encoder implements Disposable {
123
119
  * ```typescript
124
120
  * // Hardware encoder
125
121
  * const hw = HardwareContext.auto();
126
- * const encoder = await Encoder.create('hevc_videotoolbox', streamInfo, {
127
- * hardware: hw,
122
+ * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_H264_VIDEOTOOLBOX;
123
+ * const encoder = await Encoder.create(encoderCodec, {
124
+ * timeBase: video.timeBase,
128
125
  * bitrate: '8M'
129
126
  * });
130
127
  * ```
131
128
  *
132
- * @see {@link Decoder.getOutputStreamInfo} For stream info source
133
129
  * @see {@link EncoderOptions} For configuration options
134
130
  */
135
- static create(encoderCodec: FFEncoderCodec | AVCodecID | Codec, input: StreamInfo, options?: EncoderOptions): Promise<Encoder>;
131
+ static create(encoderCodec: FFEncoderCodec | AVCodecID | Codec, options: EncoderOptions): Promise<Encoder>;
136
132
  /**
137
133
  * Check if encoder is open.
138
134
  *
@@ -144,6 +140,22 @@ export declare class Encoder implements Disposable {
144
140
  * ```
145
141
  */
146
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;
147
159
  /**
148
160
  * Check if encoder uses hardware acceleration.
149
161
  *
@@ -159,12 +171,25 @@ export declare class Encoder implements Disposable {
159
171
  * @see {@link HardwareContext} For hardware setup
160
172
  */
161
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;
162
187
  /**
163
188
  * Encode a frame to a packet.
164
189
  *
165
190
  * Sends a frame to the encoder and attempts to receive an encoded packet.
191
+ * On first frame, automatically initializes encoder with frame properties.
166
192
  * Handles internal buffering - may return null if more frames needed.
167
- * Automatically manages encoder state and hardware context binding.
168
193
  *
169
194
  * Direct mapping to avcodec_send_frame() and avcodec_receive_packet().
170
195
  *
@@ -211,7 +236,7 @@ export declare class Encoder implements Disposable {
211
236
  * Primary interface for stream-based encoding.
212
237
  *
213
238
  * @param frames - Async iterable of frames (freed automatically)
214
- * @yields Encoded packets (caller must free)
239
+ * @yields {Packet} Encoded packets (caller must free)
215
240
  * @throws {Error} If encoder is closed
216
241
  *
217
242
  * @throws {FFmpegError} If encoding fails
@@ -230,11 +255,11 @@ export declare class Encoder implements Disposable {
230
255
  * // With frame filtering
231
256
  * async function* filteredFrames() {
232
257
  * for await (const frame of decoder.frames(input.packets())) {
233
- * await filter.filterFrame(frame);
234
- * const filtered = await filter.getFrame();
258
+ * const filtered = await filter.process(frame);
235
259
  * if (filtered) {
236
260
  * yield filtered;
237
261
  * }
262
+ * frame.free();
238
263
  * }
239
264
  * }
240
265
  *
@@ -263,23 +288,22 @@ export declare class Encoder implements Disposable {
263
288
  */
264
289
  packets(frames: AsyncIterable<Frame>): AsyncGenerator<Packet>;
265
290
  /**
266
- * Flush encoder and get buffered packet.
291
+ * Flush encoder and signal end-of-stream.
267
292
  *
268
- * Signals end-of-stream and retrieves remaining packets.
269
- * Call repeatedly until null to get all buffered packets.
270
- * 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.
271
296
  *
272
297
  * Direct mapping to avcodec_send_frame(NULL).
273
298
  *
274
- * @returns Buffered packet or null if none remaining
275
- *
276
- * @throws {Error} If encoder is closed
277
- *
278
299
  * @example
279
300
  * ```typescript
280
- * // Flush remaining packets
301
+ * // Signal end of stream
302
+ * await encoder.flush();
303
+ *
304
+ * // Then get remaining packets
281
305
  * let packet;
282
- * while ((packet = await encoder.flush()) !== null) {
306
+ * while ((packet = await encoder.receive()) !== null) {
283
307
  * console.log('Got buffered packet');
284
308
  * await output.writePacket(packet);
285
309
  * packet.free();
@@ -287,18 +311,17 @@ export declare class Encoder implements Disposable {
287
311
  * ```
288
312
  *
289
313
  * @see {@link flushPackets} For async iteration
290
- * @see {@link packets} For complete encoding pipeline
314
+ * @see {@link receive} For getting buffered packets
291
315
  */
292
- flush(): Promise<Packet | null>;
316
+ flush(): Promise<void>;
293
317
  /**
294
318
  * Flush all buffered packets as async generator.
295
319
  *
296
320
  * Convenient async iteration over remaining packets.
297
- * Automatically handles repeated flush calls.
298
- * 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.
299
323
  *
300
- * @yields Buffered packets
301
- * @throws {Error} If encoder is closed
324
+ * @yields {Packet} Buffered packets
302
325
  *
303
326
  * @example
304
327
  * ```typescript
@@ -310,21 +333,59 @@ export declare class Encoder implements Disposable {
310
333
  * }
311
334
  * ```
312
335
  *
313
- * @see {@link flush} For single packet flush
336
+ * @see {@link flush} For signaling end-of-stream
314
337
  * @see {@link packets} For complete pipeline
315
338
  */
316
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>;
317
379
  /**
318
380
  * Close encoder and free resources.
319
381
  *
320
382
  * Releases codec context and internal packet buffer.
321
383
  * Safe to call multiple times.
322
- * Does NOT dispose hardware context - caller is responsible.
323
384
  * Automatically called by Symbol.dispose.
324
385
  *
325
386
  * @example
326
387
  * ```typescript
327
- * const encoder = await Encoder.create(FF_ENCODER_LIBX264, streamInfo);
388
+ * const encoder = await Encoder.create(FF_ENCODER_LIBX264, { ... });
328
389
  * try {
329
390
  * // Use encoder
330
391
  * } finally {
@@ -335,6 +396,20 @@ export declare class Encoder implements Disposable {
335
396
  * @see {@link Symbol.dispose} For automatic cleanup
336
397
  */
337
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;
338
413
  /**
339
414
  * Get encoder codec.
340
415
  *
@@ -343,42 +418,25 @@ export declare class Encoder implements Disposable {
343
418
  *
344
419
  * @returns Codec instance
345
420
  *
346
- * @example
347
- * ```typescript
348
- * const codec = encoder.getCodec();
349
- * console.log(`Using codec: ${codec.name}`);
350
- * console.log(`Capabilities: ${codec.capabilities}`);
351
- * ```
421
+ * @internal
352
422
  *
353
- * @see {@link Codec} For codec properties
423
+ * @see {@link Codec} For codec details
354
424
  */
355
425
  getCodec(): Codec;
356
426
  /**
357
427
  * Get underlying codec context.
358
428
  *
359
- * Returns the internal codec context for advanced operations.
360
- * 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.
361
432
  *
362
- * @returns Codec context or null
433
+ * @returns Codec context or null if closed/not initialized
363
434
  *
364
435
  * @internal
365
- */
366
- getCodecContext(): CodecContext | null;
367
- /**
368
- * Receive packet from encoder.
369
436
  *
370
- * Internal method to get encoded packets from codec.
371
- * Handles packet cloning and error checking.
372
- *
373
- * Direct mapping to avcodec_receive_packet().
374
- *
375
- * @returns Cloned packet or null
376
- *
377
- * @throws {FFmpegError} If receive fails with error other than AVERROR_EAGAIN or AVERROR_EOF
378
- *
379
- * @internal
437
+ * @see {@link CodecContext} For context details
380
438
  */
381
- private receivePacket;
439
+ getCodecContext(): CodecContext | null;
382
440
  /**
383
441
  * Dispose of encoder.
384
442
  *
@@ -388,7 +446,7 @@ export declare class Encoder implements Disposable {
388
446
  * @example
389
447
  * ```typescript
390
448
  * {
391
- * using encoder = await Encoder.create(FF_ENCODER_LIBX264, streamInfo);
449
+ * using encoder = await Encoder.create(FF_ENCODER_LIBX264, { ... });
392
450
  * // Encode frames...
393
451
  * } // Automatically closed
394
452
  * ```