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.
- 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 +12 -6
- 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 +52 -2
- package/docs/configuration.md +10 -7
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo: Audio Visualizer (node-av Muxer version)
|
|
3
|
+
*
|
|
4
|
+
* Same as demo-audio-visualizer.ts but uses node-av Muxer directly
|
|
5
|
+
* instead of spawning FFmpeg for muxing. This should be faster.
|
|
6
|
+
*
|
|
7
|
+
* Outputs both video and audio encoded in-process, then muxes them together.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=demo-audio-visualizer-nodeav.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-audio-visualizer-nodeav.d.ts","sourceRoot":"","sources":["../../src/demos/demo-audio-visualizer-nodeav.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo: Audio Visualizer (node-av Muxer version)
|
|
3
|
+
*
|
|
4
|
+
* Same as demo-audio-visualizer.ts but uses node-av Muxer directly
|
|
5
|
+
* instead of spawning FFmpeg for muxing. This should be faster.
|
|
6
|
+
*
|
|
7
|
+
* Outputs both video and audio encoded in-process, then muxes them together.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { createCanvas, getRawPixels } from '../canvas/index.js';
|
|
12
|
+
import { VideoEncoder } from '../encoders/VideoEncoder.js';
|
|
13
|
+
import { AudioEncoder } from '../encoders/AudioEncoder.js';
|
|
14
|
+
import { VideoFrame } from '../core/VideoFrame.js';
|
|
15
|
+
import { AudioData } from '../core/AudioData.js';
|
|
16
|
+
import { NodeAvMuxer } from '../containers/NodeAvMuxer.js';
|
|
17
|
+
const WIDTH = 800;
|
|
18
|
+
const HEIGHT = 600;
|
|
19
|
+
const DURATION_SECONDS = 10;
|
|
20
|
+
const FRAME_RATE = 30;
|
|
21
|
+
const SAMPLE_RATE = 48000;
|
|
22
|
+
const AUDIO_CHANNELS = 2;
|
|
23
|
+
const FRAME_COUNT = DURATION_SECONDS * FRAME_RATE;
|
|
24
|
+
const FRAME_DURATION_US = Math.round(1_000_000 / FRAME_RATE);
|
|
25
|
+
const SAMPLES_PER_FRAME = Math.round(SAMPLE_RATE / FRAME_RATE);
|
|
26
|
+
const OUTPUT_DIR = path.resolve('media', 'visualizer-demo');
|
|
27
|
+
const OUTPUT_VIDEO = path.join(OUTPUT_DIR, 'visualizer-nodeav.mp4');
|
|
28
|
+
// Musical frequencies (A minor pentatonic scale)
|
|
29
|
+
const FREQUENCIES = [220, 261.63, 329.63, 392, 440, 523.25, 659.25, 783.99];
|
|
30
|
+
// Visualization colors
|
|
31
|
+
const COLORS = {
|
|
32
|
+
background: '#1a1a2e',
|
|
33
|
+
waveform: '#00ff88',
|
|
34
|
+
bars: ['#ff0080', '#ff4080', '#ff8080', '#ffaa00', '#ffff00', '#80ff00', '#00ff80', '#00ffff'],
|
|
35
|
+
text: '#ffffff',
|
|
36
|
+
grid: '#333355',
|
|
37
|
+
};
|
|
38
|
+
function generateAudioSamples(state, numSamples, sampleRate, startSample) {
|
|
39
|
+
const samples = new Float32Array(numSamples * AUDIO_CHANNELS);
|
|
40
|
+
for (let i = 0; i < numSamples; i++) {
|
|
41
|
+
const t = (startSample + i) / sampleRate;
|
|
42
|
+
let sample = 0;
|
|
43
|
+
// Mix multiple frequencies with their amplitudes
|
|
44
|
+
for (let f = 0; f < state.frequencies.length; f++) {
|
|
45
|
+
const freq = state.frequencies[f];
|
|
46
|
+
const amp = state.amplitudes[f];
|
|
47
|
+
const phase = state.phases[f];
|
|
48
|
+
sample += Math.sin(2 * Math.PI * freq * t + phase) * amp;
|
|
49
|
+
}
|
|
50
|
+
// Normalize
|
|
51
|
+
sample = sample / state.frequencies.length * 0.7;
|
|
52
|
+
// Stereo (same for both channels)
|
|
53
|
+
samples[i * AUDIO_CHANNELS] = sample;
|
|
54
|
+
samples[i * AUDIO_CHANNELS + 1] = sample;
|
|
55
|
+
}
|
|
56
|
+
return samples;
|
|
57
|
+
}
|
|
58
|
+
function drawWaveform(ctx, samples, x, y, width, height) {
|
|
59
|
+
const step = Math.ceil(samples.length / AUDIO_CHANNELS / width);
|
|
60
|
+
const centerY = y + height / 2;
|
|
61
|
+
ctx.beginPath();
|
|
62
|
+
ctx.strokeStyle = COLORS.waveform;
|
|
63
|
+
ctx.lineWidth = 2;
|
|
64
|
+
for (let i = 0; i < width; i++) {
|
|
65
|
+
const sampleIndex = Math.min(i * step, samples.length / AUDIO_CHANNELS - 1);
|
|
66
|
+
const sample = samples[sampleIndex * AUDIO_CHANNELS];
|
|
67
|
+
const py = centerY - sample * (height / 2) * 0.9;
|
|
68
|
+
if (i === 0) {
|
|
69
|
+
ctx.moveTo(x + i, py);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
ctx.lineTo(x + i, py);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
ctx.stroke();
|
|
76
|
+
}
|
|
77
|
+
function drawSpectrumBars(ctx, amplitudes, x, y, width, height, time) {
|
|
78
|
+
const numBars = amplitudes.length;
|
|
79
|
+
const barWidth = (width / numBars) * 0.8;
|
|
80
|
+
const gap = (width / numBars) * 0.2;
|
|
81
|
+
for (let i = 0; i < numBars; i++) {
|
|
82
|
+
// Add some animation to the bars
|
|
83
|
+
const animatedAmp = amplitudes[i] * (0.8 + 0.2 * Math.sin(time * 5 + i));
|
|
84
|
+
const barHeight = animatedAmp * height * 0.9;
|
|
85
|
+
const bx = x + i * (barWidth + gap) + gap / 2;
|
|
86
|
+
const by = y + height - barHeight;
|
|
87
|
+
// Gradient effect
|
|
88
|
+
const gradient = ctx.createLinearGradient(bx, by, bx, y + height);
|
|
89
|
+
gradient.addColorStop(0, COLORS.bars[i % COLORS.bars.length]);
|
|
90
|
+
gradient.addColorStop(1, '#000033');
|
|
91
|
+
ctx.fillStyle = gradient;
|
|
92
|
+
// Rounded rectangle
|
|
93
|
+
const radius = barWidth / 4;
|
|
94
|
+
ctx.beginPath();
|
|
95
|
+
ctx.moveTo(bx + radius, by);
|
|
96
|
+
ctx.lineTo(bx + barWidth - radius, by);
|
|
97
|
+
ctx.quadraticCurveTo(bx + barWidth, by, bx + barWidth, by + radius);
|
|
98
|
+
ctx.lineTo(bx + barWidth, y + height);
|
|
99
|
+
ctx.lineTo(bx, y + height);
|
|
100
|
+
ctx.lineTo(bx, by + radius);
|
|
101
|
+
ctx.quadraticCurveTo(bx, by, bx + radius, by);
|
|
102
|
+
ctx.fill();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function drawGrid(ctx, width, height) {
|
|
106
|
+
ctx.strokeStyle = COLORS.grid;
|
|
107
|
+
ctx.lineWidth = 1;
|
|
108
|
+
// Horizontal lines
|
|
109
|
+
for (let y = 0; y < height; y += 50) {
|
|
110
|
+
ctx.beginPath();
|
|
111
|
+
ctx.moveTo(0, y);
|
|
112
|
+
ctx.lineTo(width, y);
|
|
113
|
+
ctx.stroke();
|
|
114
|
+
}
|
|
115
|
+
// Vertical lines
|
|
116
|
+
for (let x = 0; x < width; x += 50) {
|
|
117
|
+
ctx.beginPath();
|
|
118
|
+
ctx.moveTo(x, 0);
|
|
119
|
+
ctx.lineTo(x, height);
|
|
120
|
+
ctx.stroke();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function drawLabels(ctx, frequencies, time) {
|
|
124
|
+
ctx.fillStyle = COLORS.text;
|
|
125
|
+
ctx.font = '16px monospace';
|
|
126
|
+
ctx.textAlign = 'left';
|
|
127
|
+
// Title
|
|
128
|
+
ctx.font = 'bold 24px sans-serif';
|
|
129
|
+
ctx.fillText('Audio Visualizer (node-av)', 20, 35);
|
|
130
|
+
// Time
|
|
131
|
+
ctx.font = '16px monospace';
|
|
132
|
+
ctx.fillText(`Time: ${time.toFixed(2)}s`, WIDTH - 120, 35);
|
|
133
|
+
// Frequency labels
|
|
134
|
+
ctx.font = '12px monospace';
|
|
135
|
+
ctx.textAlign = 'center';
|
|
136
|
+
const barWidth = (WIDTH - 40) / frequencies.length;
|
|
137
|
+
for (let i = 0; i < frequencies.length; i++) {
|
|
138
|
+
const x = 20 + i * barWidth + barWidth / 2;
|
|
139
|
+
ctx.fillText(`${frequencies[i].toFixed(0)}Hz`, x, HEIGHT - 10);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function main() {
|
|
143
|
+
console.log('╔═══════════════════════════════════════════════════════════════╗');
|
|
144
|
+
console.log('║ Audio Visualizer Demo (node-av Muxer) ║');
|
|
145
|
+
console.log('╚═══════════════════════════════════════════════════════════════╝\n');
|
|
146
|
+
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
147
|
+
// Initialize audio state with varying amplitudes
|
|
148
|
+
const audioState = {
|
|
149
|
+
frequencies: FREQUENCIES.slice(0, 8),
|
|
150
|
+
amplitudes: [0.8, 0.6, 0.7, 0.5, 0.9, 0.4, 0.6, 0.7],
|
|
151
|
+
phases: FREQUENCIES.map((_, i) => (i * Math.PI) / 4),
|
|
152
|
+
};
|
|
153
|
+
// Create canvas
|
|
154
|
+
const canvas = createCanvas({ width: WIDTH, height: HEIGHT });
|
|
155
|
+
const ctx = canvas.getContext('2d');
|
|
156
|
+
// Collect encoded chunks
|
|
157
|
+
const videoChunks = [];
|
|
158
|
+
const audioChunks = [];
|
|
159
|
+
let videoDescription;
|
|
160
|
+
let audioDescription;
|
|
161
|
+
// Video encoder
|
|
162
|
+
const videoEncoder = new VideoEncoder({
|
|
163
|
+
output: (chunk, metadata) => {
|
|
164
|
+
videoChunks.push(chunk);
|
|
165
|
+
if (metadata?.decoderConfig?.description && !videoDescription) {
|
|
166
|
+
const desc = metadata.decoderConfig.description;
|
|
167
|
+
videoDescription = desc instanceof Uint8Array ? desc : new Uint8Array(desc);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
error: (err) => console.error('Video encoder error:', err),
|
|
171
|
+
});
|
|
172
|
+
videoEncoder.configure({
|
|
173
|
+
codec: 'avc1.64001E',
|
|
174
|
+
width: WIDTH,
|
|
175
|
+
height: HEIGHT,
|
|
176
|
+
framerate: FRAME_RATE,
|
|
177
|
+
bitrate: 4_000_000,
|
|
178
|
+
latencyMode: 'quality',
|
|
179
|
+
hardwareAcceleration: 'prefer-hardware',
|
|
180
|
+
});
|
|
181
|
+
// Audio encoder
|
|
182
|
+
const audioEncoder = new AudioEncoder({
|
|
183
|
+
output: (chunk, metadata) => {
|
|
184
|
+
audioChunks.push(chunk);
|
|
185
|
+
if (metadata?.decoderConfig?.description && !audioDescription) {
|
|
186
|
+
const desc = metadata.decoderConfig.description;
|
|
187
|
+
audioDescription = desc instanceof Uint8Array ? desc : new Uint8Array(desc);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
error: (err) => console.error('Audio encoder error:', err),
|
|
191
|
+
});
|
|
192
|
+
audioEncoder.configure({
|
|
193
|
+
codec: 'mp4a.40.2', // AAC-LC
|
|
194
|
+
sampleRate: SAMPLE_RATE,
|
|
195
|
+
numberOfChannels: AUDIO_CHANNELS,
|
|
196
|
+
bitrate: 128_000,
|
|
197
|
+
});
|
|
198
|
+
console.log(` Resolution: ${WIDTH}x${HEIGHT}`);
|
|
199
|
+
console.log(` Duration: ${DURATION_SECONDS}s`);
|
|
200
|
+
console.log(` Frequencies: ${audioState.frequencies.map(f => f.toFixed(0) + 'Hz').join(', ')}`);
|
|
201
|
+
console.log(` Encoding...\n`);
|
|
202
|
+
const startTime = Date.now();
|
|
203
|
+
let totalSamples = 0;
|
|
204
|
+
for (let i = 0; i < FRAME_COUNT; i++) {
|
|
205
|
+
// Backpressure: wait if encoder queues are getting full
|
|
206
|
+
while (videoEncoder.encodeQueueSize >= 50 || audioEncoder.encodeQueueSize >= 50) {
|
|
207
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
208
|
+
}
|
|
209
|
+
const time = i / FRAME_RATE;
|
|
210
|
+
const timestamp = i * FRAME_DURATION_US;
|
|
211
|
+
// Animate amplitudes over time
|
|
212
|
+
for (let f = 0; f < audioState.amplitudes.length; f++) {
|
|
213
|
+
audioState.amplitudes[f] = 0.3 + 0.5 * Math.abs(Math.sin(time * 0.5 + f * 0.7));
|
|
214
|
+
}
|
|
215
|
+
// Generate audio samples for this frame
|
|
216
|
+
const samples = generateAudioSamples(audioState, SAMPLES_PER_FRAME, SAMPLE_RATE, totalSamples);
|
|
217
|
+
totalSamples += SAMPLES_PER_FRAME;
|
|
218
|
+
// Encode audio samples
|
|
219
|
+
const audioData = new AudioData({
|
|
220
|
+
format: 'f32-planar',
|
|
221
|
+
sampleRate: SAMPLE_RATE,
|
|
222
|
+
numberOfFrames: SAMPLES_PER_FRAME,
|
|
223
|
+
numberOfChannels: AUDIO_CHANNELS,
|
|
224
|
+
timestamp,
|
|
225
|
+
data: samples,
|
|
226
|
+
});
|
|
227
|
+
audioEncoder.encode(audioData);
|
|
228
|
+
audioData.close();
|
|
229
|
+
// Draw visualization
|
|
230
|
+
ctx.fillStyle = COLORS.background;
|
|
231
|
+
ctx.fillRect(0, 0, WIDTH, HEIGHT);
|
|
232
|
+
drawGrid(ctx, WIDTH, HEIGHT);
|
|
233
|
+
// Waveform in top half
|
|
234
|
+
drawWaveform(ctx, samples, 20, 60, WIDTH - 40, HEIGHT / 2 - 80);
|
|
235
|
+
// Spectrum bars in bottom half
|
|
236
|
+
drawSpectrumBars(ctx, audioState.amplitudes, 20, HEIGHT / 2 + 20, WIDTH - 40, HEIGHT / 2 - 60, time);
|
|
237
|
+
// Labels
|
|
238
|
+
drawLabels(ctx, audioState.frequencies, time);
|
|
239
|
+
// Divider line
|
|
240
|
+
ctx.strokeStyle = COLORS.grid;
|
|
241
|
+
ctx.lineWidth = 2;
|
|
242
|
+
ctx.beginPath();
|
|
243
|
+
ctx.moveTo(0, HEIGHT / 2);
|
|
244
|
+
ctx.lineTo(WIDTH, HEIGHT / 2);
|
|
245
|
+
ctx.stroke();
|
|
246
|
+
// Create video frame
|
|
247
|
+
const pixels = getRawPixels(canvas);
|
|
248
|
+
const frame = new VideoFrame(pixels, {
|
|
249
|
+
format: 'RGBA',
|
|
250
|
+
codedWidth: WIDTH,
|
|
251
|
+
codedHeight: HEIGHT,
|
|
252
|
+
timestamp,
|
|
253
|
+
});
|
|
254
|
+
videoEncoder.encode(frame, { keyFrame: i % 30 === 0 });
|
|
255
|
+
frame.close();
|
|
256
|
+
// Progress indicator
|
|
257
|
+
if ((i + 1) % 60 === 0) {
|
|
258
|
+
const elapsed = Date.now() - startTime;
|
|
259
|
+
const fps = ((i + 1) / elapsed) * 1000;
|
|
260
|
+
console.log(` Frame ${i + 1}/${FRAME_COUNT} (${fps.toFixed(1)} fps)`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Flush encoders
|
|
264
|
+
await videoEncoder.flush();
|
|
265
|
+
await audioEncoder.flush();
|
|
266
|
+
videoEncoder.close();
|
|
267
|
+
audioEncoder.close();
|
|
268
|
+
const encodeTime = Date.now() - startTime;
|
|
269
|
+
console.log(`\n Encoding complete: ${encodeTime}ms`);
|
|
270
|
+
console.log(` Video chunks: ${videoChunks.length}`);
|
|
271
|
+
console.log(` Audio chunks: ${audioChunks.length}`);
|
|
272
|
+
// Mux using node-av Muxer
|
|
273
|
+
console.log(' Muxing with node-av...');
|
|
274
|
+
const muxStartTime = Date.now();
|
|
275
|
+
const muxer = new NodeAvMuxer({ path: OUTPUT_VIDEO });
|
|
276
|
+
await muxer.open();
|
|
277
|
+
// Add video track
|
|
278
|
+
await muxer.addVideoTrack({
|
|
279
|
+
codec: 'avc1.64001E',
|
|
280
|
+
codedWidth: WIDTH,
|
|
281
|
+
codedHeight: HEIGHT,
|
|
282
|
+
framerate: FRAME_RATE,
|
|
283
|
+
bitrate: 4_000_000,
|
|
284
|
+
description: videoDescription,
|
|
285
|
+
});
|
|
286
|
+
// Add audio track
|
|
287
|
+
await muxer.addAudioTrack({
|
|
288
|
+
codec: 'mp4a.40.2',
|
|
289
|
+
sampleRate: SAMPLE_RATE,
|
|
290
|
+
numberOfChannels: AUDIO_CHANNELS,
|
|
291
|
+
bitrate: 128_000,
|
|
292
|
+
description: audioDescription,
|
|
293
|
+
});
|
|
294
|
+
// Write video chunks
|
|
295
|
+
for (const chunk of videoChunks) {
|
|
296
|
+
await muxer.writeVideoChunk(chunk);
|
|
297
|
+
}
|
|
298
|
+
// Write audio chunks
|
|
299
|
+
for (const chunk of audioChunks) {
|
|
300
|
+
await muxer.writeAudioChunk(chunk);
|
|
301
|
+
}
|
|
302
|
+
await muxer.close();
|
|
303
|
+
const muxTime = Date.now() - muxStartTime;
|
|
304
|
+
console.log(` Muxing complete: ${muxTime}ms`);
|
|
305
|
+
const totalTime = Date.now() - startTime;
|
|
306
|
+
const stats = fs.statSync(OUTPUT_VIDEO);
|
|
307
|
+
console.log(`\n Output: ${OUTPUT_VIDEO}`);
|
|
308
|
+
console.log(` Size: ${(stats.size / 1024).toFixed(1)} KB`);
|
|
309
|
+
console.log(` Total time: ${totalTime}ms`);
|
|
310
|
+
console.log('\n╔═══════════════════════════════════════════════════════════════╗');
|
|
311
|
+
console.log('║ Demo Complete! ║');
|
|
312
|
+
console.log('╚═══════════════════════════════════════════════════════════════╝\n');
|
|
313
|
+
}
|
|
314
|
+
main().catch((err) => {
|
|
315
|
+
console.error(err);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
});
|
|
318
|
+
//# sourceMappingURL=demo-audio-visualizer-nodeav.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-audio-visualizer-nodeav.js","sourceRoot":"","sources":["../../src/demos/demo-audio-visualizer-nodeav.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-muxer-fallback.d.ts","sourceRoot":"","sources":["../../src/demos/demo-muxer-fallback.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo: Muxer Fallback Test
|
|
3
|
+
*
|
|
4
|
+
* Tests the Muxer class which tries node-av first
|
|
5
|
+
* and falls back to FFmpeg spawn if it fails.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { createCanvas, getRawPixels } from '../canvas/index.js';
|
|
10
|
+
import { VideoEncoder } from '../encoders/VideoEncoder.js';
|
|
11
|
+
import { AudioEncoder } from '../encoders/AudioEncoder.js';
|
|
12
|
+
import { VideoFrame } from '../core/VideoFrame.js';
|
|
13
|
+
import { AudioData } from '../core/AudioData.js';
|
|
14
|
+
import { muxChunks } from '../containers/index.js';
|
|
15
|
+
const WIDTH = 320;
|
|
16
|
+
const HEIGHT = 240;
|
|
17
|
+
const DURATION_SECONDS = 2;
|
|
18
|
+
const FRAME_RATE = 30;
|
|
19
|
+
const SAMPLE_RATE = 48000;
|
|
20
|
+
const AUDIO_CHANNELS = 2;
|
|
21
|
+
const FRAME_COUNT = DURATION_SECONDS * FRAME_RATE;
|
|
22
|
+
const FRAME_DURATION_US = Math.round(1_000_000 / FRAME_RATE);
|
|
23
|
+
const SAMPLES_PER_FRAME = Math.round(SAMPLE_RATE / FRAME_RATE);
|
|
24
|
+
const OUTPUT_DIR = path.resolve('media', 'fallback-test');
|
|
25
|
+
async function generateTestContent() {
|
|
26
|
+
const videoChunks = [];
|
|
27
|
+
const audioChunks = [];
|
|
28
|
+
let videoDescription;
|
|
29
|
+
let audioDescription;
|
|
30
|
+
const canvas = createCanvas({ width: WIDTH, height: HEIGHT });
|
|
31
|
+
const ctx = canvas.getContext('2d');
|
|
32
|
+
const videoEncoder = new VideoEncoder({
|
|
33
|
+
output: (chunk, metadata) => {
|
|
34
|
+
videoChunks.push(chunk);
|
|
35
|
+
if (metadata?.decoderConfig?.description && !videoDescription) {
|
|
36
|
+
const desc = metadata.decoderConfig.description;
|
|
37
|
+
videoDescription = desc instanceof Uint8Array ? desc : new Uint8Array(desc);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
error: (err) => console.error('Video encoder error:', err),
|
|
41
|
+
});
|
|
42
|
+
videoEncoder.configure({
|
|
43
|
+
codec: 'avc1.42001E',
|
|
44
|
+
width: WIDTH,
|
|
45
|
+
height: HEIGHT,
|
|
46
|
+
framerate: FRAME_RATE,
|
|
47
|
+
bitrate: 500_000,
|
|
48
|
+
});
|
|
49
|
+
const audioEncoder = new AudioEncoder({
|
|
50
|
+
output: (chunk, metadata) => {
|
|
51
|
+
audioChunks.push(chunk);
|
|
52
|
+
if (metadata?.decoderConfig?.description && !audioDescription) {
|
|
53
|
+
const desc = metadata.decoderConfig.description;
|
|
54
|
+
audioDescription = desc instanceof Uint8Array ? desc : new Uint8Array(desc);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
error: (err) => console.error('Audio encoder error:', err),
|
|
58
|
+
});
|
|
59
|
+
audioEncoder.configure({
|
|
60
|
+
codec: 'mp4a.40.2',
|
|
61
|
+
sampleRate: SAMPLE_RATE,
|
|
62
|
+
numberOfChannels: AUDIO_CHANNELS,
|
|
63
|
+
bitrate: 64_000,
|
|
64
|
+
});
|
|
65
|
+
for (let i = 0; i < FRAME_COUNT; i++) {
|
|
66
|
+
const timestamp = i * FRAME_DURATION_US;
|
|
67
|
+
const hue = (i / FRAME_COUNT) * 360;
|
|
68
|
+
// Draw simple colored frame
|
|
69
|
+
ctx.fillStyle = `hsl(${hue}, 70%, 50%)`;
|
|
70
|
+
ctx.fillRect(0, 0, WIDTH, HEIGHT);
|
|
71
|
+
ctx.fillStyle = 'white';
|
|
72
|
+
ctx.font = '24px sans-serif';
|
|
73
|
+
ctx.textAlign = 'center';
|
|
74
|
+
ctx.fillText(`Frame ${i}`, WIDTH / 2, HEIGHT / 2);
|
|
75
|
+
const pixels = getRawPixels(canvas);
|
|
76
|
+
const frame = new VideoFrame(pixels, {
|
|
77
|
+
format: 'RGBA',
|
|
78
|
+
codedWidth: WIDTH,
|
|
79
|
+
codedHeight: HEIGHT,
|
|
80
|
+
timestamp,
|
|
81
|
+
});
|
|
82
|
+
videoEncoder.encode(frame, { keyFrame: i % 30 === 0 });
|
|
83
|
+
frame.close();
|
|
84
|
+
// Generate audio
|
|
85
|
+
const samples = new Float32Array(SAMPLES_PER_FRAME * AUDIO_CHANNELS);
|
|
86
|
+
const freq = 440 + Math.sin(i * 0.1) * 100;
|
|
87
|
+
for (let s = 0; s < SAMPLES_PER_FRAME; s++) {
|
|
88
|
+
const t = s / SAMPLE_RATE;
|
|
89
|
+
const sample = Math.sin(2 * Math.PI * freq * t) * 0.3;
|
|
90
|
+
samples[s * AUDIO_CHANNELS] = sample;
|
|
91
|
+
samples[s * AUDIO_CHANNELS + 1] = sample;
|
|
92
|
+
}
|
|
93
|
+
const audioData = new AudioData({
|
|
94
|
+
format: 'f32-planar',
|
|
95
|
+
sampleRate: SAMPLE_RATE,
|
|
96
|
+
numberOfFrames: SAMPLES_PER_FRAME,
|
|
97
|
+
numberOfChannels: AUDIO_CHANNELS,
|
|
98
|
+
timestamp,
|
|
99
|
+
data: samples,
|
|
100
|
+
});
|
|
101
|
+
audioEncoder.encode(audioData);
|
|
102
|
+
audioData.close();
|
|
103
|
+
}
|
|
104
|
+
await videoEncoder.flush();
|
|
105
|
+
await audioEncoder.flush();
|
|
106
|
+
videoEncoder.close();
|
|
107
|
+
audioEncoder.close();
|
|
108
|
+
return { videoChunks, audioChunks, videoDescription, audioDescription };
|
|
109
|
+
}
|
|
110
|
+
async function testMuxer(name, outputPath, forceBackend) {
|
|
111
|
+
console.log(`\n Testing ${name}...`);
|
|
112
|
+
const { videoChunks, audioChunks, videoDescription, audioDescription } = await generateTestContent();
|
|
113
|
+
const startTime = Date.now();
|
|
114
|
+
const result = await muxChunks({
|
|
115
|
+
path: outputPath,
|
|
116
|
+
video: {
|
|
117
|
+
config: {
|
|
118
|
+
codec: 'avc1.42001E',
|
|
119
|
+
codedWidth: WIDTH,
|
|
120
|
+
codedHeight: HEIGHT,
|
|
121
|
+
framerate: FRAME_RATE,
|
|
122
|
+
description: videoDescription,
|
|
123
|
+
},
|
|
124
|
+
chunks: videoChunks,
|
|
125
|
+
},
|
|
126
|
+
audio: {
|
|
127
|
+
config: {
|
|
128
|
+
codec: 'mp4a.40.2',
|
|
129
|
+
sampleRate: SAMPLE_RATE,
|
|
130
|
+
numberOfChannels: AUDIO_CHANNELS,
|
|
131
|
+
description: audioDescription,
|
|
132
|
+
},
|
|
133
|
+
chunks: audioChunks,
|
|
134
|
+
},
|
|
135
|
+
forceBackend,
|
|
136
|
+
onFallback: (err) => console.log(` Fallback triggered: ${err.message}`),
|
|
137
|
+
});
|
|
138
|
+
const totalTime = Date.now() - startTime;
|
|
139
|
+
const stats = fs.statSync(outputPath);
|
|
140
|
+
console.log(` Backend: ${result.backend}`);
|
|
141
|
+
console.log(` Muxing time: ${result.durationMs}ms`);
|
|
142
|
+
console.log(` Total time: ${totalTime}ms`);
|
|
143
|
+
console.log(` Output: ${outputPath}`);
|
|
144
|
+
console.log(` Size: ${(stats.size / 1024).toFixed(1)} KB`);
|
|
145
|
+
}
|
|
146
|
+
async function main() {
|
|
147
|
+
console.log('╔═══════════════════════════════════════════════════════════════╗');
|
|
148
|
+
console.log('║ Muxer Fallback Test ║');
|
|
149
|
+
console.log('╚═══════════════════════════════════════════════════════════════╝');
|
|
150
|
+
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
|
151
|
+
// Test 1: Node-av muxer (forced)
|
|
152
|
+
await testMuxer('node-av (forced)', path.join(OUTPUT_DIR, 'test-nodeav.mp4'), 'node-av');
|
|
153
|
+
// Test 2: FFmpeg spawn muxer (forced)
|
|
154
|
+
await testMuxer('FFmpeg spawn (forced)', path.join(OUTPUT_DIR, 'test-ffmpeg.mp4'), 'ffmpeg-spawn');
|
|
155
|
+
// Test 3: Automatic (node-av with fallback)
|
|
156
|
+
await testMuxer('Automatic (node-av with fallback)', path.join(OUTPUT_DIR, 'test-auto.mp4'));
|
|
157
|
+
console.log('\n╔═══════════════════════════════════════════════════════════════╗');
|
|
158
|
+
console.log('║ All Tests Passed! ║');
|
|
159
|
+
console.log('╚═══════════════════════════════════════════════════════════════╝\n');
|
|
160
|
+
}
|
|
161
|
+
main().catch((err) => {
|
|
162
|
+
console.error(err);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=demo-muxer-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-muxer-fallback.js","sourceRoot":"","sources":["../../src/demos/demo-muxer-fallback.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,8 @@ export declare class AudioEncoder extends WebCodecsEventTarget {
|
|
|
48
48
|
private _flushPromise;
|
|
49
49
|
/** Actual encoder sample rate (48kHz for Opus, config.sampleRate otherwise) */
|
|
50
50
|
private _encoderSampleRate;
|
|
51
|
+
/** Cached codec base for hot path */
|
|
52
|
+
private _codecBase;
|
|
51
53
|
constructor(init: AudioEncoderInit);
|
|
52
54
|
get state(): CodecState;
|
|
53
55
|
get encodeQueueSize(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioEncoder.d.ts","sourceRoot":"","sources":["../../src/encoders/AudioEncoder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGjE,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;AAkBpD,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,YAAY,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,WAAW,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAClF,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,CAAC,EAAE,UAAU,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAQD,qBAAa,YAAa,SAAQ,oBAAoB;IACpD,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,eAAe,CAA4E;IACnG,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,aAAa,CAA8B;IACnD,+EAA+E;IAC/E,OAAO,CAAC,kBAAkB,CAAK;
|
|
1
|
+
{"version":3,"file":"AudioEncoder.d.ts","sourceRoot":"","sources":["../../src/encoders/AudioEncoder.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,8 @@ export class AudioEncoder extends WebCodecsEventTarget {
|
|
|
33
33
|
_flushPromise = null;
|
|
34
34
|
/** Actual encoder sample rate (48kHz for Opus, config.sampleRate otherwise) */
|
|
35
35
|
_encoderSampleRate = 0;
|
|
36
|
+
/** Cached codec base for hot path */
|
|
37
|
+
_codecBase = null;
|
|
36
38
|
constructor(init) {
|
|
37
39
|
super();
|
|
38
40
|
if (!init || typeof init.output !== 'function') {
|
|
@@ -119,8 +121,9 @@ export class AudioEncoder extends WebCodecsEventTarget {
|
|
|
119
121
|
this._bitstreamFormat = config.format ?? 'adts';
|
|
120
122
|
this._codecDescription = null;
|
|
121
123
|
// Opus always encodes at 48kHz regardless of input sample rate
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
// Cache codec base for hot path in _onEncoderFrame
|
|
125
|
+
this._codecBase = getCodecBase(config.codec);
|
|
126
|
+
const isOpus = this._codecBase === 'opus';
|
|
124
127
|
this._encoderSampleRate = isOpus ? OPUS_ENCODER_SAMPLE_RATE : config.sampleRate;
|
|
125
128
|
this._startEncoder();
|
|
126
129
|
}
|
|
@@ -290,8 +293,8 @@ export class AudioEncoder extends WebCodecsEventTarget {
|
|
|
290
293
|
const timestamp = Math.max(0, (frame.timestamp * 1_000_000) / this._encoderSampleRate);
|
|
291
294
|
const duration = (samplesPerFrame * 1_000_000) / this._encoderSampleRate;
|
|
292
295
|
let payload = frame.data;
|
|
293
|
-
|
|
294
|
-
const isAac =
|
|
296
|
+
// Use cached codec base for hot path
|
|
297
|
+
const isAac = this._codecBase === 'mp4a' || this._codecBase === 'aac';
|
|
295
298
|
// Use description from backend if provided (AAC, FLAC, Vorbis, etc.)
|
|
296
299
|
// For AAC, the backend provides proper AudioSpecificConfig with correct channelConfiguration
|
|
297
300
|
if (frame.description && !this._codecDescription) {
|