fix: codec fallback list for VideoEncoder with descriptive errors

Replaces single hardcoded avc1.640033 with a 5-step fallback chain
(High 5.1 → Main 5.1 → Baseline 5.1 → Main 3.1 → Baseline 3.1).
Each codec is tried with hardware acceleration first, then software.
The final error message now includes which codecs were attempted, the
output dimensions, and a suggestion to lower the quality setting.
This commit is contained in:
webadderall
2026-03-16 21:49:06 +11:00
parent 43678fdb85
commit 3615e09e2c
+41 -25
View File
@@ -258,6 +258,14 @@ export class VideoExporter {
this.chunkCount = 0;
let videoDescription: Uint8Array | undefined;
// Ordered from most capable to most compatible. avc1.PPCCLL where PP=profile, CC=constraints, LL=level.
// High 5.1 → Main 5.1 → Baseline 5.1 → Main 3.1 → Baseline 3.1
const CODEC_FALLBACK_LIST = this.config.codec
? [this.config.codec]
: ['avc1.640033', 'avc1.4d4033', 'avc1.420033', 'avc1.4d401f', 'avc1.42001f'];
let resolvedCodec: string | null = null;
this.encoder = new VideoEncoder({
output: (chunk, meta) => {
// Capture decoder config metadata from encoder output
@@ -288,7 +296,7 @@ export class VideoExporter {
const metadata: EncodedVideoChunkMetadata = {
decoderConfig: {
codec: this.config.codec || 'avc1.640033',
codec: resolvedCodec ?? (this.config.codec || 'avc1.640033'),
codedWidth: this.config.width,
codedHeight: this.config.height,
description: this.videoDescription,
@@ -307,44 +315,52 @@ export class VideoExporter {
this.encodeQueue--;
},
error: (error) => {
console.error('[VideoExporter] Encoder error:', error);
// Stop export encoding failed
console.error(
`[VideoExporter] Encoder error (codec: ${resolvedCodec}, ${this.config.width}x${this.config.height}):`,
error,
);
// Stop export — encoding failed
this.cancelled = true;
},
});
const codec = this.config.codec || 'avc1.640033';
const encoderConfig: VideoEncoderConfig = {
codec,
const baseConfig: Omit<VideoEncoderConfig, 'codec' | 'hardwareAcceleration'> = {
width: this.config.width,
height: this.config.height,
bitrate: this.config.bitrate,
framerate: this.config.frameRate,
latencyMode: 'quality', // Changed from 'realtime' to 'quality' for better throughput
latencyMode: 'quality',
bitrateMode: 'variable',
hardwareAcceleration: 'prefer-hardware',
};
// Check hardware support first
const hardwareSupport = await VideoEncoder.isConfigSupported(encoderConfig);
if (hardwareSupport.supported) {
// Use hardware encoding
console.log('[VideoExporter] Using hardware acceleration');
this.encoder.configure(encoderConfig);
} else {
// Fall back to software encoding
console.log('[VideoExporter] Hardware not supported, using software encoding');
encoderConfig.hardwareAcceleration = 'prefer-software';
const softwareSupport = await VideoEncoder.isConfigSupported(encoderConfig);
if (!softwareSupport.supported) {
throw new Error('Video encoding not supported on this system');
for (const candidateCodec of CODEC_FALLBACK_LIST) {
const hwConfig: VideoEncoderConfig = { ...baseConfig, codec: candidateCodec, hardwareAcceleration: 'prefer-hardware' };
const hwSupport = await VideoEncoder.isConfigSupported(hwConfig);
if (hwSupport.supported) {
resolvedCodec = candidateCodec;
console.log(`[VideoExporter] Using hardware acceleration with codec ${candidateCodec}`);
this.encoder.configure(hwConfig);
return;
}
this.encoder.configure(encoderConfig);
const swConfig: VideoEncoderConfig = { ...baseConfig, codec: candidateCodec, hardwareAcceleration: 'prefer-software' };
const swSupport = await VideoEncoder.isConfigSupported(swConfig);
if (swSupport.supported) {
resolvedCodec = candidateCodec;
console.log(`[VideoExporter] Using software encoding with codec ${candidateCodec}`);
this.encoder.configure(swConfig);
return;
}
console.warn(`[VideoExporter] Codec ${candidateCodec} not supported (${this.config.width}x${this.config.height}), trying next…`);
}
throw new Error(
`Video encoding not supported on this system. ` +
`Tried codecs: ${CODEC_FALLBACK_LIST.join(', ')} at ${this.config.width}x${this.config.height}. ` +
`Your browser or hardware may not support H.264 encoding at this resolution. ` +
`Try exporting at a lower quality setting.`,
);
}
cancel(): void {