webcodecs-node 0.7.2 → 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.
- package/README.md +94 -12
- package/dist/config/ffmpeg-quality.d.ts +10 -1
- package/dist/config/ffmpeg-quality.d.ts.map +1 -1
- package/dist/config/ffmpeg-quality.js +12 -38
- package/dist/config/ffmpeg-quality.js.map +1 -1
- package/dist/config/webcodecs-config.d.ts +58 -0
- package/dist/config/webcodecs-config.d.ts.map +1 -0
- package/dist/config/webcodecs-config.js +187 -0
- package/dist/config/webcodecs-config.js.map +1 -0
- package/dist/containers/Demuxer.d.ts +3 -1
- package/dist/containers/Demuxer.d.ts.map +1 -1
- package/dist/containers/Demuxer.js +26 -19
- package/dist/containers/Demuxer.js.map +1 -1
- package/dist/containers/FFmpegMuxer.d.ts +42 -0
- package/dist/containers/FFmpegMuxer.d.ts.map +1 -0
- package/dist/containers/FFmpegMuxer.js +311 -0
- package/dist/containers/FFmpegMuxer.js.map +1 -0
- package/dist/containers/FFmpegSpawnMuxer.d.ts +42 -0
- package/dist/containers/FFmpegSpawnMuxer.d.ts.map +1 -0
- package/dist/containers/FFmpegSpawnMuxer.js +311 -0
- package/dist/containers/FFmpegSpawnMuxer.js.map +1 -0
- package/dist/containers/FallbackMuxer.d.ts +42 -0
- package/dist/containers/FallbackMuxer.d.ts.map +1 -0
- package/dist/containers/FallbackMuxer.js +311 -0
- package/dist/containers/FallbackMuxer.js.map +1 -0
- package/dist/containers/Muxer.d.ts +75 -107
- package/dist/containers/Muxer.d.ts.map +1 -1
- package/dist/containers/Muxer.js +184 -243
- package/dist/containers/Muxer.js.map +1 -1
- package/dist/containers/MuxerWithFallback.d.ts +110 -0
- package/dist/containers/MuxerWithFallback.d.ts.map +1 -0
- package/dist/containers/MuxerWithFallback.js +239 -0
- package/dist/containers/MuxerWithFallback.js.map +1 -0
- package/dist/containers/NodeAvMuxer.d.ts +118 -0
- package/dist/containers/NodeAvMuxer.d.ts.map +1 -0
- package/dist/containers/NodeAvMuxer.js +338 -0
- package/dist/containers/NodeAvMuxer.js.map +1 -0
- package/dist/containers/extract.d.ts.map +1 -1
- package/dist/containers/extract.js +3 -1
- package/dist/containers/extract.js.map +1 -1
- package/dist/containers/index.d.ts +20 -14
- package/dist/containers/index.d.ts.map +1 -1
- package/dist/containers/index.js +21 -14
- package/dist/containers/index.js.map +1 -1
- package/dist/containers/muxer-types.d.ts +117 -0
- package/dist/containers/muxer-types.d.ts.map +1 -0
- package/dist/containers/muxer-types.js +45 -0
- package/dist/containers/muxer-types.js.map +1 -0
- package/dist/containers/transcode.d.ts.map +1 -1
- package/dist/containers/transcode.js +171 -150
- package/dist/containers/transcode.js.map +1 -1
- package/dist/core/VideoFrame.d.ts +19 -0
- package/dist/core/VideoFrame.d.ts.map +1 -1
- package/dist/core/VideoFrame.js +11 -0
- package/dist/core/VideoFrame.js.map +1 -1
- package/dist/decoders/VideoDecoder.d.ts +1 -0
- package/dist/decoders/VideoDecoder.d.ts.map +1 -1
- package/dist/decoders/VideoDecoder.js +6 -4
- package/dist/decoders/VideoDecoder.js.map +1 -1
- package/dist/demos/demo-audio-visualizer-mediabunny.d.ts +10 -0
- package/dist/demos/demo-audio-visualizer-mediabunny.d.ts.map +1 -0
- package/dist/demos/demo-audio-visualizer-mediabunny.js +357 -0
- package/dist/demos/demo-audio-visualizer-mediabunny.js.map +1 -0
- package/dist/demos/demo-audio-visualizer-nodeav.d.ts +10 -0
- package/dist/demos/demo-audio-visualizer-nodeav.d.ts.map +1 -0
- package/dist/demos/demo-audio-visualizer-nodeav.js +318 -0
- package/dist/demos/demo-audio-visualizer-nodeav.js.map +1 -0
- package/dist/demos/demo-muxer-fallback.d.ts +8 -0
- package/dist/demos/demo-muxer-fallback.d.ts.map +1 -0
- package/dist/demos/demo-muxer-fallback.js +165 -0
- package/dist/demos/demo-muxer-fallback.js.map +1 -0
- package/dist/encoders/AudioEncoder.d.ts +2 -0
- package/dist/encoders/AudioEncoder.d.ts.map +1 -1
- package/dist/encoders/AudioEncoder.js +7 -4
- package/dist/encoders/AudioEncoder.js.map +1 -1
- package/dist/hardware/decoder-args.d.ts.map +1 -1
- package/dist/hardware/decoder-args.js +35 -14
- package/dist/hardware/decoder-args.js.map +1 -1
- package/dist/hardware/detection.d.ts.map +1 -1
- package/dist/hardware/detection.js +39 -0
- package/dist/hardware/detection.js.map +1 -1
- package/dist/hardware/encoder-args.d.ts.map +1 -1
- package/dist/hardware/encoder-args.js +43 -5
- package/dist/hardware/encoder-args.js.map +1 -1
- package/dist/hardware/types.d.ts.map +1 -1
- package/dist/hardware/types.js +30 -28
- package/dist/hardware/types.js.map +1 -1
- package/dist/node-av/NodeAvVideoEncoder.d.ts +5 -0
- package/dist/node-av/NodeAvVideoEncoder.d.ts.map +1 -1
- package/dist/node-av/NodeAvVideoEncoder.js +76 -23
- package/dist/node-av/NodeAvVideoEncoder.js.map +1 -1
- package/dist/utils/avc.d.ts +2 -0
- package/dist/utils/avc.d.ts.map +1 -1
- package/dist/utils/avc.js +36 -8
- package/dist/utils/avc.js.map +1 -1
- package/dist/utils/codec-validation.d.ts.map +1 -1
- package/dist/utils/codec-validation.js +18 -8
- package/dist/utils/codec-validation.js.map +1 -1
- package/dist/utils/hevc.d.ts +2 -0
- package/dist/utils/hevc.d.ts.map +1 -1
- package/dist/utils/hevc.js +42 -8
- package/dist/utils/hevc.js.map +1 -1
- package/docs/api.md +20 -2
- package/docs/configuration.md +10 -7
- package/package.json +1 -1
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-av Muxer - Fast muxer using node-av's FormatContext API
|
|
3
|
+
*
|
|
4
|
+
* Uses node-av's low-level FormatContext API to provide a WebCodecs-compatible interface
|
|
5
|
+
* that accepts EncodedVideoChunk and EncodedAudioChunk objects. This is the fast path
|
|
6
|
+
* (~5ms muxing time) used by the main Muxer class.
|
|
7
|
+
*/
|
|
8
|
+
import { FormatContext, Packet, Rational, Demuxer as NodeAvDemuxerInternal, Muxer as NodeAvMuxerInternal, 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, AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, } from 'node-av';
|
|
9
|
+
import { withTimeout, DEFAULT_TIMEOUTS } from '../utils/timeout.js';
|
|
10
|
+
import { Logger } from '../utils/logger.js';
|
|
11
|
+
import { inferFormat } from './muxer-types.js';
|
|
12
|
+
const logger = new Logger('NodeAvMuxer');
|
|
13
|
+
/**
|
|
14
|
+
* Maps WebCodecs codec strings to FFmpeg codec IDs
|
|
15
|
+
*/
|
|
16
|
+
function mapVideoCodecId(codec) {
|
|
17
|
+
const codecLower = codec.toLowerCase();
|
|
18
|
+
if (codecLower.startsWith('avc1') || codecLower.startsWith('avc3') || codecLower === 'h264') {
|
|
19
|
+
return AV_CODEC_ID_H264;
|
|
20
|
+
}
|
|
21
|
+
else if (codecLower.startsWith('hvc1') || codecLower.startsWith('hev1') || codecLower === 'hevc') {
|
|
22
|
+
return AV_CODEC_ID_HEVC;
|
|
23
|
+
}
|
|
24
|
+
else if (codecLower === 'vp8') {
|
|
25
|
+
return AV_CODEC_ID_VP8;
|
|
26
|
+
}
|
|
27
|
+
else if (codecLower.startsWith('vp09') || codecLower === 'vp9') {
|
|
28
|
+
return AV_CODEC_ID_VP9;
|
|
29
|
+
}
|
|
30
|
+
else if (codecLower.startsWith('av01') || codecLower === 'av1') {
|
|
31
|
+
return AV_CODEC_ID_AV1;
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Unsupported video codec: ${codec}`);
|
|
34
|
+
}
|
|
35
|
+
function mapAudioCodecId(codec) {
|
|
36
|
+
const codecLower = codec.toLowerCase();
|
|
37
|
+
if (codecLower.startsWith('mp4a') || codecLower === 'aac') {
|
|
38
|
+
return AV_CODEC_ID_AAC;
|
|
39
|
+
}
|
|
40
|
+
else if (codecLower === 'mp3') {
|
|
41
|
+
return AV_CODEC_ID_MP3;
|
|
42
|
+
}
|
|
43
|
+
else if (codecLower === 'opus') {
|
|
44
|
+
return AV_CODEC_ID_OPUS;
|
|
45
|
+
}
|
|
46
|
+
else if (codecLower === 'vorbis') {
|
|
47
|
+
return AV_CODEC_ID_VORBIS;
|
|
48
|
+
}
|
|
49
|
+
else if (codecLower === 'flac') {
|
|
50
|
+
return AV_CODEC_ID_FLAC;
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Unsupported audio codec: ${codec}`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Node-av based muxer that accepts WebCodecs-compatible chunks
|
|
56
|
+
*
|
|
57
|
+
* Uses node-av's low-level FormatContext API for direct packet writing.
|
|
58
|
+
* This is the fast implementation (~5ms) used internally by the main Muxer class.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const muxer = new NodeAvMuxer({ path: 'output.mp4' });
|
|
63
|
+
* await muxer.open();
|
|
64
|
+
* await muxer.addVideoTrack({
|
|
65
|
+
* codec: 'avc1.42001E',
|
|
66
|
+
* codedWidth: 640,
|
|
67
|
+
* codedHeight: 480,
|
|
68
|
+
* framerate: 30,
|
|
69
|
+
* description: spsNaluBuffer, // Optional: H.264 SPS/PPS
|
|
70
|
+
* });
|
|
71
|
+
*
|
|
72
|
+
* // Write encoded chunks from VideoEncoder
|
|
73
|
+
* await muxer.writeVideoChunk(chunk);
|
|
74
|
+
*
|
|
75
|
+
* await muxer.close();
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export class NodeAvMuxer {
|
|
79
|
+
formatContext = null;
|
|
80
|
+
config;
|
|
81
|
+
_videoStreamIndex = -1;
|
|
82
|
+
_audioStreamIndex = -1;
|
|
83
|
+
_videoConfig = null;
|
|
84
|
+
_audioConfig = null;
|
|
85
|
+
_videoChunkCount = 0;
|
|
86
|
+
_audioChunkCount = 0;
|
|
87
|
+
_headerWritten = false;
|
|
88
|
+
constructor(config) {
|
|
89
|
+
this.config = config;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Open the muxer for writing
|
|
93
|
+
*
|
|
94
|
+
* @param timeout - Operation timeout in milliseconds (default: 15000)
|
|
95
|
+
*/
|
|
96
|
+
async open(timeout = DEFAULT_TIMEOUTS.open) {
|
|
97
|
+
const format = this.config.format || inferFormat(this.config.path);
|
|
98
|
+
// Create and configure FormatContext
|
|
99
|
+
this.formatContext = new FormatContext();
|
|
100
|
+
this.formatContext.allocOutputContext2(null, format, this.config.path);
|
|
101
|
+
// Open output file
|
|
102
|
+
await withTimeout(this.formatContext.openOutput(this.config.path), timeout, `Muxer open (${this.config.path})`);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Add a video track to the output
|
|
106
|
+
*
|
|
107
|
+
* @param config - Video track configuration
|
|
108
|
+
* @returns Stream index for the video track
|
|
109
|
+
*/
|
|
110
|
+
async addVideoTrack(config) {
|
|
111
|
+
if (!this.formatContext) {
|
|
112
|
+
throw new Error('Muxer not opened');
|
|
113
|
+
}
|
|
114
|
+
this._videoConfig = config;
|
|
115
|
+
const codecId = mapVideoCodecId(config.codec);
|
|
116
|
+
// Create a new stream
|
|
117
|
+
const stream = this.formatContext.newStream(null);
|
|
118
|
+
this._videoStreamIndex = stream.index;
|
|
119
|
+
// Set codec parameters on the stream
|
|
120
|
+
const cp = stream.codecpar;
|
|
121
|
+
cp.codecType = AVMEDIA_TYPE_VIDEO;
|
|
122
|
+
cp.codecId = codecId;
|
|
123
|
+
cp.width = config.codedWidth;
|
|
124
|
+
cp.height = config.codedHeight;
|
|
125
|
+
cp.bitRate = BigInt(config.bitrate || 1_000_000);
|
|
126
|
+
cp.format = 0; // YUV420P
|
|
127
|
+
// Set extradata if description is provided (SPS/PPS for H.264, etc.)
|
|
128
|
+
if (config.description && config.description.length > 0) {
|
|
129
|
+
cp.extradata = Buffer.from(config.description);
|
|
130
|
+
}
|
|
131
|
+
// Set stream time base to microseconds (WebCodecs uses microseconds)
|
|
132
|
+
stream.timeBase = new Rational(1, 1_000_000);
|
|
133
|
+
return this._videoStreamIndex;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Add an audio track to the output
|
|
137
|
+
*
|
|
138
|
+
* @param config - Audio track configuration
|
|
139
|
+
* @returns Stream index for the audio track
|
|
140
|
+
*/
|
|
141
|
+
async addAudioTrack(config) {
|
|
142
|
+
if (!this.formatContext) {
|
|
143
|
+
throw new Error('Muxer not opened');
|
|
144
|
+
}
|
|
145
|
+
this._audioConfig = config;
|
|
146
|
+
const codecId = mapAudioCodecId(config.codec);
|
|
147
|
+
// Create a new stream
|
|
148
|
+
const stream = this.formatContext.newStream(null);
|
|
149
|
+
this._audioStreamIndex = stream.index;
|
|
150
|
+
// Set codec parameters on the stream
|
|
151
|
+
const cp = stream.codecpar;
|
|
152
|
+
cp.codecType = AVMEDIA_TYPE_AUDIO;
|
|
153
|
+
cp.codecId = codecId;
|
|
154
|
+
cp.sampleRate = config.sampleRate;
|
|
155
|
+
cp.channels = config.numberOfChannels;
|
|
156
|
+
cp.bitRate = BigInt(config.bitrate || 128_000);
|
|
157
|
+
// Set extradata if description is provided (AudioSpecificConfig for AAC, etc.)
|
|
158
|
+
if (config.description && config.description.length > 0) {
|
|
159
|
+
cp.extradata = Buffer.from(config.description);
|
|
160
|
+
}
|
|
161
|
+
// Set stream time base to microseconds (WebCodecs uses microseconds)
|
|
162
|
+
stream.timeBase = new Rational(1, 1_000_000);
|
|
163
|
+
return this._audioStreamIndex;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Write header if not already written
|
|
167
|
+
*/
|
|
168
|
+
writeHeaderIfNeeded() {
|
|
169
|
+
if (!this._headerWritten && this.formatContext) {
|
|
170
|
+
const ret = this.formatContext.writeHeaderSync();
|
|
171
|
+
if (ret < 0) {
|
|
172
|
+
throw new Error(`Failed to write header: ${ret}`);
|
|
173
|
+
}
|
|
174
|
+
this._headerWritten = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Write an encoded video chunk to the output container
|
|
179
|
+
*
|
|
180
|
+
* @param chunk - EncodedVideoChunk from VideoEncoder
|
|
181
|
+
*/
|
|
182
|
+
async writeVideoChunk(chunk) {
|
|
183
|
+
if (!this.formatContext || this._videoStreamIndex < 0) {
|
|
184
|
+
throw new Error('Video track not configured. Call addVideoTrack() first.');
|
|
185
|
+
}
|
|
186
|
+
// Write header on first chunk
|
|
187
|
+
this.writeHeaderIfNeeded();
|
|
188
|
+
// Get the output stream's actual time base (may differ from what we set)
|
|
189
|
+
const stream = this.formatContext.streams[this._videoStreamIndex];
|
|
190
|
+
const streamTimeBase = stream.timeBase;
|
|
191
|
+
// Create a proper node-av Packet from the chunk data
|
|
192
|
+
const packet = new Packet();
|
|
193
|
+
packet.alloc();
|
|
194
|
+
packet.data = Buffer.from(chunk._buffer);
|
|
195
|
+
// Convert timestamps from microseconds to stream timebase
|
|
196
|
+
const usToStreamTs = (us) => {
|
|
197
|
+
// ts_out = ts_in * (timebase_in / timebase_out)
|
|
198
|
+
// ts_out = us * (1/1000000) / (streamTimeBase.num / streamTimeBase.den)
|
|
199
|
+
// ts_out = us * streamTimeBase.den / (1000000 * streamTimeBase.num)
|
|
200
|
+
return BigInt(Math.round(us * streamTimeBase.den / (1_000_000 * streamTimeBase.num)));
|
|
201
|
+
};
|
|
202
|
+
packet.pts = usToStreamTs(chunk.timestamp);
|
|
203
|
+
packet.dts = usToStreamTs(chunk.timestamp);
|
|
204
|
+
if (chunk.duration) {
|
|
205
|
+
packet.duration = usToStreamTs(chunk.duration);
|
|
206
|
+
}
|
|
207
|
+
packet.streamIndex = this._videoStreamIndex;
|
|
208
|
+
packet.isKeyframe = chunk.type === 'key';
|
|
209
|
+
packet.timeBase = streamTimeBase;
|
|
210
|
+
const ret = this.formatContext.interleavedWriteFrameSync(packet);
|
|
211
|
+
packet.free();
|
|
212
|
+
if (ret < 0) {
|
|
213
|
+
throw new Error(`Failed to write video packet: ${ret}`);
|
|
214
|
+
}
|
|
215
|
+
this._videoChunkCount++;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Write an encoded audio chunk to the output container
|
|
219
|
+
*
|
|
220
|
+
* @param chunk - EncodedAudioChunk from AudioEncoder
|
|
221
|
+
*/
|
|
222
|
+
async writeAudioChunk(chunk) {
|
|
223
|
+
if (!this.formatContext || this._audioStreamIndex < 0 || !this._audioConfig) {
|
|
224
|
+
throw new Error('Audio track not configured. Call addAudioTrack() first.');
|
|
225
|
+
}
|
|
226
|
+
// Write header on first chunk
|
|
227
|
+
this.writeHeaderIfNeeded();
|
|
228
|
+
// Get the output stream's actual time base (may differ from what we set)
|
|
229
|
+
const stream = this.formatContext.streams[this._audioStreamIndex];
|
|
230
|
+
const streamTimeBase = stream.timeBase;
|
|
231
|
+
// Create a proper node-av Packet from the chunk data
|
|
232
|
+
const packet = new Packet();
|
|
233
|
+
packet.alloc();
|
|
234
|
+
packet.data = Buffer.from(chunk._rawData);
|
|
235
|
+
// Convert timestamps from microseconds to stream timebase
|
|
236
|
+
// For audio, the stream timebase is typically 1/sampleRate
|
|
237
|
+
const usToStreamTs = (us) => {
|
|
238
|
+
// ts_out = ts_in * (timebase_in / timebase_out)
|
|
239
|
+
// ts_out = us * (1/1000000) / (streamTimeBase.num / streamTimeBase.den)
|
|
240
|
+
// ts_out = us * streamTimeBase.den / (1000000 * streamTimeBase.num)
|
|
241
|
+
return BigInt(Math.round(us * streamTimeBase.den / (1_000_000 * streamTimeBase.num)));
|
|
242
|
+
};
|
|
243
|
+
packet.pts = usToStreamTs(chunk.timestamp);
|
|
244
|
+
packet.dts = usToStreamTs(chunk.timestamp);
|
|
245
|
+
if (chunk.duration) {
|
|
246
|
+
packet.duration = usToStreamTs(chunk.duration);
|
|
247
|
+
}
|
|
248
|
+
packet.streamIndex = this._audioStreamIndex;
|
|
249
|
+
packet.isKeyframe = chunk.type === 'key';
|
|
250
|
+
packet.timeBase = streamTimeBase;
|
|
251
|
+
const ret = this.formatContext.interleavedWriteFrameSync(packet);
|
|
252
|
+
packet.free();
|
|
253
|
+
if (ret < 0) {
|
|
254
|
+
throw new Error(`Failed to write audio packet: ${ret}`);
|
|
255
|
+
}
|
|
256
|
+
this._audioChunkCount++;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Finalize and close the muxer
|
|
260
|
+
*
|
|
261
|
+
* @param timeout - Operation timeout in milliseconds (default: 10000)
|
|
262
|
+
*/
|
|
263
|
+
async close(timeout = DEFAULT_TIMEOUTS.close) {
|
|
264
|
+
if (this.formatContext) {
|
|
265
|
+
// Write trailer
|
|
266
|
+
if (this._headerWritten) {
|
|
267
|
+
const ret = this.formatContext.writeTrailerSync();
|
|
268
|
+
if (ret < 0) {
|
|
269
|
+
logger.warn(`writeTrailer returned error code ${ret}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Close output and free context
|
|
273
|
+
await withTimeout(this.formatContext.closeOutput(), timeout, 'Muxer close output');
|
|
274
|
+
this.formatContext.freeContext();
|
|
275
|
+
this.formatContext = null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get the underlying FormatContext (for advanced use)
|
|
280
|
+
*/
|
|
281
|
+
get native() {
|
|
282
|
+
return this.formatContext;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Get number of video chunks written
|
|
286
|
+
*/
|
|
287
|
+
get videoChunkCount() {
|
|
288
|
+
return this._videoChunkCount;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Get number of audio chunks written
|
|
292
|
+
*/
|
|
293
|
+
get audioChunkCount() {
|
|
294
|
+
return this._audioChunkCount;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Helper class for stream copy (remux) operations
|
|
299
|
+
* This copies encoded data from one container to another without re-encoding
|
|
300
|
+
*/
|
|
301
|
+
export class StreamCopier {
|
|
302
|
+
srcDemuxer = null;
|
|
303
|
+
dstMuxer = null;
|
|
304
|
+
/**
|
|
305
|
+
* Remux a file from one container format to another
|
|
306
|
+
* This performs a stream copy without re-encoding
|
|
307
|
+
*/
|
|
308
|
+
static async remux(inputPath, outputPath, options) {
|
|
309
|
+
const demuxer = await NodeAvDemuxerInternal.open(inputPath);
|
|
310
|
+
const format = options?.format || inferFormat(outputPath);
|
|
311
|
+
const muxer = await NodeAvMuxerInternal.open(outputPath, { format });
|
|
312
|
+
const streamMap = new Map();
|
|
313
|
+
// Copy video stream
|
|
314
|
+
const videoStream = demuxer.video();
|
|
315
|
+
if (videoStream) {
|
|
316
|
+
const outIndex = muxer.addStream(videoStream);
|
|
317
|
+
streamMap.set(videoStream.index, outIndex);
|
|
318
|
+
}
|
|
319
|
+
// Copy audio stream
|
|
320
|
+
const audioStream = demuxer.audio();
|
|
321
|
+
if (audioStream) {
|
|
322
|
+
const outIndex = muxer.addStream(audioStream);
|
|
323
|
+
streamMap.set(audioStream.index, outIndex);
|
|
324
|
+
}
|
|
325
|
+
// Copy packets
|
|
326
|
+
for await (const packet of demuxer.packets()) {
|
|
327
|
+
if (!packet)
|
|
328
|
+
continue;
|
|
329
|
+
const outIndex = streamMap.get(packet.streamIndex);
|
|
330
|
+
if (outIndex !== undefined) {
|
|
331
|
+
await muxer.writePacket(packet, outIndex);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
await demuxer.close();
|
|
335
|
+
await muxer.close();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=NodeAvMuxer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeAvMuxer.js","sourceRoot":"","sources":["../../src/containers/NodeAvMuxer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +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;
|
|
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;AAKnD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAuB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CA8CvF"}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Demuxer } from './Demuxer.js';
|
|
7
7
|
import { VideoDecoder } from '../decoders/VideoDecoder.js';
|
|
8
|
+
import { Logger } from '../utils/logger.js';
|
|
9
|
+
const logger = new Logger('Extract');
|
|
8
10
|
/**
|
|
9
11
|
* Extract video frames from a container file as VideoFrame objects
|
|
10
12
|
*
|
|
@@ -36,7 +38,7 @@ export async function* extractVideoFrames(inputPath) {
|
|
|
36
38
|
output: (frame) => {
|
|
37
39
|
frames.push(frame);
|
|
38
40
|
},
|
|
39
|
-
error: (err) =>
|
|
41
|
+
error: (err) => logger.error('Decode error:', err),
|
|
40
42
|
});
|
|
41
43
|
decoder.configure({
|
|
42
44
|
codec: videoConfig.codec,
|
|
@@ -1 +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;
|
|
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;AAE3D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;AAErC;;;;;;;;;;;;;;;;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,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC;KACnD,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"}
|
|
@@ -6,11 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```typescript
|
|
9
|
-
* import { Demuxer,
|
|
10
|
-
*
|
|
11
|
-
* // Get media info
|
|
12
|
-
* const info = await getMediaInfo('video.mp4');
|
|
13
|
-
* console.log(info.video.codec, info.video.width, info.video.height);
|
|
9
|
+
* import { Demuxer, Muxer, muxChunks } from 'webcodecs-node/containers';
|
|
14
10
|
*
|
|
15
11
|
* // Demux video chunks for WebCodecs processing
|
|
16
12
|
* const demuxer = new Demuxer({ path: 'video.mp4' });
|
|
@@ -20,20 +16,30 @@
|
|
|
20
16
|
* }
|
|
21
17
|
* await demuxer.close();
|
|
22
18
|
*
|
|
23
|
-
* //
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
19
|
+
* // Mux encoded chunks to a file (with automatic fallback)
|
|
20
|
+
* const muxer = new Muxer({ path: 'output.mp4' });
|
|
21
|
+
* await muxer.open();
|
|
22
|
+
* await muxer.addVideoTrack({ codec: 'avc1.64001E', ... });
|
|
23
|
+
* // ... write chunks
|
|
24
|
+
* const result = await muxer.closeWithResult();
|
|
25
|
+
* console.log(`Used ${result.backend} in ${result.durationMs}ms`);
|
|
28
26
|
*
|
|
29
|
-
* //
|
|
30
|
-
* await
|
|
27
|
+
* // Or use the convenience function
|
|
28
|
+
* const result = await muxChunks({
|
|
29
|
+
* path: 'output.mp4',
|
|
30
|
+
* video: { config, chunks },
|
|
31
|
+
* audio: { config, chunks },
|
|
32
|
+
* });
|
|
31
33
|
* ```
|
|
32
34
|
*/
|
|
33
35
|
export { Demuxer } from './Demuxer.js';
|
|
34
36
|
export type { DemuxerConfig, VideoStreamConfig, AudioStreamConfig, VideoChunkCallback, AudioChunkCallback, } from './Demuxer.js';
|
|
35
|
-
export {
|
|
36
|
-
export
|
|
37
|
+
export type { IMuxer, MuxerConfig, VideoTrackConfig, AudioTrackConfig, MuxResult, } from './muxer-types.js';
|
|
38
|
+
export { MuxerError, inferFormat } from './muxer-types.js';
|
|
39
|
+
export { Muxer, muxChunks } from './Muxer.js';
|
|
40
|
+
export type { MuxerOptions } from './Muxer.js';
|
|
41
|
+
export { NodeAvMuxer, StreamCopier } from './NodeAvMuxer.js';
|
|
42
|
+
export { FFmpegMuxer } from './FFmpegMuxer.js';
|
|
37
43
|
export { remux, transcode, getMediaInfo } from './transcode.js';
|
|
38
44
|
export type { TranscodeOptions, TranscodeProgress, TranscodeResult, MediaInfo, VideoCodec, AudioCodec, HardwareAcceleration, } from './transcode.js';
|
|
39
45
|
export { extractVideoFrames } from './extract.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/containers/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/containers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;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,YAAY,EACV,MAAM,EACN,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG3D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,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"}
|
package/dist/containers/index.js
CHANGED
|
@@ -6,11 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```typescript
|
|
9
|
-
* import { Demuxer,
|
|
10
|
-
*
|
|
11
|
-
* // Get media info
|
|
12
|
-
* const info = await getMediaInfo('video.mp4');
|
|
13
|
-
* console.log(info.video.codec, info.video.width, info.video.height);
|
|
9
|
+
* import { Demuxer, Muxer, muxChunks } from 'webcodecs-node/containers';
|
|
14
10
|
*
|
|
15
11
|
* // Demux video chunks for WebCodecs processing
|
|
16
12
|
* const demuxer = new Demuxer({ path: 'video.mp4' });
|
|
@@ -20,20 +16,31 @@
|
|
|
20
16
|
* }
|
|
21
17
|
* await demuxer.close();
|
|
22
18
|
*
|
|
23
|
-
* //
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
19
|
+
* // Mux encoded chunks to a file (with automatic fallback)
|
|
20
|
+
* const muxer = new Muxer({ path: 'output.mp4' });
|
|
21
|
+
* await muxer.open();
|
|
22
|
+
* await muxer.addVideoTrack({ codec: 'avc1.64001E', ... });
|
|
23
|
+
* // ... write chunks
|
|
24
|
+
* const result = await muxer.closeWithResult();
|
|
25
|
+
* console.log(`Used ${result.backend} in ${result.durationMs}ms`);
|
|
28
26
|
*
|
|
29
|
-
* //
|
|
30
|
-
* await
|
|
27
|
+
* // Or use the convenience function
|
|
28
|
+
* const result = await muxChunks({
|
|
29
|
+
* path: 'output.mp4',
|
|
30
|
+
* video: { config, chunks },
|
|
31
|
+
* audio: { config, chunks },
|
|
32
|
+
* });
|
|
31
33
|
* ```
|
|
32
34
|
*/
|
|
33
35
|
// Demuxer
|
|
34
36
|
export { Demuxer } from './Demuxer.js';
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
export { MuxerError, inferFormat } from './muxer-types.js';
|
|
38
|
+
// Main Muxer (with automatic fallback - recommended)
|
|
39
|
+
export { Muxer, muxChunks } from './Muxer.js';
|
|
40
|
+
// Node-av Muxer (fast, direct implementation)
|
|
41
|
+
export { NodeAvMuxer, StreamCopier } from './NodeAvMuxer.js';
|
|
42
|
+
// FFmpeg Muxer (subprocess-based, more compatible)
|
|
43
|
+
export { FFmpegMuxer } from './FFmpegMuxer.js';
|
|
37
44
|
// Transcoding utilities
|
|
38
45
|
export { remux, transcode, getMediaInfo } from './transcode.js';
|
|
39
46
|
// Frame extraction
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/containers/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/containers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAiBvC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE3D,qDAAqD;AACrD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9C,8CAA8C;AAC9C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7D,mDAAmD;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types and interfaces for muxers
|
|
3
|
+
*
|
|
4
|
+
* This module defines common interfaces that both NodeAvMuxer and FFmpegSpawnMuxer
|
|
5
|
+
* implement, enabling a clean fallback mechanism.
|
|
6
|
+
*/
|
|
7
|
+
import type { EncodedVideoChunk } from '../core/EncodedVideoChunk.js';
|
|
8
|
+
import type { EncodedAudioChunk } from '../core/EncodedAudioChunk.js';
|
|
9
|
+
/**
|
|
10
|
+
* Video track configuration for muxing
|
|
11
|
+
*/
|
|
12
|
+
export interface VideoTrackConfig {
|
|
13
|
+
/** WebCodecs codec string (e.g., 'avc1.64001E', 'hvc1.1.6.L93.B0') */
|
|
14
|
+
codec: string;
|
|
15
|
+
/** Video width in pixels */
|
|
16
|
+
codedWidth: number;
|
|
17
|
+
/** Video height in pixels */
|
|
18
|
+
codedHeight: number;
|
|
19
|
+
/** Frame rate (optional, used for timing) */
|
|
20
|
+
framerate?: number;
|
|
21
|
+
/** Target bitrate in bits/second (optional, for container hints) */
|
|
22
|
+
bitrate?: number;
|
|
23
|
+
/** Codec-specific description (SPS/PPS for H.264, etc.) */
|
|
24
|
+
description?: Uint8Array;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Audio track configuration for muxing
|
|
28
|
+
*/
|
|
29
|
+
export interface AudioTrackConfig {
|
|
30
|
+
/** WebCodecs codec string (e.g., 'mp4a.40.2', 'opus') */
|
|
31
|
+
codec: string;
|
|
32
|
+
/** Sample rate in Hz */
|
|
33
|
+
sampleRate: number;
|
|
34
|
+
/** Number of audio channels */
|
|
35
|
+
numberOfChannels: number;
|
|
36
|
+
/** Target bitrate in bits/second (optional) */
|
|
37
|
+
bitrate?: number;
|
|
38
|
+
/** Codec-specific description (AudioSpecificConfig for AAC, etc.) */
|
|
39
|
+
description?: Uint8Array;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Muxer configuration
|
|
43
|
+
*/
|
|
44
|
+
export interface MuxerConfig {
|
|
45
|
+
/** Path to the output file */
|
|
46
|
+
path: string;
|
|
47
|
+
/** Container format (mp4, webm, mkv) - inferred from extension if not specified */
|
|
48
|
+
format?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Result of a muxing operation
|
|
52
|
+
*/
|
|
53
|
+
export interface MuxResult {
|
|
54
|
+
/** Path to the output file */
|
|
55
|
+
path: string;
|
|
56
|
+
/** Number of video chunks written */
|
|
57
|
+
videoChunkCount: number;
|
|
58
|
+
/** Number of audio chunks written */
|
|
59
|
+
audioChunkCount: number;
|
|
60
|
+
/** Time taken for muxing in milliseconds */
|
|
61
|
+
durationMs: number;
|
|
62
|
+
/** Which muxer backend was used */
|
|
63
|
+
backend: 'node-av' | 'ffmpeg-spawn';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Common interface for all muxer implementations
|
|
67
|
+
*/
|
|
68
|
+
export interface IMuxer {
|
|
69
|
+
/**
|
|
70
|
+
* Open the muxer for writing
|
|
71
|
+
*/
|
|
72
|
+
open(timeout?: number): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Add a video track to the output
|
|
75
|
+
* @returns Stream index for the video track
|
|
76
|
+
*/
|
|
77
|
+
addVideoTrack(config: VideoTrackConfig): Promise<number>;
|
|
78
|
+
/**
|
|
79
|
+
* Add an audio track to the output
|
|
80
|
+
* @returns Stream index for the audio track
|
|
81
|
+
*/
|
|
82
|
+
addAudioTrack(config: AudioTrackConfig): Promise<number>;
|
|
83
|
+
/**
|
|
84
|
+
* Write an encoded video chunk
|
|
85
|
+
*/
|
|
86
|
+
writeVideoChunk(chunk: EncodedVideoChunk): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Write an encoded audio chunk
|
|
89
|
+
*/
|
|
90
|
+
writeAudioChunk(chunk: EncodedAudioChunk): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Finalize and close the muxer
|
|
93
|
+
*/
|
|
94
|
+
close(timeout?: number): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Get number of video chunks written
|
|
97
|
+
*/
|
|
98
|
+
readonly videoChunkCount: number;
|
|
99
|
+
/**
|
|
100
|
+
* Get number of audio chunks written
|
|
101
|
+
*/
|
|
102
|
+
readonly audioChunkCount: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Muxer error with additional context
|
|
106
|
+
*/
|
|
107
|
+
export declare class MuxerError extends Error {
|
|
108
|
+
readonly backend: 'node-av' | 'ffmpeg-spawn';
|
|
109
|
+
readonly operation: 'open' | 'addTrack' | 'write' | 'close';
|
|
110
|
+
readonly cause?: Error | undefined;
|
|
111
|
+
constructor(message: string, backend: 'node-av' | 'ffmpeg-spawn', operation: 'open' | 'addTrack' | 'write' | 'close', cause?: Error | undefined);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Infer container format from file extension
|
|
115
|
+
*/
|
|
116
|
+
export declare function inferFormat(path: string): string;
|
|
117
|
+
//# sourceMappingURL=muxer-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"muxer-types.d.ts","sourceRoot":"","sources":["../../src/containers/muxer-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,OAAO,EAAE,SAAS,GAAG,cAAc,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzD;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzD;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,KAAK;aAGjB,OAAO,EAAE,SAAS,GAAG,cAAc;aACnC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO;aAClD,KAAK,CAAC,EAAE,KAAK;gBAH7B,OAAO,EAAE,MAAM,EACC,OAAO,EAAE,SAAS,GAAG,cAAc,EACnC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,EAClD,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBhD"}
|