webcodecs-node 0.2.2 → 0.5.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.
- package/README.md +4 -0
- package/dist/__tests__/AudioData.test.js +2 -1
- package/dist/__tests__/AudioData.test.js.map +1 -1
- package/dist/__tests__/AudioDecoder.test.js +8 -8
- package/dist/__tests__/AudioDecoder.test.js.map +1 -1
- package/dist/__tests__/AudioEncoder.test.js +3 -3
- package/dist/__tests__/AudioEncoder.test.js.map +1 -1
- package/dist/__tests__/EncodedChunks.test.js +3 -2
- package/dist/__tests__/EncodedChunks.test.js.map +1 -1
- package/dist/__tests__/HardwareAcceleration.test.js +2 -1
- package/dist/__tests__/HardwareAcceleration.test.js.map +1 -1
- package/dist/__tests__/ImageDecoder.test.js +16 -45
- package/dist/__tests__/ImageDecoder.test.js.map +1 -1
- package/dist/__tests__/ImageDecoder.wpt.test.d.ts +8 -0
- package/dist/__tests__/ImageDecoder.wpt.test.d.ts.map +1 -0
- package/dist/__tests__/ImageDecoder.wpt.test.js +135 -0
- package/dist/__tests__/ImageDecoder.wpt.test.js.map +1 -0
- package/dist/__tests__/NodeAvDecoder.test.d.ts +2 -0
- package/dist/__tests__/NodeAvDecoder.test.d.ts.map +1 -0
- package/dist/__tests__/NodeAvDecoder.test.js +206 -0
- package/dist/__tests__/NodeAvDecoder.test.js.map +1 -0
- package/dist/__tests__/NodeAvEncoder.test.d.ts +2 -0
- package/dist/__tests__/NodeAvEncoder.test.d.ts.map +1 -0
- package/dist/__tests__/NodeAvEncoder.test.js +176 -0
- package/dist/__tests__/NodeAvEncoder.test.js.map +1 -0
- package/dist/__tests__/VideoDecoder.test.js +5 -5
- package/dist/__tests__/VideoDecoder.test.js.map +1 -1
- package/dist/__tests__/VideoEncoder.test.js +3 -3
- package/dist/__tests__/VideoEncoder.test.js.map +1 -1
- package/dist/__tests__/VideoFrame.test.js +4 -1
- package/dist/__tests__/VideoFrame.test.js.map +1 -1
- package/dist/backends/index.d.ts +3 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +2 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/types.d.ts +168 -0
- package/dist/backends/types.d.ts.map +1 -0
- package/dist/backends/types.js +25 -0
- package/dist/backends/types.js.map +1 -0
- package/dist/codec-utils/audio-codecs.d.ts +60 -0
- package/dist/codec-utils/audio-codecs.d.ts.map +1 -0
- package/dist/codec-utils/audio-codecs.js +117 -0
- package/dist/codec-utils/audio-codecs.js.map +1 -0
- package/dist/codec-utils/formats.d.ts +42 -0
- package/dist/codec-utils/formats.d.ts.map +1 -0
- package/dist/codec-utils/formats.js +147 -0
- package/dist/codec-utils/formats.js.map +1 -0
- package/dist/codec-utils/index.d.ts +9 -0
- package/dist/codec-utils/index.d.ts.map +1 -0
- package/dist/codec-utils/index.js +12 -0
- package/dist/codec-utils/index.js.map +1 -0
- package/dist/codec-utils/types.d.ts +87 -0
- package/dist/codec-utils/types.d.ts.map +1 -0
- package/dist/codec-utils/types.js +10 -0
- package/dist/codec-utils/types.js.map +1 -0
- package/dist/containers/Demuxer.d.ts +114 -0
- package/dist/containers/Demuxer.d.ts.map +1 -0
- package/dist/containers/Demuxer.js +256 -0
- package/dist/containers/Demuxer.js.map +1 -0
- package/dist/containers/Muxer.d.ts +142 -0
- package/dist/containers/Muxer.d.ts.map +1 -0
- package/dist/containers/Muxer.js +295 -0
- package/dist/containers/Muxer.js.map +1 -0
- package/dist/containers/extract.d.ts +25 -0
- package/dist/containers/extract.d.ts.map +1 -0
- package/dist/containers/extract.js +64 -0
- package/dist/containers/extract.js.map +1 -0
- package/dist/containers/index.d.ts +40 -0
- package/dist/containers/index.d.ts.map +1 -0
- package/dist/containers/index.js +41 -0
- package/dist/containers/index.js.map +1 -0
- package/dist/containers/transcode.d.ts +138 -0
- package/dist/containers/transcode.d.ts.map +1 -0
- package/dist/containers/transcode.js +536 -0
- package/dist/containers/transcode.js.map +1 -0
- package/dist/core/AudioData.d.ts +5 -1
- package/dist/core/AudioData.d.ts.map +1 -1
- package/dist/core/AudioData.js +69 -13
- package/dist/core/AudioData.js.map +1 -1
- package/dist/core/EncodedAudioChunk.d.ts +1 -1
- package/dist/core/EncodedAudioChunk.d.ts.map +1 -1
- package/dist/core/EncodedAudioChunk.js +1 -1
- package/dist/core/EncodedAudioChunk.js.map +1 -1
- package/dist/core/EncodedVideoChunk.d.ts.map +1 -1
- package/dist/core/EncodedVideoChunk.js +3 -19
- package/dist/core/EncodedVideoChunk.js.map +1 -1
- package/dist/core/VideoFrame.d.ts +31 -11
- package/dist/core/VideoFrame.d.ts.map +1 -1
- package/dist/core/VideoFrame.js +244 -81
- package/dist/core/VideoFrame.js.map +1 -1
- package/dist/decoders/AudioDecoder.d.ts +14 -12
- package/dist/decoders/AudioDecoder.d.ts.map +1 -1
- package/dist/decoders/AudioDecoder.js +113 -173
- package/dist/decoders/AudioDecoder.js.map +1 -1
- package/dist/decoders/ImageDecoder.d.ts +1 -3
- package/dist/decoders/ImageDecoder.d.ts.map +1 -1
- package/dist/decoders/ImageDecoder.js +39 -192
- package/dist/decoders/ImageDecoder.js.map +1 -1
- package/dist/decoders/VideoDecoder.d.ts +14 -13
- package/dist/decoders/VideoDecoder.d.ts.map +1 -1
- package/dist/decoders/VideoDecoder.js +115 -166
- package/dist/decoders/VideoDecoder.js.map +1 -1
- package/dist/demos/demo-1080p-transcode.d.ts +8 -0
- package/dist/demos/demo-1080p-transcode.d.ts.map +1 -0
- package/dist/demos/demo-1080p-transcode.js +188 -0
- package/dist/demos/demo-1080p-transcode.js.map +1 -0
- package/dist/demos/demo-containers.d.ts +7 -0
- package/dist/demos/demo-containers.d.ts.map +1 -0
- package/dist/demos/demo-containers.js +140 -0
- package/dist/demos/demo-containers.js.map +1 -0
- package/dist/demos/demo-conversion.js +2 -2
- package/dist/demos/demo-conversion.js.map +1 -1
- package/dist/demos/demo-four-corners.d.ts +6 -0
- package/dist/demos/demo-four-corners.d.ts.map +1 -0
- package/dist/demos/demo-four-corners.js +218 -0
- package/dist/demos/demo-four-corners.js.map +1 -0
- package/dist/demos/demo-hwaccel-conversion.js +1 -1
- package/dist/demos/demo-hwaccel-conversion.js.map +1 -1
- package/dist/demos/demo-hwaccel.js +1 -1
- package/dist/demos/demo-hwaccel.js.map +1 -1
- package/dist/demos/demo-samples.js +232 -68
- package/dist/demos/demo-samples.js.map +1 -1
- package/dist/demos/demo-streaming.js +6 -6
- package/dist/demos/demo-streaming.js.map +1 -1
- package/dist/encoders/AudioEncoder.d.ts +14 -13
- package/dist/encoders/AudioEncoder.d.ts.map +1 -1
- package/dist/encoders/AudioEncoder.js +138 -228
- package/dist/encoders/AudioEncoder.js.map +1 -1
- package/dist/encoders/VideoEncoder.d.ts +13 -14
- package/dist/encoders/VideoEncoder.d.ts.map +1 -1
- package/dist/encoders/VideoEncoder.js +92 -161
- package/dist/encoders/VideoEncoder.js.map +1 -1
- package/dist/ffmpeg/index.d.ts +3 -2
- package/dist/ffmpeg/index.d.ts.map +1 -1
- package/dist/ffmpeg/index.js +3 -3
- package/dist/ffmpeg/index.js.map +1 -1
- package/dist/formats/conversions/batch-converter.d.ts +61 -0
- package/dist/formats/conversions/batch-converter.d.ts.map +1 -0
- package/dist/formats/conversions/batch-converter.js +274 -0
- package/dist/formats/conversions/batch-converter.js.map +1 -0
- package/dist/formats/conversions/frame-converter.d.ts +17 -0
- package/dist/formats/conversions/frame-converter.d.ts.map +1 -1
- package/dist/formats/conversions/frame-converter.js +144 -10
- package/dist/formats/conversions/frame-converter.js.map +1 -1
- package/dist/formats/conversions/index.d.ts +2 -0
- package/dist/formats/conversions/index.d.ts.map +1 -1
- package/dist/formats/conversions/index.js +4 -0
- package/dist/formats/conversions/index.js.map +1 -1
- package/dist/hardware/decoder-args.d.ts +2 -7
- package/dist/hardware/decoder-args.d.ts.map +1 -1
- package/dist/hardware/decoder-args.js +2 -32
- package/dist/hardware/decoder-args.js.map +1 -1
- package/dist/hardware/detection.d.ts +1 -1
- package/dist/hardware/detection.d.ts.map +1 -1
- package/dist/hardware/detection.js +54 -27
- package/dist/hardware/detection.js.map +1 -1
- package/dist/hardware/encoder-args.d.ts +2 -11
- package/dist/hardware/encoder-args.d.ts.map +1 -1
- package/dist/hardware/encoder-args.js +2 -71
- package/dist/hardware/encoder-args.js.map +1 -1
- package/dist/hardware/index.d.ts +2 -2
- package/dist/hardware/index.d.ts.map +1 -1
- package/dist/hardware/index.js +2 -2
- package/dist/hardware/index.js.map +1 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -6
- package/dist/index.js.map +1 -1
- package/dist/mediabunny/FFmpegAudioDecoder.d.ts +4 -17
- package/dist/mediabunny/FFmpegAudioDecoder.d.ts.map +1 -1
- package/dist/mediabunny/FFmpegAudioDecoder.js +57 -185
- package/dist/mediabunny/FFmpegAudioDecoder.js.map +1 -1
- package/dist/mediabunny/FFmpegAudioEncoder.d.ts +6 -39
- package/dist/mediabunny/FFmpegAudioEncoder.d.ts.map +1 -1
- package/dist/mediabunny/FFmpegAudioEncoder.js +66 -329
- package/dist/mediabunny/FFmpegAudioEncoder.js.map +1 -1
- package/dist/mediabunny/FFmpegVideoDecoder.d.ts +5 -38
- package/dist/mediabunny/FFmpegVideoDecoder.d.ts.map +1 -1
- package/dist/mediabunny/FFmpegVideoDecoder.js +39 -283
- package/dist/mediabunny/FFmpegVideoDecoder.js.map +1 -1
- package/dist/mediabunny/FFmpegVideoEncoder.d.ts +9 -37
- package/dist/mediabunny/FFmpegVideoEncoder.d.ts.map +1 -1
- package/dist/mediabunny/FFmpegVideoEncoder.js +49 -336
- package/dist/mediabunny/FFmpegVideoEncoder.js.map +1 -1
- package/dist/node-av/HardwarePipeline.d.ts +36 -0
- package/dist/node-av/HardwarePipeline.d.ts.map +1 -0
- package/dist/node-av/HardwarePipeline.js +243 -0
- package/dist/node-av/HardwarePipeline.js.map +1 -0
- package/dist/node-av/NodeAvAudioDecoder.d.ts +46 -0
- package/dist/node-av/NodeAvAudioDecoder.d.ts.map +1 -0
- package/dist/node-av/NodeAvAudioDecoder.js +350 -0
- package/dist/node-av/NodeAvAudioDecoder.js.map +1 -0
- package/dist/node-av/NodeAvAudioEncoder.d.ts +50 -0
- package/dist/node-av/NodeAvAudioEncoder.d.ts.map +1 -0
- package/dist/node-av/NodeAvAudioEncoder.js +506 -0
- package/dist/node-av/NodeAvAudioEncoder.js.map +1 -0
- package/dist/node-av/NodeAvImageDecoder.d.ts +114 -0
- package/dist/node-av/NodeAvImageDecoder.d.ts.map +1 -0
- package/dist/node-av/NodeAvImageDecoder.js +406 -0
- package/dist/node-av/NodeAvImageDecoder.js.map +1 -0
- package/dist/node-av/NodeAvVideoDecoder.d.ts +43 -0
- package/dist/node-av/NodeAvVideoDecoder.d.ts.map +1 -0
- package/dist/node-av/NodeAvVideoDecoder.js +365 -0
- package/dist/node-av/NodeAvVideoDecoder.js.map +1 -0
- package/dist/node-av/NodeAvVideoEncoder.d.ts +56 -0
- package/dist/node-av/NodeAvVideoEncoder.d.ts.map +1 -0
- package/dist/node-av/NodeAvVideoEncoder.js +509 -0
- package/dist/node-av/NodeAvVideoEncoder.js.map +1 -0
- package/dist/polyfill.d.ts.map +1 -1
- package/dist/polyfill.js +11 -9
- package/dist/polyfill.js.map +1 -1
- package/dist/utils/aac.d.ts.map +1 -1
- package/dist/utils/aac.js +6 -0
- package/dist/utils/aac.js.map +1 -1
- package/dist/utils/buffer-pool.d.ts +109 -0
- package/dist/utils/buffer-pool.d.ts.map +1 -0
- package/dist/utils/buffer-pool.js +278 -0
- package/dist/utils/buffer-pool.js.map +1 -0
- package/dist/utils/codec-cache.d.ts +65 -0
- package/dist/utils/codec-cache.d.ts.map +1 -0
- package/dist/utils/codec-cache.js +116 -0
- package/dist/utils/codec-cache.js.map +1 -0
- package/dist/utils/errors.d.ts +62 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +84 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/event-target.d.ts +42 -0
- package/dist/utils/event-target.d.ts.map +1 -0
- package/dist/utils/event-target.js +96 -0
- package/dist/utils/event-target.js.map +1 -0
- package/dist/utils/hardware-pool.d.ts +88 -0
- package/dist/utils/hardware-pool.d.ts.map +1 -0
- package/dist/utils/hardware-pool.js +266 -0
- package/dist/utils/hardware-pool.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +12 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/timeout.d.ts +44 -0
- package/dist/utils/timeout.d.ts.map +1 -0
- package/dist/utils/timeout.js +73 -0
- package/dist/utils/timeout.js.map +1 -0
- package/dist/utils/type-guards.d.ts +11 -1
- package/dist/utils/type-guards.d.ts.map +1 -1
- package/dist/utils/type-guards.js.map +1 -1
- package/package.json +20 -34
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container Muxer - Writes encoded chunks to container files (MP4, WebM, MKV)
|
|
3
|
+
*
|
|
4
|
+
* Wraps node-av's Muxer to provide a WebCodecs-compatible interface that accepts
|
|
5
|
+
* EncodedVideoChunk and EncodedAudioChunk objects.
|
|
6
|
+
*/
|
|
7
|
+
import { Muxer as NodeAvMuxer, Demuxer as NodeAvDemuxer, Encoder as NodeAvEncoder, AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, AV_CODEC_ID_VP8, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1, AV_CODEC_ID_AAC, AV_CODEC_ID_OPUS, AV_CODEC_ID_MP3, AV_CODEC_ID_VORBIS, AV_CODEC_ID_FLAC, AV_PIX_FMT_YUV420P, AV_SAMPLE_FMT_FLTP, } from 'node-av';
|
|
8
|
+
import { withTimeout, DEFAULT_TIMEOUTS } from '../utils/timeout.js';
|
|
9
|
+
/**
|
|
10
|
+
* Maps WebCodecs codec strings to FFmpeg codec IDs
|
|
11
|
+
*/
|
|
12
|
+
function mapVideoCodecId(codec) {
|
|
13
|
+
const codecLower = codec.toLowerCase();
|
|
14
|
+
if (codecLower.startsWith('avc1') || codecLower.startsWith('avc3') || codecLower === 'h264') {
|
|
15
|
+
return AV_CODEC_ID_H264;
|
|
16
|
+
}
|
|
17
|
+
else if (codecLower.startsWith('hvc1') || codecLower.startsWith('hev1') || codecLower === 'hevc') {
|
|
18
|
+
return AV_CODEC_ID_HEVC;
|
|
19
|
+
}
|
|
20
|
+
else if (codecLower === 'vp8') {
|
|
21
|
+
return AV_CODEC_ID_VP8;
|
|
22
|
+
}
|
|
23
|
+
else if (codecLower.startsWith('vp09') || codecLower === 'vp9') {
|
|
24
|
+
return AV_CODEC_ID_VP9;
|
|
25
|
+
}
|
|
26
|
+
else if (codecLower.startsWith('av01') || codecLower === 'av1') {
|
|
27
|
+
return AV_CODEC_ID_AV1;
|
|
28
|
+
}
|
|
29
|
+
throw new Error(`Unsupported video codec: ${codec}`);
|
|
30
|
+
}
|
|
31
|
+
function mapAudioCodecId(codec) {
|
|
32
|
+
const codecLower = codec.toLowerCase();
|
|
33
|
+
if (codecLower.startsWith('mp4a') || codecLower === 'aac') {
|
|
34
|
+
return AV_CODEC_ID_AAC;
|
|
35
|
+
}
|
|
36
|
+
else if (codecLower === 'mp3') {
|
|
37
|
+
return AV_CODEC_ID_MP3;
|
|
38
|
+
}
|
|
39
|
+
else if (codecLower === 'opus') {
|
|
40
|
+
return AV_CODEC_ID_OPUS;
|
|
41
|
+
}
|
|
42
|
+
else if (codecLower === 'vorbis') {
|
|
43
|
+
return AV_CODEC_ID_VORBIS;
|
|
44
|
+
}
|
|
45
|
+
else if (codecLower === 'flac') {
|
|
46
|
+
return AV_CODEC_ID_FLAC;
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`Unsupported audio codec: ${codec}`);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Infer container format from file extension
|
|
52
|
+
*/
|
|
53
|
+
function inferFormat(path) {
|
|
54
|
+
const ext = path.split('.').pop()?.toLowerCase();
|
|
55
|
+
switch (ext) {
|
|
56
|
+
case 'mp4':
|
|
57
|
+
case 'm4v':
|
|
58
|
+
return 'mp4';
|
|
59
|
+
case 'webm':
|
|
60
|
+
return 'webm';
|
|
61
|
+
case 'mkv':
|
|
62
|
+
return 'matroska';
|
|
63
|
+
case 'mov':
|
|
64
|
+
return 'mov';
|
|
65
|
+
case 'avi':
|
|
66
|
+
return 'avi';
|
|
67
|
+
case 'ts':
|
|
68
|
+
return 'mpegts';
|
|
69
|
+
default:
|
|
70
|
+
return 'mp4';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Container muxer that accepts WebCodecs-compatible chunks
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const muxer = new Muxer({ path: 'output.mp4' });
|
|
79
|
+
* await muxer.open();
|
|
80
|
+
* await muxer.addVideoTrack({
|
|
81
|
+
* codec: 'avc1.42001E',
|
|
82
|
+
* codedWidth: 640,
|
|
83
|
+
* codedHeight: 480,
|
|
84
|
+
* framerate: 30,
|
|
85
|
+
* description: spsNaluBuffer, // Optional: H.264 SPS/PPS
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* // Write encoded chunks from VideoEncoder
|
|
89
|
+
* encoder.configure({ codec: 'avc1.42001E', ... });
|
|
90
|
+
* encoder.encode(frame);
|
|
91
|
+
* // In output callback:
|
|
92
|
+
* await muxer.writeVideoChunk(chunk);
|
|
93
|
+
*
|
|
94
|
+
* await muxer.close();
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export class Muxer {
|
|
98
|
+
muxer = null;
|
|
99
|
+
config;
|
|
100
|
+
_videoStreamIndex = -1;
|
|
101
|
+
_audioStreamIndex = -1;
|
|
102
|
+
_videoEncoder = null;
|
|
103
|
+
_audioEncoder = null;
|
|
104
|
+
_videoConfig = null;
|
|
105
|
+
_audioConfig = null;
|
|
106
|
+
_videoChunkCount = 0;
|
|
107
|
+
_audioChunkCount = 0;
|
|
108
|
+
constructor(config) {
|
|
109
|
+
this.config = config;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Open the muxer for writing
|
|
113
|
+
*
|
|
114
|
+
* @param timeout - Operation timeout in milliseconds (default: 15000)
|
|
115
|
+
*/
|
|
116
|
+
async open(timeout = DEFAULT_TIMEOUTS.open) {
|
|
117
|
+
const format = this.config.format || inferFormat(this.config.path);
|
|
118
|
+
this.muxer = await withTimeout(NodeAvMuxer.open(this.config.path, { format }), timeout, `Muxer open (${this.config.path})`);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Add a video track to the output
|
|
122
|
+
*
|
|
123
|
+
* @param config - Video track configuration
|
|
124
|
+
* @returns Stream index for the video track
|
|
125
|
+
*/
|
|
126
|
+
async addVideoTrack(config) {
|
|
127
|
+
if (!this.muxer) {
|
|
128
|
+
throw new Error('Muxer not opened');
|
|
129
|
+
}
|
|
130
|
+
this._videoConfig = config;
|
|
131
|
+
const codecId = mapVideoCodecId(config.codec);
|
|
132
|
+
// Create an encoder to properly configure the output stream
|
|
133
|
+
// The encoder sets up codec parameters that the muxer needs
|
|
134
|
+
this._videoEncoder = await NodeAvEncoder.create(codecId, {
|
|
135
|
+
width: config.codedWidth,
|
|
136
|
+
height: config.codedHeight,
|
|
137
|
+
pixelFormat: AV_PIX_FMT_YUV420P,
|
|
138
|
+
timeBase: { num: 1, den: config.framerate || 30 },
|
|
139
|
+
frameRate: { num: config.framerate || 30, den: 1 },
|
|
140
|
+
bitrate: config.bitrate || 1_000_000,
|
|
141
|
+
gopSize: 30,
|
|
142
|
+
// Set extradata from description (SPS/PPS for H.264, etc.)
|
|
143
|
+
extradata: config.description ? Buffer.from(config.description) : undefined,
|
|
144
|
+
});
|
|
145
|
+
// Add the encoder's stream to the muxer
|
|
146
|
+
this._videoStreamIndex = this.muxer.addStream(this._videoEncoder);
|
|
147
|
+
return this._videoStreamIndex;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Add an audio track to the output
|
|
151
|
+
*
|
|
152
|
+
* @param config - Audio track configuration
|
|
153
|
+
* @returns Stream index for the audio track
|
|
154
|
+
*/
|
|
155
|
+
async addAudioTrack(config) {
|
|
156
|
+
if (!this.muxer) {
|
|
157
|
+
throw new Error('Muxer not opened');
|
|
158
|
+
}
|
|
159
|
+
this._audioConfig = config;
|
|
160
|
+
const codecId = mapAudioCodecId(config.codec);
|
|
161
|
+
// Create an encoder to properly configure the output stream
|
|
162
|
+
this._audioEncoder = await NodeAvEncoder.create(codecId, {
|
|
163
|
+
sampleRate: config.sampleRate,
|
|
164
|
+
channels: config.numberOfChannels,
|
|
165
|
+
sampleFormat: AV_SAMPLE_FMT_FLTP,
|
|
166
|
+
bitrate: config.bitrate || 128_000,
|
|
167
|
+
// Set extradata from description (AudioSpecificConfig for AAC, etc.)
|
|
168
|
+
extradata: config.description ? Buffer.from(config.description) : undefined,
|
|
169
|
+
});
|
|
170
|
+
// Add the encoder's stream to the muxer
|
|
171
|
+
this._audioStreamIndex = this.muxer.addStream(this._audioEncoder);
|
|
172
|
+
return this._audioStreamIndex;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Write an encoded video chunk to the output container
|
|
176
|
+
*
|
|
177
|
+
* @param chunk - EncodedVideoChunk from VideoEncoder
|
|
178
|
+
*/
|
|
179
|
+
async writeVideoChunk(chunk) {
|
|
180
|
+
if (!this.muxer || this._videoStreamIndex < 0) {
|
|
181
|
+
throw new Error('Video track not configured. Call addVideoTrack() first.');
|
|
182
|
+
}
|
|
183
|
+
// Create a packet from the chunk data
|
|
184
|
+
const packetData = {
|
|
185
|
+
data: Buffer.from(chunk._buffer),
|
|
186
|
+
pts: BigInt(Math.round(chunk.timestamp)), // microseconds
|
|
187
|
+
dts: BigInt(Math.round(chunk.timestamp)),
|
|
188
|
+
duration: chunk.duration ? BigInt(Math.round(chunk.duration)) : undefined,
|
|
189
|
+
isKeyframe: chunk.type === 'key',
|
|
190
|
+
};
|
|
191
|
+
await this.muxer.writePacket(packetData, this._videoStreamIndex);
|
|
192
|
+
this._videoChunkCount++;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Write an encoded audio chunk to the output container
|
|
196
|
+
*
|
|
197
|
+
* @param chunk - EncodedAudioChunk from AudioEncoder
|
|
198
|
+
*/
|
|
199
|
+
async writeAudioChunk(chunk) {
|
|
200
|
+
if (!this.muxer || this._audioStreamIndex < 0) {
|
|
201
|
+
throw new Error('Audio track not configured. Call addAudioTrack() first.');
|
|
202
|
+
}
|
|
203
|
+
// Create a packet from the chunk data
|
|
204
|
+
const packetData = {
|
|
205
|
+
data: Buffer.from(chunk._rawData),
|
|
206
|
+
pts: BigInt(Math.round(chunk.timestamp)), // microseconds
|
|
207
|
+
dts: BigInt(Math.round(chunk.timestamp)),
|
|
208
|
+
duration: chunk.duration ? BigInt(Math.round(chunk.duration)) : undefined,
|
|
209
|
+
isKeyframe: chunk.type === 'key',
|
|
210
|
+
};
|
|
211
|
+
await this.muxer.writePacket(packetData, this._audioStreamIndex);
|
|
212
|
+
this._audioChunkCount++;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Finalize and close the muxer
|
|
216
|
+
*
|
|
217
|
+
* @param timeout - Operation timeout in milliseconds (default: 10000)
|
|
218
|
+
*/
|
|
219
|
+
async close(timeout = DEFAULT_TIMEOUTS.close) {
|
|
220
|
+
// Close encoders (sync)
|
|
221
|
+
if (this._videoEncoder) {
|
|
222
|
+
this._videoEncoder.close();
|
|
223
|
+
this._videoEncoder = null;
|
|
224
|
+
}
|
|
225
|
+
if (this._audioEncoder) {
|
|
226
|
+
this._audioEncoder.close();
|
|
227
|
+
this._audioEncoder = null;
|
|
228
|
+
}
|
|
229
|
+
// Close muxer (async with timeout)
|
|
230
|
+
if (this.muxer) {
|
|
231
|
+
await withTimeout(this.muxer.close(), timeout, 'Muxer close');
|
|
232
|
+
this.muxer = null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Get the underlying node-av muxer (for advanced use)
|
|
237
|
+
*/
|
|
238
|
+
get native() {
|
|
239
|
+
return this.muxer;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get number of video chunks written
|
|
243
|
+
*/
|
|
244
|
+
get videoChunkCount() {
|
|
245
|
+
return this._videoChunkCount;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get number of audio chunks written
|
|
249
|
+
*/
|
|
250
|
+
get audioChunkCount() {
|
|
251
|
+
return this._audioChunkCount;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Helper class for stream copy (remux) operations
|
|
256
|
+
* This copies encoded data from one container to another without re-encoding
|
|
257
|
+
*/
|
|
258
|
+
export class StreamCopier {
|
|
259
|
+
srcDemuxer = null;
|
|
260
|
+
dstMuxer = null;
|
|
261
|
+
/**
|
|
262
|
+
* Remux a file from one container format to another
|
|
263
|
+
* This performs a stream copy without re-encoding
|
|
264
|
+
*/
|
|
265
|
+
static async remux(inputPath, outputPath, options) {
|
|
266
|
+
const demuxer = await NodeAvDemuxer.open(inputPath);
|
|
267
|
+
const format = options?.format || inferFormat(outputPath);
|
|
268
|
+
const muxer = await NodeAvMuxer.open(outputPath, { format });
|
|
269
|
+
const streamMap = new Map();
|
|
270
|
+
// Copy video stream
|
|
271
|
+
const videoStream = demuxer.video();
|
|
272
|
+
if (videoStream) {
|
|
273
|
+
const outIndex = muxer.addStream(videoStream);
|
|
274
|
+
streamMap.set(videoStream.index, outIndex);
|
|
275
|
+
}
|
|
276
|
+
// Copy audio stream
|
|
277
|
+
const audioStream = demuxer.audio();
|
|
278
|
+
if (audioStream) {
|
|
279
|
+
const outIndex = muxer.addStream(audioStream);
|
|
280
|
+
streamMap.set(audioStream.index, outIndex);
|
|
281
|
+
}
|
|
282
|
+
// Copy packets
|
|
283
|
+
for await (const packet of demuxer.packets()) {
|
|
284
|
+
if (!packet)
|
|
285
|
+
continue;
|
|
286
|
+
const outIndex = streamMap.get(packet.streamIndex);
|
|
287
|
+
if (outIndex !== undefined) {
|
|
288
|
+
await muxer.writePacket(packet, outIndex);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
await demuxer.close();
|
|
292
|
+
await muxer.close();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=Muxer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Muxer.js","sourceRoot":"","sources":["../../src/containers/Muxer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame extraction utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to extract decoded frames from container files.
|
|
5
|
+
*/
|
|
6
|
+
import { VideoFrame } from '../core/VideoFrame.js';
|
|
7
|
+
/**
|
|
8
|
+
* Extract video frames from a container file as VideoFrame objects
|
|
9
|
+
*
|
|
10
|
+
* This function uses our WebCodecs VideoDecoder to decode frames,
|
|
11
|
+
* providing WebCodecs-compatible VideoFrame objects.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { extractVideoFrames } from 'webcodecs-node/containers';
|
|
16
|
+
*
|
|
17
|
+
* for await (const frame of extractVideoFrames('input.mp4')) {
|
|
18
|
+
* console.log(`Frame: ${frame.timestamp}us, ${frame.codedWidth}x${frame.codedHeight}`);
|
|
19
|
+
* // Process frame...
|
|
20
|
+
* frame.close();
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractVideoFrames(inputPath: string): AsyncGenerator<VideoFrame>;
|
|
25
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/containers/extract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAuB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CA8CvF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame extraction utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to extract decoded frames from container files.
|
|
5
|
+
*/
|
|
6
|
+
import { Demuxer } from './Demuxer.js';
|
|
7
|
+
import { VideoDecoder } from '../decoders/VideoDecoder.js';
|
|
8
|
+
/**
|
|
9
|
+
* Extract video frames from a container file as VideoFrame objects
|
|
10
|
+
*
|
|
11
|
+
* This function uses our WebCodecs VideoDecoder to decode frames,
|
|
12
|
+
* providing WebCodecs-compatible VideoFrame objects.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { extractVideoFrames } from 'webcodecs-node/containers';
|
|
17
|
+
*
|
|
18
|
+
* for await (const frame of extractVideoFrames('input.mp4')) {
|
|
19
|
+
* console.log(`Frame: ${frame.timestamp}us, ${frame.codedWidth}x${frame.codedHeight}`);
|
|
20
|
+
* // Process frame...
|
|
21
|
+
* frame.close();
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export async function* extractVideoFrames(inputPath) {
|
|
26
|
+
const demuxer = new Demuxer({ path: inputPath });
|
|
27
|
+
await demuxer.open();
|
|
28
|
+
const videoConfig = demuxer.videoConfig;
|
|
29
|
+
if (!videoConfig) {
|
|
30
|
+
await demuxer.close();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Collect frames as they're decoded
|
|
34
|
+
const frames = [];
|
|
35
|
+
const decoder = new VideoDecoder({
|
|
36
|
+
output: (frame) => {
|
|
37
|
+
frames.push(frame);
|
|
38
|
+
},
|
|
39
|
+
error: (err) => console.error('Decode error:', err),
|
|
40
|
+
});
|
|
41
|
+
decoder.configure({
|
|
42
|
+
codec: videoConfig.codec,
|
|
43
|
+
codedWidth: videoConfig.codedWidth,
|
|
44
|
+
codedHeight: videoConfig.codedHeight,
|
|
45
|
+
description: videoConfig.description,
|
|
46
|
+
});
|
|
47
|
+
// Decode all video chunks
|
|
48
|
+
for await (const chunk of demuxer.videoChunks()) {
|
|
49
|
+
decoder.decode(chunk);
|
|
50
|
+
// Yield any decoded frames
|
|
51
|
+
while (frames.length > 0) {
|
|
52
|
+
yield frames.shift();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Flush decoder to get remaining frames
|
|
56
|
+
await decoder.flush();
|
|
57
|
+
decoder.close();
|
|
58
|
+
await demuxer.close();
|
|
59
|
+
// Yield any remaining frames
|
|
60
|
+
for (const frame of frames) {
|
|
61
|
+
yield frame;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/containers/extract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG3D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,kBAAkB,CAAC,SAAiB;IACzD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACjD,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IAErB,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACxC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,oCAAoC;IACpC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAEhC,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;QAC/B,MAAM,EAAE,CAAC,KAAiB,EAAE,EAAE;YAC5B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC;KACpD,CAAC,CAAC;IAEH,OAAO,CAAC,SAAS,CAAC;QAChB,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,UAAU,EAAE,WAAW,CAAC,UAAU;QAClC,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,WAAW,EAAE,WAAW,CAAC,WAAW;KACrC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEtB,2BAA2B;QAC3B,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,MAAM,CAAC,KAAK,EAAG,CAAC;QACxB,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACtB,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IAEtB,6BAA6B;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container handling module for WebCodecs
|
|
3
|
+
*
|
|
4
|
+
* This module provides container (MP4, WebM, MKV) demuxing, muxing, and transcoding
|
|
5
|
+
* capabilities using node-av as the backend.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { Demuxer, transcode, getMediaInfo } from 'webcodecs-node/containers';
|
|
10
|
+
*
|
|
11
|
+
* // Get media info
|
|
12
|
+
* const info = await getMediaInfo('video.mp4');
|
|
13
|
+
* console.log(info.video.codec, info.video.width, info.video.height);
|
|
14
|
+
*
|
|
15
|
+
* // Demux video chunks for WebCodecs processing
|
|
16
|
+
* const demuxer = new Demuxer({ path: 'video.mp4' });
|
|
17
|
+
* await demuxer.open();
|
|
18
|
+
* for await (const chunk of demuxer.videoChunks()) {
|
|
19
|
+
* // Feed to VideoDecoder...
|
|
20
|
+
* }
|
|
21
|
+
* await demuxer.close();
|
|
22
|
+
*
|
|
23
|
+
* // Transcode to different codec/settings
|
|
24
|
+
* await transcode('input.mp4', 'output.mp4', {
|
|
25
|
+
* videoCodec: 'h264',
|
|
26
|
+
* videoBitrate: 1_000_000,
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Remux to different container (no re-encoding)
|
|
30
|
+
* await remux('input.mp4', 'output.mkv');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export { Demuxer } from './Demuxer.js';
|
|
34
|
+
export type { DemuxerConfig, VideoStreamConfig, AudioStreamConfig, VideoChunkCallback, AudioChunkCallback, } from './Demuxer.js';
|
|
35
|
+
export { Muxer, StreamCopier } from './Muxer.js';
|
|
36
|
+
export type { MuxerConfig, VideoTrackConfig, AudioTrackConfig } from './Muxer.js';
|
|
37
|
+
export { remux, transcode, getMediaInfo } from './transcode.js';
|
|
38
|
+
export type { TranscodeOptions, TranscodeProgress, TranscodeResult, MediaInfo, VideoCodec, AudioCodec, HardwareAcceleration, } from './transcode.js';
|
|
39
|
+
export { extractVideoFrames } from './extract.js';
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/containers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGlF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,SAAS,EACT,UAAU,EACV,UAAU,EACV,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container handling module for WebCodecs
|
|
3
|
+
*
|
|
4
|
+
* This module provides container (MP4, WebM, MKV) demuxing, muxing, and transcoding
|
|
5
|
+
* capabilities using node-av as the backend.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { Demuxer, transcode, getMediaInfo } from 'webcodecs-node/containers';
|
|
10
|
+
*
|
|
11
|
+
* // Get media info
|
|
12
|
+
* const info = await getMediaInfo('video.mp4');
|
|
13
|
+
* console.log(info.video.codec, info.video.width, info.video.height);
|
|
14
|
+
*
|
|
15
|
+
* // Demux video chunks for WebCodecs processing
|
|
16
|
+
* const demuxer = new Demuxer({ path: 'video.mp4' });
|
|
17
|
+
* await demuxer.open();
|
|
18
|
+
* for await (const chunk of demuxer.videoChunks()) {
|
|
19
|
+
* // Feed to VideoDecoder...
|
|
20
|
+
* }
|
|
21
|
+
* await demuxer.close();
|
|
22
|
+
*
|
|
23
|
+
* // Transcode to different codec/settings
|
|
24
|
+
* await transcode('input.mp4', 'output.mp4', {
|
|
25
|
+
* videoCodec: 'h264',
|
|
26
|
+
* videoBitrate: 1_000_000,
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Remux to different container (no re-encoding)
|
|
30
|
+
* await remux('input.mp4', 'output.mkv');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
// Demuxer
|
|
34
|
+
export { Demuxer } from './Demuxer.js';
|
|
35
|
+
// Muxer
|
|
36
|
+
export { Muxer, StreamCopier } from './Muxer.js';
|
|
37
|
+
// Transcoding utilities
|
|
38
|
+
export { remux, transcode, getMediaInfo } from './transcode.js';
|
|
39
|
+
// Frame extraction
|
|
40
|
+
export { extractVideoFrames } from './extract.js';
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/containers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AASvC,QAAQ;AACR,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGjD,wBAAwB;AACxB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAWhE,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level transcoding utilities using node-av
|
|
3
|
+
*
|
|
4
|
+
* Provides easy-to-use functions for common transcoding operations.
|
|
5
|
+
* Uses node-av internally for efficient end-to-end processing.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Video codec options for transcoding
|
|
9
|
+
*/
|
|
10
|
+
export type VideoCodec = 'h264' | 'hevc' | 'vp8' | 'vp9' | 'av1' | 'copy';
|
|
11
|
+
/**
|
|
12
|
+
* Audio codec options for transcoding
|
|
13
|
+
*/
|
|
14
|
+
export type AudioCodec = 'aac' | 'opus' | 'mp3' | 'copy';
|
|
15
|
+
/**
|
|
16
|
+
* Hardware acceleration preference
|
|
17
|
+
*/
|
|
18
|
+
export type HardwareAcceleration = 'no-preference' | 'prefer-hardware' | 'prefer-software';
|
|
19
|
+
/**
|
|
20
|
+
* Transcoding options
|
|
21
|
+
*/
|
|
22
|
+
export interface TranscodeOptions {
|
|
23
|
+
/** Target video codec */
|
|
24
|
+
videoCodec?: VideoCodec;
|
|
25
|
+
/** Target audio codec */
|
|
26
|
+
audioCodec?: AudioCodec;
|
|
27
|
+
/** Target video bitrate in bits per second */
|
|
28
|
+
videoBitrate?: number;
|
|
29
|
+
/** Target audio bitrate in bits per second */
|
|
30
|
+
audioBitrate?: number;
|
|
31
|
+
/** Target video width (maintains aspect ratio if only width specified) */
|
|
32
|
+
width?: number;
|
|
33
|
+
/** Target video height */
|
|
34
|
+
height?: number;
|
|
35
|
+
/** Target framerate */
|
|
36
|
+
framerate?: number;
|
|
37
|
+
/** GOP size (keyframe interval) */
|
|
38
|
+
gopSize?: number;
|
|
39
|
+
/** Target audio sample rate */
|
|
40
|
+
sampleRate?: number;
|
|
41
|
+
/** Target number of audio channels */
|
|
42
|
+
numberOfChannels?: number;
|
|
43
|
+
/** Output container format (mp4, webm, mkv) - inferred from extension if not specified */
|
|
44
|
+
format?: string;
|
|
45
|
+
/** Hardware acceleration preference (default: 'no-preference') */
|
|
46
|
+
hardwareAcceleration?: HardwareAcceleration;
|
|
47
|
+
/** Progress callback */
|
|
48
|
+
onProgress?: (progress: TranscodeProgress) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Progress information during transcoding
|
|
52
|
+
*/
|
|
53
|
+
export interface TranscodeProgress {
|
|
54
|
+
/** Number of video frames processed */
|
|
55
|
+
videoFrames: number;
|
|
56
|
+
/** Number of audio frames processed */
|
|
57
|
+
audioFrames: number;
|
|
58
|
+
/** Estimated progress (0-1) if duration is known */
|
|
59
|
+
progress?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Transcoding result
|
|
63
|
+
*/
|
|
64
|
+
export interface TranscodeResult {
|
|
65
|
+
/** Number of video frames transcoded */
|
|
66
|
+
videoFrames: number;
|
|
67
|
+
/** Number of audio frames transcoded */
|
|
68
|
+
audioFrames: number;
|
|
69
|
+
/** Output file size in bytes */
|
|
70
|
+
outputSize: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Remux a file from one container format to another without re-encoding
|
|
74
|
+
*
|
|
75
|
+
* This is a fast operation that just changes the container format.
|
|
76
|
+
* The video and audio streams are copied without modification.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // Convert MP4 to MKV container (keeping same codecs)
|
|
81
|
+
* await remux('input.mp4', 'output.mkv');
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function remux(inputPath: string, outputPath: string): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Transcode a video file to different codecs/settings
|
|
87
|
+
*
|
|
88
|
+
* Uses node-av internally for efficient end-to-end processing.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* // Convert to H.264 with lower bitrate
|
|
93
|
+
* await transcode('input.mp4', 'output.mp4', {
|
|
94
|
+
* videoCodec: 'h264',
|
|
95
|
+
* videoBitrate: 1_000_000,
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* // Convert to VP9 WebM
|
|
99
|
+
* await transcode('input.mp4', 'output.webm', {
|
|
100
|
+
* videoCodec: 'vp9',
|
|
101
|
+
* videoBitrate: 2_000_000,
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export declare function transcode(inputPath: string, outputPath: string, options?: TranscodeOptions): Promise<TranscodeResult>;
|
|
106
|
+
/**
|
|
107
|
+
* Get media information from a container file
|
|
108
|
+
*/
|
|
109
|
+
export interface MediaInfo {
|
|
110
|
+
format: string;
|
|
111
|
+
duration: number;
|
|
112
|
+
video?: {
|
|
113
|
+
codec: string;
|
|
114
|
+
width: number;
|
|
115
|
+
height: number;
|
|
116
|
+
};
|
|
117
|
+
audio?: {
|
|
118
|
+
codec: string;
|
|
119
|
+
sampleRate: number;
|
|
120
|
+
channels: number;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export declare function getMediaInfo(inputPath: string): Promise<MediaInfo>;
|
|
124
|
+
/**
|
|
125
|
+
* Extract video frames from a container file as VideoFrame objects
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* import { extractVideoFrames } from 'webcodecs-node/containers';
|
|
130
|
+
*
|
|
131
|
+
* for await (const frame of extractVideoFrames('input.mp4')) {
|
|
132
|
+
* console.log(`Frame: ${frame.timestamp}us`);
|
|
133
|
+
* frame.close();
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export { extractVideoFrames } from './extract.js';
|
|
138
|
+
//# sourceMappingURL=transcode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcode.d.ts","sourceRoot":"","sources":["../../src/containers/transcode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,yBAAyB;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AA6GD;;;;;;;;;;;GAWG;AACH,wBAAsB,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAoW1B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA6BxE;AAED;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|