node-av 5.0.4 → 5.1.1
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/BENCHMARK.md +113 -0
- package/README.md +59 -1
- package/dist/api/bitstream-filter.d.ts +190 -74
- package/dist/api/bitstream-filter.js +276 -222
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/decoder.d.ts +23 -29
- package/dist/api/decoder.js +37 -47
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/encoder.d.ts +4 -4
- package/dist/api/encoder.js +16 -20
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter-complex.js +7 -3
- package/dist/api/filter-complex.js.map +1 -1
- package/dist/api/filter.d.ts +4 -4
- package/dist/api/filter.js +18 -16
- package/dist/api/filter.js.map +1 -1
- package/dist/api/hardware.d.ts +17 -0
- package/dist/api/hardware.js +73 -27
- package/dist/api/hardware.js.map +1 -1
- package/dist/api/muxer.js +8 -4
- package/dist/api/muxer.js.map +1 -1
- package/dist/api/rtp-stream.js +0 -6
- package/dist/api/rtp-stream.js.map +1 -1
- package/dist/api/types.d.ts +29 -9
- package/dist/constants/constants.d.ts +6 -3
- package/dist/constants/constants.js +5 -5
- package/dist/constants/constants.js.map +1 -1
- package/dist/ffmpeg/index.js +3 -4
- package/dist/ffmpeg/index.js.map +1 -1
- package/dist/lib/binding.js +3 -4
- package/dist/lib/binding.js.map +1 -1
- package/dist/lib/codec-context.d.ts +5 -3
- package/dist/lib/codec-context.js +2 -0
- package/dist/lib/codec-context.js.map +1 -1
- package/dist/lib/native-types.d.ts +2 -2
- package/dist/utils/electron.d.ts +49 -0
- package/dist/utils/electron.js +63 -0
- package/dist/utils/electron.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +32 -15
- package/binding.gyp +0 -166
|
@@ -140,6 +140,8 @@ export class BitStreamFilterAPI {
|
|
|
140
140
|
*
|
|
141
141
|
* @param stream - Stream to apply filter to
|
|
142
142
|
*
|
|
143
|
+
* @param filterOptions - Optional filter-specific options
|
|
144
|
+
*
|
|
143
145
|
* @returns Configured bitstream filter
|
|
144
146
|
*
|
|
145
147
|
* @throws {Error} If initialization fails
|
|
@@ -160,13 +162,24 @@ export class BitStreamFilterAPI {
|
|
|
160
162
|
*
|
|
161
163
|
* @example
|
|
162
164
|
* ```typescript
|
|
163
|
-
* // Remove
|
|
164
|
-
* const filter = BitStreamFilterAPI.create('
|
|
165
|
+
* // Remove AUDs from H.264 stream
|
|
166
|
+
* const filter = BitStreamFilterAPI.create('h264_metadata', stream, {
|
|
167
|
+
* options: { aud: 'remove' }
|
|
168
|
+
* });
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* // Set H.264 level
|
|
174
|
+
* const filter = BitStreamFilterAPI.create('h264_metadata', stream, {
|
|
175
|
+
* options: { level: 51 }
|
|
176
|
+
* });
|
|
165
177
|
* ```
|
|
166
178
|
*
|
|
167
179
|
* @see {@link BitStreamFilter.getByName} For filter discovery
|
|
180
|
+
* @see {@link BitstreamFilterOptions} For available options
|
|
168
181
|
*/
|
|
169
|
-
static create(filterName, stream) {
|
|
182
|
+
static create(filterName, stream, filterOptions) {
|
|
170
183
|
if (!stream) {
|
|
171
184
|
throw new Error('Stream is required');
|
|
172
185
|
}
|
|
@@ -187,6 +200,13 @@ export class BitStreamFilterAPI {
|
|
|
187
200
|
stream.codecpar.copy(ctx.inputCodecParameters);
|
|
188
201
|
// Set time base
|
|
189
202
|
ctx.inputTimeBase = stream.timeBase;
|
|
203
|
+
// Apply filter-specific options before init
|
|
204
|
+
if (filterOptions?.options) {
|
|
205
|
+
for (const [key, value] of Object.entries(filterOptions.options)) {
|
|
206
|
+
const ret = ctx.setOption(key, value);
|
|
207
|
+
FFmpegError.throwIfError(ret, `Failed to set bitstream filter option '${key}'`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
190
210
|
// Initialize the filter
|
|
191
211
|
const initRet = ctx.init();
|
|
192
212
|
FFmpegError.throwIfError(initRet, 'Failed to initialize bitstream filter');
|
|
@@ -252,115 +272,129 @@ export class BitStreamFilterAPI {
|
|
|
252
272
|
return !this.isClosed;
|
|
253
273
|
}
|
|
254
274
|
/**
|
|
255
|
-
*
|
|
275
|
+
* Send a packet to the filter.
|
|
256
276
|
*
|
|
257
|
-
* Sends a packet to the filter
|
|
258
|
-
*
|
|
277
|
+
* Sends a packet to the filter for processing.
|
|
278
|
+
* Does not return filtered packets - use {@link receive} to retrieve packets.
|
|
279
|
+
* A single packet can produce zero, one, or multiple packets depending on filter.
|
|
259
280
|
*
|
|
260
|
-
* **
|
|
261
|
-
*
|
|
262
|
-
* To receive all packets from a packet, use {@link filterAll} or {@link packets} instead.
|
|
281
|
+
* **Important**: This method only SENDS the packet to the filter.
|
|
282
|
+
* You must call {@link receive} separately (potentially multiple times) to get filtered packets.
|
|
263
283
|
*
|
|
264
|
-
* Direct mapping to av_bsf_send_packet()
|
|
284
|
+
* Direct mapping to av_bsf_send_packet().
|
|
265
285
|
*
|
|
266
|
-
* @param packet - Packet to filter
|
|
286
|
+
* @param packet - Packet to send to filter, or null to flush
|
|
267
287
|
*
|
|
268
|
-
* @
|
|
269
|
-
*
|
|
270
|
-
* @throws {FFmpegError} If filtering fails
|
|
288
|
+
* @throws {FFmpegError} If sending fails
|
|
271
289
|
*
|
|
272
290
|
* @example
|
|
273
291
|
* ```typescript
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
292
|
+
* // Send packet and receive filtered packets
|
|
293
|
+
* await filter.filter(inputPacket);
|
|
294
|
+
*
|
|
295
|
+
* // Receive all available filtered packets
|
|
296
|
+
* while (true) {
|
|
297
|
+
* const outPacket = await filter.receive();
|
|
298
|
+
* if (!outPacket) break;
|
|
299
|
+
* console.log(`Filtered packet with PTS: ${outPacket.pts}`);
|
|
277
300
|
* await output.writePacket(outPacket);
|
|
278
301
|
* outPacket.free();
|
|
279
302
|
* }
|
|
280
303
|
* ```
|
|
281
304
|
*
|
|
282
|
-
* @
|
|
283
|
-
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* for await (const packet of input.packets()) {
|
|
308
|
+
* // packet is null at end of stream - automatically flushes filter
|
|
309
|
+
* await filter.filter(packet);
|
|
310
|
+
*
|
|
311
|
+
* // Receive available filtered packets
|
|
312
|
+
* let outPacket;
|
|
313
|
+
* while ((outPacket = await filter.receive())) {
|
|
314
|
+
* await output.writePacket(outPacket);
|
|
315
|
+
* outPacket.free();
|
|
316
|
+
* }
|
|
317
|
+
* }
|
|
318
|
+
* ```
|
|
319
|
+
*
|
|
320
|
+
* @see {@link receive} For receiving filtered packets
|
|
321
|
+
* @see {@link filterAll} For combined send+receive operation
|
|
322
|
+
* @see {@link packets} For automatic packet iteration
|
|
284
323
|
* @see {@link flush} For end-of-stream handling
|
|
285
324
|
* @see {@link filterSync} For synchronous version
|
|
286
325
|
*/
|
|
287
326
|
async filter(packet) {
|
|
288
327
|
if (this.isClosed) {
|
|
289
|
-
return
|
|
328
|
+
return;
|
|
290
329
|
}
|
|
291
|
-
// Send packet to filter
|
|
330
|
+
// Send packet to filter (null signals EOF/flush)
|
|
292
331
|
const sendRet = await this.ctx.sendPacket(packet);
|
|
293
|
-
|
|
294
|
-
if (sendRet === AVERROR_EAGAIN) {
|
|
295
|
-
// Filter is full, receive a packet first
|
|
296
|
-
const outPacket = await this.receive();
|
|
297
|
-
if (outPacket) {
|
|
298
|
-
return outPacket;
|
|
299
|
-
}
|
|
300
|
-
// If receive() returned null, this is unexpected - treat as error
|
|
301
|
-
throw new Error('Filter returned EAGAIN but no packet available');
|
|
302
|
-
}
|
|
303
|
-
if (sendRet < 0 && sendRet !== AVERROR_EOF) {
|
|
332
|
+
if (sendRet < 0 && sendRet !== AVERROR_EOF && sendRet !== AVERROR_EAGAIN) {
|
|
304
333
|
FFmpegError.throwIfError(sendRet, 'Failed to send packet to bitstream filter');
|
|
305
334
|
}
|
|
306
|
-
// Try to receive packet
|
|
307
|
-
return await this.receive();
|
|
308
335
|
}
|
|
309
336
|
/**
|
|
310
|
-
*
|
|
337
|
+
* Send a packet to the filter synchronously.
|
|
311
338
|
* Synchronous version of filter.
|
|
312
339
|
*
|
|
313
|
-
* Sends a packet to the filter
|
|
314
|
-
*
|
|
315
|
-
*
|
|
316
|
-
* **Note**: This method receives only ONE packet per call.
|
|
317
|
-
* A single packet can produce multiple output packets (e.g., codec buffering).
|
|
318
|
-
* To receive all packets from a packet, use {@link filterAllSync} or {@link packetsSync} instead.
|
|
340
|
+
* Sends a packet to the filter for processing.
|
|
341
|
+
* Does not return filtered packets - use {@link receiveSync} to retrieve packets.
|
|
342
|
+
* A single packet can produce zero, one, or multiple packets depending on filter.
|
|
319
343
|
*
|
|
320
|
-
*
|
|
344
|
+
* **Important**: This method only SENDS the packet to the filter.
|
|
345
|
+
* You must call {@link receiveSync} separately (potentially multiple times) to get filtered packets.
|
|
321
346
|
*
|
|
322
|
-
*
|
|
347
|
+
* Direct mapping to av_bsf_send_packet().
|
|
323
348
|
*
|
|
324
|
-
* @
|
|
349
|
+
* @param packet - Packet to send to filter, or null to flush
|
|
325
350
|
*
|
|
326
|
-
* @throws {FFmpegError} If
|
|
351
|
+
* @throws {FFmpegError} If sending fails
|
|
327
352
|
*
|
|
328
353
|
* @example
|
|
329
354
|
* ```typescript
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
355
|
+
* // Send packet and receive filtered packets
|
|
356
|
+
* filter.filterSync(inputPacket);
|
|
357
|
+
*
|
|
358
|
+
* // Receive all available filtered packets
|
|
359
|
+
* while (true) {
|
|
360
|
+
* const outPacket = filter.receiveSync();
|
|
361
|
+
* if (!outPacket) break;
|
|
362
|
+
* console.log(`Filtered packet with PTS: ${outPacket.pts}`);
|
|
333
363
|
* output.writePacketSync(outPacket);
|
|
334
364
|
* outPacket.free();
|
|
335
365
|
* }
|
|
336
366
|
* ```
|
|
337
367
|
*
|
|
338
|
-
* @
|
|
339
|
-
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript
|
|
370
|
+
* for (const packet of packets) {
|
|
371
|
+
* // packet is null at end of stream - automatically flushes filter
|
|
372
|
+
* filter.filterSync(packet);
|
|
373
|
+
*
|
|
374
|
+
* // Receive available filtered packets
|
|
375
|
+
* let outPacket;
|
|
376
|
+
* while ((outPacket = filter.receiveSync())) {
|
|
377
|
+
* output.writePacketSync(outPacket);
|
|
378
|
+
* outPacket.free();
|
|
379
|
+
* }
|
|
380
|
+
* }
|
|
381
|
+
* ```
|
|
382
|
+
*
|
|
383
|
+
* @see {@link receiveSync} For receiving filtered packets
|
|
384
|
+
* @see {@link filterAllSync} For combined send+receive operation
|
|
385
|
+
* @see {@link packetsSync} For automatic packet iteration
|
|
340
386
|
* @see {@link flushSync} For end-of-stream handling
|
|
341
387
|
* @see {@link filter} For async version
|
|
342
388
|
*/
|
|
343
389
|
filterSync(packet) {
|
|
344
390
|
if (this.isClosed) {
|
|
345
|
-
return
|
|
391
|
+
return;
|
|
346
392
|
}
|
|
347
|
-
// Send packet to filter
|
|
393
|
+
// Send packet to filter (null signals EOF/flush)
|
|
348
394
|
const sendRet = this.ctx.sendPacketSync(packet);
|
|
349
|
-
|
|
350
|
-
if (sendRet === AVERROR_EAGAIN) {
|
|
351
|
-
// Filter is full, receive a packet first
|
|
352
|
-
const outPacket = this.receiveSync();
|
|
353
|
-
if (outPacket) {
|
|
354
|
-
return outPacket;
|
|
355
|
-
}
|
|
356
|
-
// If receive() returned null, this is unexpected - treat as error
|
|
357
|
-
throw new Error('Filter returned EAGAIN but no packet available');
|
|
358
|
-
}
|
|
359
|
-
if (sendRet < 0 && sendRet !== AVERROR_EOF) {
|
|
395
|
+
if (sendRet < 0 && sendRet !== AVERROR_EOF && sendRet !== AVERROR_EAGAIN) {
|
|
360
396
|
FFmpegError.throwIfError(sendRet, 'Failed to send packet to bitstream filter');
|
|
361
397
|
}
|
|
362
|
-
// Try to receive packet
|
|
363
|
-
return this.receiveSync();
|
|
364
398
|
}
|
|
365
399
|
/**
|
|
366
400
|
* Filter a packet to packets.
|
|
@@ -371,7 +405,7 @@ export class BitStreamFilterAPI {
|
|
|
371
405
|
*
|
|
372
406
|
* Direct mapping to av_bsf_send_packet() and av_bsf_receive_packet().
|
|
373
407
|
*
|
|
374
|
-
* @param packet - Packet to filter
|
|
408
|
+
* @param packet - Packet to filter, or null to flush
|
|
375
409
|
*
|
|
376
410
|
* @returns Array of filtered packets (empty if more data needed or filter is closed)
|
|
377
411
|
*
|
|
@@ -387,22 +421,25 @@ export class BitStreamFilterAPI {
|
|
|
387
421
|
* }
|
|
388
422
|
* ```
|
|
389
423
|
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```typescript
|
|
426
|
+
* // Flush remaining packets at end of stream
|
|
427
|
+
* const remaining = await filter.filterAll(null);
|
|
428
|
+
* for (const packet of remaining) {
|
|
429
|
+
* await output.writePacket(packet);
|
|
430
|
+
* packet.free();
|
|
431
|
+
* }
|
|
432
|
+
* ```
|
|
433
|
+
*
|
|
390
434
|
* @see {@link filter} For single packet filtering
|
|
391
435
|
* @see {@link packets} For stream processing
|
|
392
436
|
* @see {@link flush} For end-of-stream handling
|
|
393
437
|
* @see {@link filterAllSync} For synchronous version
|
|
394
438
|
*/
|
|
395
439
|
async filterAll(packet) {
|
|
396
|
-
|
|
397
|
-
return [];
|
|
398
|
-
}
|
|
399
|
-
const outputPackets = [];
|
|
400
|
-
// Send packet to filter
|
|
401
|
-
const sendRet = await this.ctx.sendPacket(packet);
|
|
402
|
-
if (sendRet < 0 && sendRet !== AVERROR_EOF) {
|
|
403
|
-
FFmpegError.throwIfError(sendRet, 'Failed to send packet to bitstream filter');
|
|
404
|
-
}
|
|
440
|
+
await this.filter(packet);
|
|
405
441
|
// Receive all output packets
|
|
442
|
+
const outputPackets = [];
|
|
406
443
|
while (true) {
|
|
407
444
|
const outPacket = await this.receive();
|
|
408
445
|
if (!outPacket)
|
|
@@ -421,7 +458,7 @@ export class BitStreamFilterAPI {
|
|
|
421
458
|
*
|
|
422
459
|
* Direct mapping to av_bsf_send_packet() and av_bsf_receive_packet().
|
|
423
460
|
*
|
|
424
|
-
* @param packet - Packet to filter
|
|
461
|
+
* @param packet - Packet to filter, or null to flush
|
|
425
462
|
*
|
|
426
463
|
* @returns Array of filtered packets (empty if more data needed or filter is closed)
|
|
427
464
|
*
|
|
@@ -437,22 +474,25 @@ export class BitStreamFilterAPI {
|
|
|
437
474
|
* }
|
|
438
475
|
* ```
|
|
439
476
|
*
|
|
477
|
+
* @example
|
|
478
|
+
* ```typescript
|
|
479
|
+
* // Flush remaining packets at end of stream
|
|
480
|
+
* const remaining = filter.filterAllSync(null);
|
|
481
|
+
* for (const packet of remaining) {
|
|
482
|
+
* output.writePacketSync(packet);
|
|
483
|
+
* packet.free();
|
|
484
|
+
* }
|
|
485
|
+
* ```
|
|
486
|
+
*
|
|
440
487
|
* @see {@link filterSync} For single packet filtering
|
|
441
488
|
* @see {@link packetsSync} For stream processing
|
|
442
489
|
* @see {@link flushSync} For end-of-stream handling
|
|
443
490
|
* @see {@link filterAll} For async version
|
|
444
491
|
*/
|
|
445
492
|
filterAllSync(packet) {
|
|
446
|
-
|
|
447
|
-
return [];
|
|
448
|
-
}
|
|
449
|
-
const outputPackets = [];
|
|
450
|
-
// Send packet to filter
|
|
451
|
-
const sendRet = this.ctx.sendPacketSync(packet);
|
|
452
|
-
if (sendRet < 0 && sendRet !== AVERROR_EOF) {
|
|
453
|
-
FFmpegError.throwIfError(sendRet, 'Failed to send packet to bitstream filter');
|
|
454
|
-
}
|
|
493
|
+
this.filterSync(packet);
|
|
455
494
|
// Receive all output packets
|
|
495
|
+
const outputPackets = [];
|
|
456
496
|
while (true) {
|
|
457
497
|
const outPacket = this.receiveSync();
|
|
458
498
|
if (!outPacket)
|
|
@@ -462,196 +502,210 @@ export class BitStreamFilterAPI {
|
|
|
462
502
|
return outputPackets;
|
|
463
503
|
}
|
|
464
504
|
/**
|
|
465
|
-
*
|
|
505
|
+
* Filter packet stream to filtered packet stream.
|
|
506
|
+
*
|
|
507
|
+
* High-level async generator for complete filtering pipeline.
|
|
508
|
+
* Filter is only flushed when EOF (null) signal is explicitly received.
|
|
509
|
+
* Primary interface for stream-based filtering.
|
|
466
510
|
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
511
|
+
* **EOF Handling:**
|
|
512
|
+
* - Send null to flush filter and get remaining buffered packets
|
|
513
|
+
* - Generator yields null after flushing when null is received
|
|
514
|
+
* - No automatic flushing - filter stays open until EOF or close()
|
|
470
515
|
*
|
|
471
|
-
* @param packets - Async iterable of packets
|
|
516
|
+
* @param packets - Async iterable of packets, single packet, or null to flush
|
|
472
517
|
*
|
|
473
|
-
* @yields {Packet} Filtered packets
|
|
518
|
+
* @yields {Packet | null} Filtered packets, followed by null when explicitly flushed
|
|
474
519
|
*
|
|
475
520
|
* @throws {FFmpegError} If filtering fails
|
|
476
521
|
*
|
|
477
522
|
* @example
|
|
478
523
|
* ```typescript
|
|
479
|
-
* //
|
|
524
|
+
* // Stream of packets with automatic EOF propagation
|
|
480
525
|
* for await (const packet of filter.packets(input.packets())) {
|
|
526
|
+
* if (packet === null) {
|
|
527
|
+
* console.log('Filter flushed');
|
|
528
|
+
* break;
|
|
529
|
+
* }
|
|
481
530
|
* await output.writePacket(packet);
|
|
482
|
-
* packet.free();
|
|
531
|
+
* packet.free(); // Must free output packets
|
|
483
532
|
* }
|
|
484
533
|
* ```
|
|
485
534
|
*
|
|
486
535
|
* @example
|
|
487
536
|
* ```typescript
|
|
488
|
-
* //
|
|
489
|
-
* const
|
|
490
|
-
*
|
|
537
|
+
* // Single packet - no automatic flush
|
|
538
|
+
* for await (const packet of filter.packets(singlePacket)) {
|
|
539
|
+
* await output.writePacket(packet);
|
|
540
|
+
* packet.free();
|
|
541
|
+
* }
|
|
542
|
+
* // Filter remains open, buffered packets not flushed
|
|
543
|
+
* ```
|
|
491
544
|
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
545
|
+
* @example
|
|
546
|
+
* ```typescript
|
|
547
|
+
* // Explicit flush with EOF
|
|
548
|
+
* for await (const packet of filter.packets(null)) {
|
|
549
|
+
* if (packet === null) {
|
|
550
|
+
* console.log('All buffered packets flushed');
|
|
551
|
+
* break;
|
|
552
|
+
* }
|
|
553
|
+
* console.log('Buffered packet:', packet.pts);
|
|
554
|
+
* await output.writePacket(packet);
|
|
555
|
+
* packet.free();
|
|
495
556
|
* }
|
|
496
557
|
* ```
|
|
497
558
|
*
|
|
498
|
-
* @see {@link
|
|
499
|
-
* @see {@link
|
|
559
|
+
* @see {@link filter} For single packet filtering
|
|
560
|
+
* @see {@link Demuxer.packets} For packet source
|
|
561
|
+
* @see {@link packetsSync} For sync version
|
|
500
562
|
*/
|
|
501
563
|
async *packets(packets) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
if (!remaining)
|
|
511
|
-
break;
|
|
512
|
-
yield remaining;
|
|
513
|
-
}
|
|
514
|
-
// Signal EOF and stop processing
|
|
515
|
-
yield null;
|
|
516
|
-
return;
|
|
564
|
+
const self = this;
|
|
565
|
+
const processPacket = async function* (packet) {
|
|
566
|
+
await self.filter(packet);
|
|
567
|
+
while (true) {
|
|
568
|
+
const outPacket = await self.receive();
|
|
569
|
+
if (!outPacket)
|
|
570
|
+
break;
|
|
571
|
+
yield outPacket;
|
|
517
572
|
}
|
|
518
|
-
|
|
519
|
-
|
|
573
|
+
}.bind(this);
|
|
574
|
+
const finalize = async function* () {
|
|
575
|
+
for await (const remaining of self.flushPackets()) {
|
|
576
|
+
yield remaining;
|
|
520
577
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
578
|
+
yield null;
|
|
579
|
+
}.bind(this);
|
|
580
|
+
if (packets === null) {
|
|
581
|
+
yield* finalize();
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
if (packets instanceof Packet) {
|
|
585
|
+
yield* processPacket(packets);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
for await (const packet_1 of packets) {
|
|
589
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
590
|
+
try {
|
|
591
|
+
const packet = __addDisposableResource(env_1, packet_1, false);
|
|
592
|
+
if (packet === null) {
|
|
593
|
+
yield* finalize();
|
|
594
|
+
return;
|
|
536
595
|
}
|
|
596
|
+
yield* processPacket(packet);
|
|
537
597
|
}
|
|
538
|
-
|
|
539
|
-
|
|
598
|
+
catch (e_1) {
|
|
599
|
+
env_1.error = e_1;
|
|
600
|
+
env_1.hasError = true;
|
|
540
601
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const outPacket = await this.receive();
|
|
544
|
-
if (!outPacket)
|
|
545
|
-
break; // EAGAIN or EOF
|
|
546
|
-
yield outPacket;
|
|
602
|
+
finally {
|
|
603
|
+
__disposeResources(env_1);
|
|
547
604
|
}
|
|
548
605
|
}
|
|
549
|
-
// Flush filter after all packets (fallback if no null was sent)
|
|
550
|
-
await this.flush();
|
|
551
|
-
while (true) {
|
|
552
|
-
const remaining = await this.receive();
|
|
553
|
-
if (!remaining)
|
|
554
|
-
break;
|
|
555
|
-
yield remaining;
|
|
556
|
-
}
|
|
557
|
-
// Signal EOF
|
|
558
|
-
yield null;
|
|
559
606
|
}
|
|
560
607
|
/**
|
|
561
|
-
*
|
|
608
|
+
* Filter packet stream to filtered packet stream synchronously.
|
|
562
609
|
* Synchronous version of packets.
|
|
563
610
|
*
|
|
564
|
-
* High-level sync generator for filtering
|
|
565
|
-
*
|
|
566
|
-
*
|
|
611
|
+
* High-level sync generator for complete filtering pipeline.
|
|
612
|
+
* Filter is only flushed when EOF (null) signal is explicitly received.
|
|
613
|
+
* Primary interface for stream-based filtering.
|
|
567
614
|
*
|
|
568
|
-
*
|
|
615
|
+
* **EOF Handling:**
|
|
616
|
+
* - Send null to flush filter and get remaining buffered packets
|
|
617
|
+
* - Generator yields null after flushing when null is received
|
|
618
|
+
* - No automatic flushing - filter stays open until EOF or close()
|
|
569
619
|
*
|
|
570
|
-
* @
|
|
620
|
+
* @param packets - Iterable of packets, single packet, or null to flush
|
|
621
|
+
*
|
|
622
|
+
* @yields {Packet | null} Filtered packets, followed by null when explicitly flushed
|
|
571
623
|
*
|
|
572
624
|
* @throws {FFmpegError} If filtering fails
|
|
573
625
|
*
|
|
574
626
|
* @example
|
|
575
627
|
* ```typescript
|
|
576
|
-
* //
|
|
577
|
-
* for (const packet of filter.packetsSync(
|
|
628
|
+
* // Stream of packets with automatic EOF propagation
|
|
629
|
+
* for (const packet of filter.packetsSync(inputPackets)) {
|
|
630
|
+
* if (packet === null) {
|
|
631
|
+
* console.log('Filter flushed');
|
|
632
|
+
* break;
|
|
633
|
+
* }
|
|
578
634
|
* output.writePacketSync(packet);
|
|
579
|
-
* packet.free();
|
|
635
|
+
* packet.free(); // Must free output packets
|
|
580
636
|
* }
|
|
581
637
|
* ```
|
|
582
638
|
*
|
|
583
639
|
* @example
|
|
584
640
|
* ```typescript
|
|
585
|
-
* //
|
|
586
|
-
* const
|
|
587
|
-
*
|
|
641
|
+
* // Single packet - no automatic flush
|
|
642
|
+
* for (const packet of filter.packetsSync(singlePacket)) {
|
|
643
|
+
* output.writePacketSync(packet);
|
|
644
|
+
* packet.free();
|
|
645
|
+
* }
|
|
646
|
+
* // Filter remains open, buffered packets not flushed
|
|
647
|
+
* ```
|
|
588
648
|
*
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```typescript
|
|
651
|
+
* // Explicit flush with EOF
|
|
652
|
+
* for (const packet of filter.packetsSync(null)) {
|
|
653
|
+
* if (packet === null) {
|
|
654
|
+
* console.log('All buffered packets flushed');
|
|
655
|
+
* break;
|
|
656
|
+
* }
|
|
657
|
+
* console.log('Buffered packet:', packet.pts);
|
|
658
|
+
* output.writePacketSync(packet);
|
|
659
|
+
* packet.free();
|
|
592
660
|
* }
|
|
593
661
|
* ```
|
|
594
662
|
*
|
|
663
|
+
* @see {@link filterSync} For single packet filtering
|
|
595
664
|
* @see {@link packets} For async version
|
|
596
665
|
*/
|
|
597
666
|
*packetsSync(packets) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if (!remaining)
|
|
607
|
-
break;
|
|
608
|
-
yield remaining;
|
|
609
|
-
}
|
|
610
|
-
// Signal EOF and stop processing
|
|
611
|
-
yield null;
|
|
612
|
-
return;
|
|
667
|
+
const self = this;
|
|
668
|
+
const processPacket = function* (packet) {
|
|
669
|
+
self.filterSync(packet);
|
|
670
|
+
while (true) {
|
|
671
|
+
const outPacket = self.receiveSync();
|
|
672
|
+
if (!outPacket)
|
|
673
|
+
break;
|
|
674
|
+
yield outPacket;
|
|
613
675
|
}
|
|
614
|
-
|
|
615
|
-
|
|
676
|
+
}.bind(this);
|
|
677
|
+
const finalize = function* () {
|
|
678
|
+
for (const remaining of self.flushPacketsSync()) {
|
|
679
|
+
yield remaining;
|
|
616
680
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
681
|
+
yield null;
|
|
682
|
+
}.bind(this);
|
|
683
|
+
if (packets === null) {
|
|
684
|
+
yield* finalize();
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
if (packets instanceof Packet) {
|
|
688
|
+
yield* processPacket(packets);
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
for (const packet_2 of packets) {
|
|
692
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
693
|
+
try {
|
|
694
|
+
const packet = __addDisposableResource(env_2, packet_2, false);
|
|
695
|
+
if (packet === null) {
|
|
696
|
+
yield* finalize();
|
|
697
|
+
return;
|
|
632
698
|
}
|
|
699
|
+
yield* processPacket(packet);
|
|
633
700
|
}
|
|
634
|
-
|
|
635
|
-
|
|
701
|
+
catch (e_2) {
|
|
702
|
+
env_2.error = e_2;
|
|
703
|
+
env_2.hasError = true;
|
|
636
704
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
const outPacket = this.receiveSync();
|
|
640
|
-
if (!outPacket)
|
|
641
|
-
break; // EAGAIN or EOF
|
|
642
|
-
yield outPacket;
|
|
705
|
+
finally {
|
|
706
|
+
__disposeResources(env_2);
|
|
643
707
|
}
|
|
644
708
|
}
|
|
645
|
-
// Flush filter after all packets (fallback if no null was sent)
|
|
646
|
-
this.flushSync();
|
|
647
|
-
while (true) {
|
|
648
|
-
const remaining = this.receiveSync();
|
|
649
|
-
if (!remaining)
|
|
650
|
-
break;
|
|
651
|
-
yield remaining;
|
|
652
|
-
}
|
|
653
|
-
// Signal EOF
|
|
654
|
-
yield null;
|
|
655
709
|
}
|
|
656
710
|
/**
|
|
657
711
|
* Flush filter and signal end-of-stream.
|
|
@@ -1074,9 +1128,9 @@ export class BitStreamFilterAPI {
|
|
|
1074
1128
|
try {
|
|
1075
1129
|
// Outer loop - receive packets
|
|
1076
1130
|
while (!this.inputQueue.isClosed) {
|
|
1077
|
-
const
|
|
1131
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
1078
1132
|
try {
|
|
1079
|
-
const packet = __addDisposableResource(
|
|
1133
|
+
const packet = __addDisposableResource(env_3, await this.inputQueue.receive(), false);
|
|
1080
1134
|
if (!packet)
|
|
1081
1135
|
break;
|
|
1082
1136
|
if (this.isClosed) {
|
|
@@ -1110,12 +1164,12 @@ export class BitStreamFilterAPI {
|
|
|
1110
1164
|
await this.outputQueue.send(outPacket);
|
|
1111
1165
|
}
|
|
1112
1166
|
}
|
|
1113
|
-
catch (
|
|
1114
|
-
|
|
1115
|
-
|
|
1167
|
+
catch (e_3) {
|
|
1168
|
+
env_3.error = e_3;
|
|
1169
|
+
env_3.hasError = true;
|
|
1116
1170
|
}
|
|
1117
1171
|
finally {
|
|
1118
|
-
__disposeResources(
|
|
1172
|
+
__disposeResources(env_3);
|
|
1119
1173
|
}
|
|
1120
1174
|
}
|
|
1121
1175
|
// Flush filter at end
|