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:
parent
e5484c9c38
commit
a9b028b0bf
@ -123,18 +123,24 @@ async function pickVideoConfig(width, height, bitrate, fps) {
|
|||||||
const config = { codec: cand.codec, width, height, bitrate, framerate: fps };
|
const config = { codec: cand.codec, width, height, bitrate, framerate: fps };
|
||||||
if (cand.avc) config.avc = cand.avc;
|
if (cand.avc) config.avc = cand.avc;
|
||||||
let supported = false;
|
let supported = false;
|
||||||
|
let negotiatedConfig = null;
|
||||||
let negotiatedHardware = '';
|
let negotiatedHardware = '';
|
||||||
try {
|
try {
|
||||||
const sup = await VideoEncoder.isConfigSupported(config);
|
const sup = await VideoEncoder.isConfigSupported(config);
|
||||||
supported = !!sup.supported;
|
supported = !!sup.supported;
|
||||||
negotiatedHardware = sup.config ? sup.config.hardwareAcceleration || '' : '';
|
negotiatedConfig = sup.config || null;
|
||||||
|
negotiatedHardware = negotiatedConfig ? negotiatedConfig.hardwareAcceleration || '' : '';
|
||||||
} catch { supported = false; }
|
} catch { supported = false; }
|
||||||
attempted.push(`${family.muxerCodec}:${cand.codec}=${supported ? 'ok' : 'no'}`);
|
attempted.push(`${family.muxerCodec}:${cand.codec}=${supported ? 'ok' : 'no'}`);
|
||||||
if (!supported) continue;
|
if (!supported) continue;
|
||||||
// Found a supported profile — does it reorder? Baseline AVC never does;
|
// Use the browser-negotiated config when available — it is guaranteed
|
||||||
// VP9/AV1 may, so we enforce the same test.
|
// to satisfy VideoEncoderConfig validation (required fields, avc
|
||||||
if (await emitsInPresentationOrder(config)) {
|
// shape, etc). Chrome has started rejecting our minimal config with
|
||||||
return { config, muxerCodec: family.muxerCodec, hardwareAcceleration: negotiatedHardware };
|
// "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}`);
|
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);
|
const picked = await pickVideoConfig(width, height, bitrate, fps);
|
||||||
if (!picked) return null;
|
if (!picked) return null;
|
||||||
return {
|
return {
|
||||||
|
config: picked.config,
|
||||||
codec: picked.config.codec,
|
codec: picked.config.codec,
|
||||||
muxerCodec: picked.muxerCodec,
|
muxerCodec: picked.muxerCodec,
|
||||||
hardwareAcceleration: picked.hardwareAcceleration || '',
|
hardwareAcceleration: picked.hardwareAcceleration || '',
|
||||||
|
|||||||
@ -658,7 +658,7 @@ async function runExport(segment) {
|
|||||||
const exporter = new Exporter(state.show);
|
const exporter = new Exporter(state.show);
|
||||||
const blob = segment
|
const blob = segment
|
||||||
? await exportSegment(state.show, state.show.timeline.frame,
|
? 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 });
|
: await exporter.export({ preset, onProgress: exportProgress, videoPick: pick });
|
||||||
|
|
||||||
const suffix = segment ? `-segment-${state.show.timeline.frame}` : '';
|
const suffix = segment ? `-segment-${state.show.timeline.frame}` : '';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user