mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-26 15:55:35 +00:00
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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user