Export: fix VideoEncoder.configure TypeError on Chrome

probeExportCodec returned codec/muxerCodec but not config, so the
pre-probed pick used by the software-encoding warning path passed
undefined to VideoEncoder.configure, which Chrome rejects as "not of
type VideoEncoderConfig". Include config in the probe result and thread
it through exportSegment (test render was still reprobing and ignoring
the pick).

Also prefer the browser-negotiated config from isConfigSupported when
available — it is guaranteed valid for configure (covers new required
fields), whereas our minimal config had started failing validation on
Chrome despite isConfigSupported reporting "supported".

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Dejvino 2026-08-29 20:09:49 +02:00
parent e5484c9c38
commit a9b028b0bf
2 changed files with 13 additions and 6 deletions

View File

@ -123,18 +123,24 @@ async function pickVideoConfig(width, height, bitrate, fps) {
const config = { codec: cand.codec, width, height, bitrate, framerate: fps };
if (cand.avc) config.avc = cand.avc;
let supported = false;
let negotiatedConfig = null;
let negotiatedHardware = '';
try {
const sup = await VideoEncoder.isConfigSupported(config);
supported = !!sup.supported;
negotiatedHardware = sup.config ? sup.config.hardwareAcceleration || '' : '';
negotiatedConfig = sup.config || null;
negotiatedHardware = negotiatedConfig ? negotiatedConfig.hardwareAcceleration || '' : '';
} catch { supported = false; }
attempted.push(`${family.muxerCodec}:${cand.codec}=${supported ? 'ok' : 'no'}`);
if (!supported) continue;
// Found a supported profile — does it reorder? Baseline AVC never does;
// VP9/AV1 may, so we enforce the same test.
if (await emitsInPresentationOrder(config)) {
return { config, muxerCodec: family.muxerCodec, hardwareAcceleration: negotiatedHardware };
// Use the browser-negotiated config when available — it is guaranteed
// to satisfy VideoEncoderConfig validation (required fields, avc
// shape, etc). Chrome has started rejecting our minimal config with
// "not of type VideoEncoderConfig" even though isConfigSupported said
// "supported", while the negotiated config it returned configures fine.
const configToTest = negotiatedConfig || config;
if (await emitsInPresentationOrder(configToTest)) {
return { config: configToTest, muxerCodec: family.muxerCodec, hardwareAcceleration: negotiatedHardware };
}
reorderFailures.push(`${cand.codec}`);
}
@ -160,6 +166,7 @@ export async function probeExportCodec(width, height, bitrate, fps = 60) {
const picked = await pickVideoConfig(width, height, bitrate, fps);
if (!picked) return null;
return {
config: picked.config,
codec: picked.config.codec,
muxerCodec: picked.muxerCodec,
hardwareAcceleration: picked.hardwareAcceleration || '',

View File

@ -658,7 +658,7 @@ async function runExport(segment) {
const exporter = new Exporter(state.show);
const blob = segment
? await exportSegment(state.show, state.show.timeline.frame,
{ seconds: 20, preset, onProgress: exportProgress, exporter })
{ seconds: 20, preset, onProgress: exportProgress, exporter, videoPick: pick })
: await exporter.export({ preset, onProgress: exportProgress, videoPick: pick });
const suffix = segment ? `-segment-${state.show.timeline.frame}` : '';