webcodecs-node 0.7.1 → 0.7.5

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 (105) hide show
  1. package/README.md +94 -12
  2. package/dist/config/ffmpeg-quality.d.ts +10 -1
  3. package/dist/config/ffmpeg-quality.d.ts.map +1 -1
  4. package/dist/config/ffmpeg-quality.js +12 -38
  5. package/dist/config/ffmpeg-quality.js.map +1 -1
  6. package/dist/config/webcodecs-config.d.ts +58 -0
  7. package/dist/config/webcodecs-config.d.ts.map +1 -0
  8. package/dist/config/webcodecs-config.js +187 -0
  9. package/dist/config/webcodecs-config.js.map +1 -0
  10. package/dist/containers/Demuxer.d.ts +3 -1
  11. package/dist/containers/Demuxer.d.ts.map +1 -1
  12. package/dist/containers/Demuxer.js +26 -19
  13. package/dist/containers/Demuxer.js.map +1 -1
  14. package/dist/containers/FFmpegMuxer.d.ts +42 -0
  15. package/dist/containers/FFmpegMuxer.d.ts.map +1 -0
  16. package/dist/containers/FFmpegMuxer.js +311 -0
  17. package/dist/containers/FFmpegMuxer.js.map +1 -0
  18. package/dist/containers/FFmpegSpawnMuxer.d.ts +42 -0
  19. package/dist/containers/FFmpegSpawnMuxer.d.ts.map +1 -0
  20. package/dist/containers/FFmpegSpawnMuxer.js +311 -0
  21. package/dist/containers/FFmpegSpawnMuxer.js.map +1 -0
  22. package/dist/containers/FallbackMuxer.d.ts +42 -0
  23. package/dist/containers/FallbackMuxer.d.ts.map +1 -0
  24. package/dist/containers/FallbackMuxer.js +311 -0
  25. package/dist/containers/FallbackMuxer.js.map +1 -0
  26. package/dist/containers/Muxer.d.ts +75 -107
  27. package/dist/containers/Muxer.d.ts.map +1 -1
  28. package/dist/containers/Muxer.js +184 -243
  29. package/dist/containers/Muxer.js.map +1 -1
  30. package/dist/containers/MuxerWithFallback.d.ts +110 -0
  31. package/dist/containers/MuxerWithFallback.d.ts.map +1 -0
  32. package/dist/containers/MuxerWithFallback.js +239 -0
  33. package/dist/containers/MuxerWithFallback.js.map +1 -0
  34. package/dist/containers/NodeAvMuxer.d.ts +118 -0
  35. package/dist/containers/NodeAvMuxer.d.ts.map +1 -0
  36. package/dist/containers/NodeAvMuxer.js +338 -0
  37. package/dist/containers/NodeAvMuxer.js.map +1 -0
  38. package/dist/containers/extract.d.ts.map +1 -1
  39. package/dist/containers/extract.js +3 -1
  40. package/dist/containers/extract.js.map +1 -1
  41. package/dist/containers/index.d.ts +20 -14
  42. package/dist/containers/index.d.ts.map +1 -1
  43. package/dist/containers/index.js +21 -14
  44. package/dist/containers/index.js.map +1 -1
  45. package/dist/containers/muxer-types.d.ts +117 -0
  46. package/dist/containers/muxer-types.d.ts.map +1 -0
  47. package/dist/containers/muxer-types.js +45 -0
  48. package/dist/containers/muxer-types.js.map +1 -0
  49. package/dist/containers/transcode.d.ts.map +1 -1
  50. package/dist/containers/transcode.js +171 -150
  51. package/dist/containers/transcode.js.map +1 -1
  52. package/dist/core/VideoFrame.d.ts +19 -0
  53. package/dist/core/VideoFrame.d.ts.map +1 -1
  54. package/dist/core/VideoFrame.js +11 -0
  55. package/dist/core/VideoFrame.js.map +1 -1
  56. package/dist/decoders/VideoDecoder.d.ts +1 -0
  57. package/dist/decoders/VideoDecoder.d.ts.map +1 -1
  58. package/dist/decoders/VideoDecoder.js +6 -4
  59. package/dist/decoders/VideoDecoder.js.map +1 -1
  60. package/dist/demos/demo-audio-visualizer-mediabunny.d.ts +10 -0
  61. package/dist/demos/demo-audio-visualizer-mediabunny.d.ts.map +1 -0
  62. package/dist/demos/demo-audio-visualizer-mediabunny.js +357 -0
  63. package/dist/demos/demo-audio-visualizer-mediabunny.js.map +1 -0
  64. package/dist/demos/demo-audio-visualizer-nodeav.d.ts +10 -0
  65. package/dist/demos/demo-audio-visualizer-nodeav.d.ts.map +1 -0
  66. package/dist/demos/demo-audio-visualizer-nodeav.js +318 -0
  67. package/dist/demos/demo-audio-visualizer-nodeav.js.map +1 -0
  68. package/dist/demos/demo-muxer-fallback.d.ts +8 -0
  69. package/dist/demos/demo-muxer-fallback.d.ts.map +1 -0
  70. package/dist/demos/demo-muxer-fallback.js +165 -0
  71. package/dist/demos/demo-muxer-fallback.js.map +1 -0
  72. package/dist/encoders/AudioEncoder.d.ts +2 -0
  73. package/dist/encoders/AudioEncoder.d.ts.map +1 -1
  74. package/dist/encoders/AudioEncoder.js +7 -4
  75. package/dist/encoders/AudioEncoder.js.map +1 -1
  76. package/dist/hardware/decoder-args.d.ts.map +1 -1
  77. package/dist/hardware/decoder-args.js +35 -14
  78. package/dist/hardware/decoder-args.js.map +1 -1
  79. package/dist/hardware/detection.d.ts.map +1 -1
  80. package/dist/hardware/detection.js +39 -0
  81. package/dist/hardware/detection.js.map +1 -1
  82. package/dist/hardware/encoder-args.d.ts.map +1 -1
  83. package/dist/hardware/encoder-args.js +43 -5
  84. package/dist/hardware/encoder-args.js.map +1 -1
  85. package/dist/hardware/types.d.ts.map +1 -1
  86. package/dist/hardware/types.js +30 -28
  87. package/dist/hardware/types.js.map +1 -1
  88. package/dist/node-av/NodeAvVideoEncoder.d.ts +5 -0
  89. package/dist/node-av/NodeAvVideoEncoder.d.ts.map +1 -1
  90. package/dist/node-av/NodeAvVideoEncoder.js +76 -23
  91. package/dist/node-av/NodeAvVideoEncoder.js.map +1 -1
  92. package/dist/utils/avc.d.ts +2 -0
  93. package/dist/utils/avc.d.ts.map +1 -1
  94. package/dist/utils/avc.js +36 -8
  95. package/dist/utils/avc.js.map +1 -1
  96. package/dist/utils/codec-validation.d.ts.map +1 -1
  97. package/dist/utils/codec-validation.js +12 -6
  98. package/dist/utils/codec-validation.js.map +1 -1
  99. package/dist/utils/hevc.d.ts +2 -0
  100. package/dist/utils/hevc.d.ts.map +1 -1
  101. package/dist/utils/hevc.js +42 -8
  102. package/dist/utils/hevc.js.map +1 -1
  103. package/docs/api.md +52 -2
  104. package/docs/configuration.md +10 -7
  105. package/package.json +1 -1
package/README.md CHANGED
@@ -367,26 +367,79 @@ encoder.configure({
367
367
 
368
368
  ### Container Utilities
369
369
 
370
- Import container demuxing/muxing utilities for working with MP4 and WebM files:
370
+ Import container demuxing/muxing utilities for working with MP4, WebM, and MKV files:
371
371
 
372
372
  ```typescript
373
- import { Mp4Demuxer, WebmMuxer } from 'webcodecs-node/containers';
373
+ import { Demuxer, Muxer, muxChunks, extractVideoFrames } from 'webcodecs-node/containers';
374
374
 
375
- // Demux an MP4 file
376
- const demuxer = new Mp4Demuxer(mp4Data);
377
- await demuxer.initialize();
375
+ // Demux a video file
376
+ const demuxer = new Demuxer({ path: 'input.mp4' });
377
+ await demuxer.open();
378
378
 
379
- for await (const sample of demuxer.videoSamples()) {
380
- // sample contains encoded video chunks
379
+ console.log('Video:', demuxer.videoConfig);
380
+ console.log('Audio:', demuxer.audioConfig);
381
+
382
+ for await (const chunk of demuxer.videoChunks()) {
383
+ // chunk is EncodedVideoChunk ready for VideoDecoder
381
384
  }
385
+ await demuxer.close();
386
+
387
+ // Mux encoded chunks to a file
388
+ const muxer = new Muxer({ path: 'output.mp4' });
389
+ await muxer.open();
390
+ await muxer.addVideoTrack({
391
+ codec: 'avc1.42001E',
392
+ codedWidth: 1920,
393
+ codedHeight: 1080,
394
+ description: spsNaluBuffer, // Optional: H.264 SPS/PPS
395
+ });
396
+
397
+ for (const chunk of encodedChunks) {
398
+ await muxer.writeVideoChunk(chunk);
399
+ }
400
+
401
+ const result = await muxer.closeWithResult();
402
+ console.log(`Muxed with ${result.backend} in ${result.durationMs}ms`);
382
403
 
383
- // Mux encoded chunks to WebM
384
- const muxer = new WebmMuxer({
385
- video: { codec: 'vp9', width: 1920, height: 1080 },
404
+ // Or use the convenience function
405
+ const result = await muxChunks({
406
+ path: 'output.mp4',
407
+ video: { config: videoTrackConfig, chunks: videoChunks },
408
+ audio: { config: audioTrackConfig, chunks: audioChunks },
386
409
  });
387
410
 
388
- muxer.addVideoChunk(encodedChunk, metadata);
389
- const webmData = muxer.finalize();
411
+ // Extract decoded frames directly
412
+ for await (const frame of extractVideoFrames('input.mp4')) {
413
+ console.log(`Frame: ${frame.timestamp}us`);
414
+ frame.close();
415
+ }
416
+ ```
417
+
418
+ **Muxer Fallback Architecture:**
419
+
420
+ The `Muxer` class uses a two-tier approach for reliability:
421
+
422
+ 1. **Primary: node-av** (~5ms) - Fast native muxing using node-av's FormatContext API
423
+ 2. **Fallback: FFmpeg subprocess** (~130ms) - Spawns FFmpeg process if node-av fails
424
+
425
+ ```typescript
426
+ const muxer = new Muxer({
427
+ path: 'output.mp4',
428
+ onFallback: (err) => console.warn('Using FFmpeg fallback:', err.message),
429
+ forceBackend: 'node-av', // Optional: 'node-av' or 'ffmpeg-spawn'
430
+ });
431
+ ```
432
+
433
+ You can also use the backend-specific classes directly:
434
+
435
+ ```typescript
436
+ import { NodeAvMuxer, FFmpegMuxer } from 'webcodecs-node/containers';
437
+
438
+ // Fast path only
439
+ const fastMuxer = new NodeAvMuxer({ path: 'output.mp4' });
440
+
441
+ // FFmpeg subprocess only
442
+ const ffmpegMuxer = new FFmpegMuxer({ path: 'output.mp4' });
390
443
  ```
391
444
 
392
445
  ### Streaming & Latency Modes
@@ -652,6 +705,35 @@ const png = await canvas.toBuffer('png');
652
705
  | Batch processing | Hardware for throughput |
653
706
  | Low-end systems | Software (more compatible) |
654
707
 
708
+ ## Debugging
709
+
710
+ Enable debug logging to troubleshoot encoding/decoding issues:
711
+
712
+ ```bash
713
+ # Enable debug output
714
+ WEBCODECS_DEBUG=1 node your-script.js
715
+
716
+ # Or set programmatically
717
+ import { setDebugMode } from 'webcodecs-node';
718
+ setDebugMode(true);
719
+ ```
720
+
721
+ Debug mode outputs detailed information about:
722
+ - Hardware acceleration detection and selection
723
+ - Encoder/decoder initialization
724
+ - Muxer backend selection and fallback events
725
+ - Filter chain configuration
726
+ - Error details with context
727
+
728
+ Example debug output:
729
+ ```
730
+ [webcodecs:Transcode] Using hardware acceleration: vaapi
731
+ [webcodecs:Transcode] Using hardware decoder for h264
732
+ [webcodecs:Transcode] Using hardware encoder for h264
733
+ [webcodecs:Transcode] Using filter chain: scale_vaapi=format=nv12
734
+ [webcodecs:NodeAvMuxer] writeTrailer returned error code -22
735
+ ```
736
+
655
737
  ## Demos
656
738
 
657
739
  Run the included demos to test functionality:
@@ -1,3 +1,9 @@
1
+ /**
2
+ * FFmpeg quality overrides
3
+ *
4
+ * This module provides backwards compatibility with the old ffmpeg-quality.js config.
5
+ * New code should use webcodecs-config.js via getQualityConfig() instead.
6
+ */
1
7
  export type FfmpegQualityOverrides = {
2
8
  crf?: number;
3
9
  preset?: string;
@@ -6,7 +12,10 @@ export type FfmpegQualityOverrides = {
6
12
  preset?: string;
7
13
  }>;
8
14
  };
9
- export declare const ffmpegQualityOverrides: FfmpegQualityOverrides;
15
+ /**
16
+ * Get quality overrides for a codec
17
+ * Uses unified webcodecs-config.js
18
+ */
10
19
  export declare function getFfmpegQualityOverrides(codecName: string): {
11
20
  crf?: number;
12
21
  preset?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ffmpeg-quality.d.ts","sourceRoot":"","sources":["../../src/config/ffmpeg-quality.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9D,CAAC;AAoCF,eAAO,MAAM,sBAAsB,wBAAwB,CAAC;AAE5D,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAO9F"}
1
+ {"version":3,"file":"ffmpeg-quality.d.ts","sourceRoot":"","sources":["../../src/config/ffmpeg-quality.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAE9F"}
@@ -1,41 +1,15 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { pathToFileURL } from 'url';
4
- const DEFAULT_OVERRIDES = {};
5
- function sanitizeOverrides(raw) {
6
- if (!raw || typeof raw !== 'object') {
7
- return DEFAULT_OVERRIDES;
8
- }
9
- const src = raw;
10
- const perCodec = src.perCodec && typeof src.perCodec === 'object' ? src.perCodec : undefined;
11
- return {
12
- crf: typeof src.crf === 'number' ? src.crf : undefined,
13
- preset: typeof src.preset === 'string' ? src.preset : undefined,
14
- perCodec,
15
- };
16
- }
17
- async function loadOverrides() {
18
- const configPath = process.env.WEB_CODECS_FFMPEG_QUALITY
19
- ?? path.join(process.cwd(), 'ffmpeg-quality.js');
20
- if (!fs.existsSync(configPath)) {
21
- return DEFAULT_OVERRIDES;
22
- }
23
- try {
24
- const mod = await import(pathToFileURL(configPath).href);
25
- const raw = mod?.default ?? mod?.ffmpegQuality ?? mod;
26
- return sanitizeOverrides(raw);
27
- }
28
- catch {
29
- return DEFAULT_OVERRIDES;
30
- }
31
- }
32
- export const ffmpegQualityOverrides = await loadOverrides();
1
+ /**
2
+ * FFmpeg quality overrides
3
+ *
4
+ * This module provides backwards compatibility with the old ffmpeg-quality.js config.
5
+ * New code should use webcodecs-config.js via getQualityConfig() instead.
6
+ */
7
+ import { getQualityConfig } from './webcodecs-config.js';
8
+ /**
9
+ * Get quality overrides for a codec
10
+ * Uses unified webcodecs-config.js
11
+ */
33
12
  export function getFfmpegQualityOverrides(codecName) {
34
- const key = codecName.toLowerCase();
35
- const perCodec = ffmpegQualityOverrides.perCodec?.[key];
36
- return {
37
- crf: typeof perCodec?.crf === 'number' ? perCodec.crf : ffmpegQualityOverrides.crf,
38
- preset: typeof perCodec?.preset === 'string' ? perCodec.preset : ffmpegQualityOverrides.preset,
39
- };
13
+ return getQualityConfig(codecName);
40
14
  }
41
15
  //# sourceMappingURL=ffmpeg-quality.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ffmpeg-quality.js","sourceRoot":"","sources":["../../src/config/ffmpeg-quality.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAQpC,MAAM,iBAAiB,GAA2B,EAAE,CAAC;AAErD,SAAS,iBAAiB,CAAC,GAAY;IACrC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,GAAG,GAAG,GAA6B,CAAC;IAC1C,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7F,OAAO;QACL,GAAG,EAAE,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;QACtD,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC/D,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa;IAC1B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB;WACnD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAEnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,aAAa,IAAI,GAAG,CAAC;QACtD,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,iBAAiB,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,aAAa,EAAE,CAAC;AAE5D,MAAM,UAAU,yBAAyB,CAAC,SAAiB;IACzD,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO;QACL,GAAG,EAAE,OAAO,QAAQ,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG;QAClF,MAAM,EAAE,OAAO,QAAQ,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,MAAM;KAC/F,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"ffmpeg-quality.js","sourceRoot":"","sources":["../../src/config/ffmpeg-quality.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQzD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,SAAiB;IACzD,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Unified WebCodecs configuration
3
+ *
4
+ * Loads configuration from webcodecs-config.js (or WEBCODECS_CONFIG env var).
5
+ * All settings are optional - omit or comment out to use defaults.
6
+ */
7
+ import type { HardwareAccelerationMethod } from '../hardware/types.js';
8
+ /**
9
+ * Per-codec configuration overrides
10
+ */
11
+ export interface CodecConfig {
12
+ /** CRF value for quality-based encoding */
13
+ crf?: number;
14
+ /** Encoder preset (e.g., 'fast', 'medium', 'slow') */
15
+ preset?: string;
16
+ /** Hardware acceleration priority order for this codec */
17
+ hwaccel?: HardwareAccelerationMethod[];
18
+ }
19
+ /**
20
+ * WebCodecs configuration options
21
+ */
22
+ export interface WebCodecsConfig {
23
+ /** Global CRF value (overridden by perCodec) */
24
+ crf?: number;
25
+ /** Global encoder preset (overridden by perCodec) */
26
+ preset?: string;
27
+ /** Global hardware acceleration priority order (overridden by perCodec) */
28
+ hwaccel?: HardwareAccelerationMethod[];
29
+ /** Per-codec overrides */
30
+ perCodec?: Record<string, CodecConfig>;
31
+ }
32
+ /**
33
+ * Get the loaded configuration (cached)
34
+ */
35
+ export declare function getConfig(): Promise<WebCodecsConfig>;
36
+ /**
37
+ * Get configuration synchronously (loads config if not cached)
38
+ */
39
+ export declare function getConfigSync(): WebCodecsConfig;
40
+ /**
41
+ * Clear cached config (for testing or reloading)
42
+ */
43
+ export declare function clearConfigCache(): void;
44
+ /**
45
+ * Get quality settings for a specific codec
46
+ */
47
+ export declare function getQualityConfig(codecName: string): {
48
+ crf?: number;
49
+ preset?: string;
50
+ };
51
+ /**
52
+ * Get hardware acceleration priority order for a specific codec
53
+ * Returns undefined if no override is configured (use default priorities)
54
+ * Returns empty array if explicitly set to [] (force software encoding)
55
+ */
56
+ export declare function getHwaccelConfig(codecName: string): HardwareAccelerationMethod[] | undefined;
57
+ export declare const webCodecsConfig: WebCodecsConfig;
58
+ //# sourceMappingURL=webcodecs-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webcodecs-config.d.ts","sourceRoot":"","sources":["../../src/config/webcodecs-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAKvE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,0BAA0B,EAAE,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACvC,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACxC;AAgGD;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC,CAK1D;AAuCD;;GAEG;AACH,wBAAgB,aAAa,IAAI,eAAe,CAK/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CASrF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,0BAA0B,EAAE,GAAG,SAAS,CAiB5F;AAGD,eAAO,MAAM,eAAe,iBAAqB,CAAC"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Unified WebCodecs configuration
3
+ *
4
+ * Loads configuration from webcodecs-config.js (or WEBCODECS_CONFIG env var).
5
+ * All settings are optional - omit or comment out to use defaults.
6
+ */
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import { pathToFileURL } from 'url';
10
+ import { createRequire } from 'module';
11
+ // Create require function for synchronous config loading
12
+ const require = createRequire(import.meta.url);
13
+ const DEFAULT_CONFIG = {};
14
+ let cachedConfig = null;
15
+ /**
16
+ * Validate and sanitize raw config object
17
+ */
18
+ function sanitizeConfig(raw) {
19
+ if (!raw || typeof raw !== 'object') {
20
+ return DEFAULT_CONFIG;
21
+ }
22
+ const src = raw;
23
+ const config = {};
24
+ // Global quality settings
25
+ if (typeof src.crf === 'number') {
26
+ config.crf = src.crf;
27
+ }
28
+ if (typeof src.preset === 'string') {
29
+ config.preset = src.preset;
30
+ }
31
+ // Global hwaccel order
32
+ if (Array.isArray(src.hwaccel)) {
33
+ config.hwaccel = src.hwaccel.filter((m) => typeof m === 'string');
34
+ }
35
+ // Per-codec overrides
36
+ if (src.perCodec && typeof src.perCodec === 'object') {
37
+ config.perCodec = {};
38
+ for (const [codec, codecConfig] of Object.entries(src.perCodec)) {
39
+ if (codecConfig && typeof codecConfig === 'object') {
40
+ const cc = codecConfig;
41
+ const parsed = {};
42
+ if (typeof cc.crf === 'number') {
43
+ parsed.crf = cc.crf;
44
+ }
45
+ if (typeof cc.preset === 'string') {
46
+ parsed.preset = cc.preset;
47
+ }
48
+ if (Array.isArray(cc.hwaccel)) {
49
+ parsed.hwaccel = cc.hwaccel.filter((m) => typeof m === 'string');
50
+ }
51
+ if (Object.keys(parsed).length > 0) {
52
+ config.perCodec[codec.toLowerCase()] = parsed;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return config;
58
+ }
59
+ /**
60
+ * Load configuration from file
61
+ */
62
+ async function loadConfig() {
63
+ // Check for config file path in env
64
+ if (process.env.WEBCODECS_CONFIG) {
65
+ const configPath = process.env.WEBCODECS_CONFIG;
66
+ if (fs.existsSync(configPath)) {
67
+ try {
68
+ const mod = await import(pathToFileURL(configPath).href);
69
+ const raw = mod?.default ?? mod?.webCodecsConfig ?? mod;
70
+ return sanitizeConfig(raw);
71
+ }
72
+ catch {
73
+ // Fall through to defaults
74
+ }
75
+ }
76
+ return DEFAULT_CONFIG;
77
+ }
78
+ // Try config file in current working directory
79
+ const configPath = path.join(process.cwd(), 'webcodecs-config.js');
80
+ if (fs.existsSync(configPath)) {
81
+ try {
82
+ const mod = await import(pathToFileURL(configPath).href);
83
+ const raw = mod?.default ?? mod?.webCodecsConfig ?? mod;
84
+ return sanitizeConfig(raw);
85
+ }
86
+ catch {
87
+ // Fall through to defaults
88
+ }
89
+ }
90
+ return DEFAULT_CONFIG;
91
+ }
92
+ /**
93
+ * Get the loaded configuration (cached)
94
+ */
95
+ export async function getConfig() {
96
+ if (cachedConfig === null) {
97
+ cachedConfig = await loadConfig();
98
+ }
99
+ return cachedConfig;
100
+ }
101
+ /**
102
+ * Load configuration synchronously using require
103
+ */
104
+ function loadConfigSync() {
105
+ // Check for config file path in env
106
+ if (process.env.WEBCODECS_CONFIG) {
107
+ const configPath = process.env.WEBCODECS_CONFIG;
108
+ if (fs.existsSync(configPath)) {
109
+ try {
110
+ // Clear require cache to allow reloading
111
+ delete require.cache[require.resolve(configPath)];
112
+ const mod = require(configPath);
113
+ const raw = mod?.default ?? mod?.webCodecsConfig ?? mod;
114
+ return sanitizeConfig(raw);
115
+ }
116
+ catch {
117
+ // Fall through to defaults
118
+ }
119
+ }
120
+ return DEFAULT_CONFIG;
121
+ }
122
+ // Try config file in current working directory
123
+ const configPath = path.join(process.cwd(), 'webcodecs-config.js');
124
+ if (fs.existsSync(configPath)) {
125
+ try {
126
+ delete require.cache[require.resolve(configPath)];
127
+ const mod = require(configPath);
128
+ const raw = mod?.default ?? mod?.webCodecsConfig ?? mod;
129
+ return sanitizeConfig(raw);
130
+ }
131
+ catch {
132
+ // Fall through to defaults
133
+ }
134
+ }
135
+ return DEFAULT_CONFIG;
136
+ }
137
+ /**
138
+ * Get configuration synchronously (loads config if not cached)
139
+ */
140
+ export function getConfigSync() {
141
+ if (cachedConfig === null) {
142
+ cachedConfig = loadConfigSync();
143
+ }
144
+ return cachedConfig;
145
+ }
146
+ /**
147
+ * Clear cached config (for testing or reloading)
148
+ */
149
+ export function clearConfigCache() {
150
+ cachedConfig = null;
151
+ }
152
+ /**
153
+ * Get quality settings for a specific codec
154
+ */
155
+ export function getQualityConfig(codecName) {
156
+ const config = getConfigSync();
157
+ const key = codecName.toLowerCase();
158
+ const perCodec = config.perCodec?.[key];
159
+ return {
160
+ crf: perCodec?.crf ?? config.crf,
161
+ preset: perCodec?.preset ?? config.preset,
162
+ };
163
+ }
164
+ /**
165
+ * Get hardware acceleration priority order for a specific codec
166
+ * Returns undefined if no override is configured (use default priorities)
167
+ * Returns empty array if explicitly set to [] (force software encoding)
168
+ */
169
+ export function getHwaccelConfig(codecName) {
170
+ const config = getConfigSync();
171
+ const key = codecName.toLowerCase();
172
+ // Per-codec hwaccel takes precedence (including empty array)
173
+ const perCodec = config.perCodec?.[key]?.hwaccel;
174
+ if (perCodec !== undefined) {
175
+ return perCodec;
176
+ }
177
+ // Fall back to global hwaccel (including empty array)
178
+ if (config.hwaccel !== undefined) {
179
+ return config.hwaccel;
180
+ }
181
+ // No override - use default priorities
182
+ return undefined;
183
+ }
184
+ // Load config on module init
185
+ export const webCodecsConfig = await loadConfig();
186
+ cachedConfig = webCodecsConfig;
187
+ //# sourceMappingURL=webcodecs-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webcodecs-config.js","sourceRoot":"","sources":["../../src/config/webcodecs-config.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,8 @@ export declare class Demuxer {
49
49
  private _audioStreamIndex;
50
50
  private _videoTimeBase;
51
51
  private _audioTimeBase;
52
+ private _videoTimeMultiplier;
53
+ private _audioTimeMultiplier;
52
54
  constructor(config: DemuxerConfig);
53
55
  /**
54
56
  * Open the container file and parse stream information
@@ -71,7 +73,7 @@ export declare class Demuxer {
71
73
  */
72
74
  get duration(): number | undefined;
73
75
  /**
74
- * Convert timestamp from stream time base to microseconds
76
+ * Convert timestamp from stream time base to microseconds using pre-calculated multiplier
75
77
  */
76
78
  private toMicroseconds;
77
79
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Demuxer.d.ts","sourceRoot":"","sources":["../../src/containers/Demuxer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAA8B,MAAM,8BAA8B,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAA8B,MAAM,8BAA8B,CAAC;AAG7F;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAC/F,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;AA+C/F;;GAEG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,cAAc,CAA6C;gBAEvD,MAAM,EAAE,aAAa;IAIjC;;OAEG;IACG,IAAI,CAAC,OAAO,GAAE,MAA8B,GAAG,OAAO,CAAC,IAAI,CAAC;IA4ClE;;OAEG;IACH,IAAI,WAAW,IAAI,iBAAiB,GAAG,IAAI,CAE1C;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,iBAAiB,GAAG,IAAI,CAE1C;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,GAAG,SAAS,CAE/B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,GAAG,SAAS,CAEjC;IAED;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACI,WAAW,IAAI,cAAc,CAAC,iBAAiB,CAAC;IAyBvD;;OAEG;IACI,WAAW,IAAI,cAAc,CAAC,iBAAiB,CAAC;IAyBvD;;;OAGG;IACI,MAAM,IAAI,cAAc,CAC3B;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAA;KAAE,GACtE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAA;KAAE,CACzE;IAuCD;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE;QACnB,YAAY,CAAC,EAAE,kBAAkB,CAAC;QAClC,YAAY,CAAC,EAAE,kBAAkB,CAAC;KACnC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACH,IAAI,MAAM,IAAI,aAAa,GAAG,IAAI,CAEjC;CACF"}
1
+ {"version":3,"file":"Demuxer.d.ts","sourceRoot":"","sources":["../../src/containers/Demuxer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAA8B,MAAM,8BAA8B,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAA8B,MAAM,8BAA8B,CAAC;AAG7F;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAC/F,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;AA+C/F;;GAEG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,cAAc,CAA6C;IAEnE,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,oBAAoB,CAAa;gBAE7B,MAAM,EAAE,aAAa;IAIjC;;OAEG;IACG,IAAI,CAAC,OAAO,GAAE,MAA8B,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDlE;;OAEG;IACH,IAAI,WAAW,IAAI,iBAAiB,GAAG,IAAI,CAE1C;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,iBAAiB,GAAG,IAAI,CAE1C;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,GAAG,SAAS,CAE/B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,GAAG,SAAS,CAEjC;IAED;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACI,WAAW,IAAI,cAAc,CAAC,iBAAiB,CAAC;IAyBvD;;OAEG;IACI,WAAW,IAAI,cAAc,CAAC,iBAAiB,CAAC;IAyBvD;;;OAGG;IACI,MAAM,IAAI,cAAc,CAC3B;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAA;KAAE,GACtE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAA;KAAE,CACzE;IAuCD;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE;QACnB,YAAY,CAAC,EAAE,kBAAkB,CAAC;QAClC,YAAY,CAAC,EAAE,kBAAkB,CAAC;KACnC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACH,IAAI,MAAM,IAAI,aAAa,GAAG,IAAI,CAEjC;CACF"}
@@ -63,6 +63,9 @@ export class Demuxer {
63
63
  _audioStreamIndex = -1;
64
64
  _videoTimeBase = null;
65
65
  _audioTimeBase = null;
66
+ // Pre-calculated multipliers for timestamp conversion (avoids division per packet)
67
+ _videoTimeMultiplier = 0;
68
+ _audioTimeMultiplier = 0;
66
69
  constructor(config) {
67
70
  this.path = config.path;
68
71
  }
@@ -79,6 +82,8 @@ export class Demuxer {
79
82
  num: videoStream.timeBase.num,
80
83
  den: videoStream.timeBase.den,
81
84
  };
85
+ // Pre-calculate multiplier: (num * 1_000_000) / den
86
+ this._videoTimeMultiplier = (videoStream.timeBase.num * 1_000_000) / videoStream.timeBase.den;
82
87
  const cp = videoStream.codecpar;
83
88
  this._videoConfig = {
84
89
  codec: mapVideoCodecId(cp.codecId, cp.extradata),
@@ -95,6 +100,8 @@ export class Demuxer {
95
100
  num: audioStream.timeBase.num,
96
101
  den: audioStream.timeBase.den,
97
102
  };
103
+ // Pre-calculate multiplier: (num * 1_000_000) / den
104
+ this._audioTimeMultiplier = (audioStream.timeBase.num * 1_000_000) / audioStream.timeBase.den;
98
105
  const cp = audioStream.codecpar;
99
106
  this._audioConfig = {
100
107
  codec: mapAudioCodecId(cp.codecId),
@@ -129,32 +136,32 @@ export class Demuxer {
129
136
  return this.demuxer?.duration;
130
137
  }
131
138
  /**
132
- * Convert timestamp from stream time base to microseconds
139
+ * Convert timestamp from stream time base to microseconds using pre-calculated multiplier
133
140
  */
134
- toMicroseconds(pts, timeBase) {
141
+ toMicroseconds(pts, multiplier) {
135
142
  const ptsNum = typeof pts === 'bigint' ? Number(pts) : pts;
136
- return Math.round((ptsNum * timeBase.num * 1_000_000) / timeBase.den);
143
+ return Math.round(ptsNum * multiplier);
137
144
  }
138
145
  /**
139
146
  * Iterate over video chunks
140
147
  */
141
148
  async *videoChunks() {
142
- if (!this.demuxer || this._videoStreamIndex < 0 || !this._videoConfig || !this._videoTimeBase) {
149
+ if (!this.demuxer || this._videoStreamIndex < 0 || !this._videoConfig || !this._videoTimeMultiplier) {
143
150
  return;
144
151
  }
145
152
  for await (const packet of this.demuxer.packets()) {
146
153
  if (!packet || !packet.data)
147
154
  continue;
148
155
  if (packet.streamIndex === this._videoStreamIndex) {
149
- const timestamp = this.toMicroseconds(packet.pts, this._videoTimeBase);
156
+ const timestamp = this.toMicroseconds(packet.pts, this._videoTimeMultiplier);
150
157
  const duration = packet.duration
151
- ? this.toMicroseconds(packet.duration, this._videoTimeBase)
158
+ ? this.toMicroseconds(packet.duration, this._videoTimeMultiplier)
152
159
  : undefined;
153
160
  const chunk = new EncodedVideoChunk({
154
161
  type: packet.isKeyframe ? 'key' : 'delta',
155
162
  timestamp,
156
163
  duration,
157
- data: new Uint8Array(packet.data),
164
+ data: packet.data.slice(),
158
165
  });
159
166
  yield chunk;
160
167
  }
@@ -164,22 +171,22 @@ export class Demuxer {
164
171
  * Iterate over audio chunks
165
172
  */
166
173
  async *audioChunks() {
167
- if (!this.demuxer || this._audioStreamIndex < 0 || !this._audioConfig || !this._audioTimeBase) {
174
+ if (!this.demuxer || this._audioStreamIndex < 0 || !this._audioConfig || !this._audioTimeMultiplier) {
168
175
  return;
169
176
  }
170
177
  for await (const packet of this.demuxer.packets()) {
171
178
  if (!packet || !packet.data)
172
179
  continue;
173
180
  if (packet.streamIndex === this._audioStreamIndex) {
174
- const timestamp = this.toMicroseconds(packet.pts, this._audioTimeBase);
181
+ const timestamp = this.toMicroseconds(packet.pts, this._audioTimeMultiplier);
175
182
  const duration = packet.duration
176
- ? this.toMicroseconds(packet.duration, this._audioTimeBase)
183
+ ? this.toMicroseconds(packet.duration, this._audioTimeMultiplier)
177
184
  : undefined;
178
185
  const chunk = new EncodedAudioChunk({
179
186
  type: packet.isKeyframe ? 'key' : 'delta',
180
187
  timestamp,
181
188
  duration,
182
- data: new Uint8Array(packet.data),
189
+ data: packet.data.slice(),
183
190
  });
184
191
  yield chunk;
185
192
  }
@@ -196,29 +203,29 @@ export class Demuxer {
196
203
  for await (const packet of this.demuxer.packets()) {
197
204
  if (!packet || !packet.data)
198
205
  continue;
199
- if (packet.streamIndex === this._videoStreamIndex && this._videoConfig && this._videoTimeBase) {
200
- const timestamp = this.toMicroseconds(packet.pts, this._videoTimeBase);
206
+ if (packet.streamIndex === this._videoStreamIndex && this._videoConfig && this._videoTimeMultiplier) {
207
+ const timestamp = this.toMicroseconds(packet.pts, this._videoTimeMultiplier);
201
208
  const duration = packet.duration
202
- ? this.toMicroseconds(packet.duration, this._videoTimeBase)
209
+ ? this.toMicroseconds(packet.duration, this._videoTimeMultiplier)
203
210
  : undefined;
204
211
  const chunk = new EncodedVideoChunk({
205
212
  type: packet.isKeyframe ? 'key' : 'delta',
206
213
  timestamp,
207
214
  duration,
208
- data: new Uint8Array(packet.data),
215
+ data: packet.data.slice(),
209
216
  });
210
217
  yield { type: 'video', chunk, config: this._videoConfig };
211
218
  }
212
- else if (packet.streamIndex === this._audioStreamIndex && this._audioConfig && this._audioTimeBase) {
213
- const timestamp = this.toMicroseconds(packet.pts, this._audioTimeBase);
219
+ else if (packet.streamIndex === this._audioStreamIndex && this._audioConfig && this._audioTimeMultiplier) {
220
+ const timestamp = this.toMicroseconds(packet.pts, this._audioTimeMultiplier);
214
221
  const duration = packet.duration
215
- ? this.toMicroseconds(packet.duration, this._audioTimeBase)
222
+ ? this.toMicroseconds(packet.duration, this._audioTimeMultiplier)
216
223
  : undefined;
217
224
  const chunk = new EncodedAudioChunk({
218
225
  type: packet.isKeyframe ? 'key' : 'delta',
219
226
  timestamp,
220
227
  duration,
221
- data: new Uint8Array(packet.data),
228
+ data: packet.data.slice(),
222
229
  });
223
230
  yield { type: 'audio', chunk, config: this._audioConfig };
224
231
  }