Make WebCodecs missing error message more helpful (fixes #466)

This commit is contained in:
Vanilagy
2026-08-20 23:22:28 +02:00
parent 1c4d1c70a8
commit 166298df2c
4 changed files with 32 additions and 11 deletions
+11 -2
View File
@@ -38,6 +38,7 @@ import {
isWebKit,
last,
mapAsyncGenerator,
missingWebCodecsClassMessage,
promiseWithResolvers,
removeItem,
Rotation,
@@ -1691,8 +1692,12 @@ export class VideoSampleSink extends BaseMediaSampleSink<VideoSample> {
onError: (error: unknown) => unknown,
) {
if (!(await this._track.canDecode())) {
if (typeof VideoDecoder === 'undefined') {
throw new Error(missingWebCodecsClassMessage('VideoDecoder'));
}
throw new Error(
'This video track cannot be decoded by this browser. Make sure to check decodability before using'
'This video track cannot be decoded in this environment. Make sure to check decodability before using'
+ ' a track.',
);
}
@@ -2426,8 +2431,12 @@ export class AudioSampleSink extends BaseMediaSampleSink<AudioSample> {
onError: (error: unknown) => unknown,
) {
if (!(await this._track.canDecode())) {
if (typeof AudioDecoder === 'undefined') {
throw new Error(missingWebCodecsClassMessage('AudioDecoder'));
}
throw new Error(
'This audio track cannot be decoded by this browser. Make sure to check decodability before using'
'This audio track cannot be decoded in this environment. Make sure to check decodability before using'
+ ' a track.',
);
}
+8 -6
View File
@@ -29,6 +29,7 @@ import {
clearIntervalUnthrottled,
floorToDivisor,
last,
missingWebCodecsClassMessage,
promiseWithResolvers,
roundToDivisor,
setInt24,
@@ -718,7 +719,7 @@ class VideoEncoderWrapper {
if (!selected) {
if (typeof VideoEncoder === 'undefined') {
throw new Error('VideoEncoder is not supported by this browser.');
throw new Error(missingWebCodecsClassMessage('VideoEncoder'));
}
// The candidates only differ in their rate control, so we describe them as one config with a
@@ -731,7 +732,7 @@ class VideoEncoderWrapper {
throw new Error(
`This specific encoder configuration (${firstConfig.codec}, ${rateControls.join(' / ')},`
+ ` ${firstConfig.width}x${firstConfig.height}, hardware acceleration:`
+ ` ${firstConfig.hardwareAcceleration ?? 'no-preference'}) is not supported by this browser.`
+ ` ${firstConfig.hardwareAcceleration ?? 'no-preference'}) is not supported in this environment.`
+ ` Consider using another codec or changing your video parameters.`,
);
}
@@ -1694,8 +1695,8 @@ export class MediaStreamVideoTrackSource extends VideoSource {
});
} else {
throw new Error(
'When no explicit frame rate is set, MediaStreamTrackProcessor is required; but it\'s not supported'
+ ' by this browser.',
'When no explicit frame rate is set, MediaStreamTrackProcessor is required; but it\'s not available'
+ ' in this environment.',
);
}
}
@@ -2210,7 +2211,7 @@ class AudioEncoderWrapper {
this.initPcmEncoder();
} else {
if (typeof AudioEncoder === 'undefined') {
throw new Error('AudioEncoder is not supported by this browser.');
throw new Error(missingWebCodecsClassMessage('AudioEncoder'));
}
let supported: boolean;
@@ -2226,7 +2227,8 @@ class AudioEncoderWrapper {
throw new Error(
`This specific encoder configuration (${encoderConfig.codec}, ${encoderConfig.bitrate} bps,`
+ ` ${encoderConfig.numberOfChannels} channels, ${encoderConfig.sampleRate} Hz) is not`
+ ` supported by this browser. Consider using another codec or changing your audio parameters.`,
+ ` supported in this environment. Consider using another codec or changing your`
+ ` audio parameters.`,
);
}
+10
View File
@@ -721,6 +721,16 @@ export const getChromiumVersion = () => {
return chromiumVersionCache = Number(match[1]!);
};
export const missingWebCodecsClassMessage = (className: string) => {
if (typeof globalThis.isSecureContext !== 'undefined' && !globalThis.isSecureContext) {
// WebCodecs is not exposed in insecure contexts
return `${className} is not available in this environment; this may be because this page is running in an`
+ ` insecure context. Try serving your page over HTTPS or use localhost.`;
}
return `${className} is not available in this environment.`;
};
/**
* T or a promise that resolves to T.
* @group Miscellaneous
+3 -3
View File
@@ -155,7 +155,7 @@ export class EncodedPacket {
throw new TypeError('Metadata-only packets cannot be converted to a video chunk.');
}
if (typeof EncodedVideoChunk === 'undefined') {
throw new Error('Your browser does not support EncodedVideoChunk.');
throw new Error('EncodedVideoChunk is not available in this environment.');
}
return new EncodedVideoChunk({
@@ -179,7 +179,7 @@ export class EncodedPacket {
throw new TypeError('Metadata-only packets cannot be converted to a video chunk.');
}
if (typeof EncodedVideoChunk === 'undefined') {
throw new Error('Your browser does not support EncodedVideoChunk.');
throw new Error('EncodedVideoChunk is not available in this environment.');
}
return new EncodedVideoChunk({
@@ -198,7 +198,7 @@ export class EncodedPacket {
throw new TypeError('Metadata-only packets cannot be converted to an audio chunk.');
}
if (typeof EncodedAudioChunk === 'undefined') {
throw new Error('Your browser does not support EncodedAudioChunk.');
throw new Error('EncodedAudioChunk is not available in this environment.');
}
return new EncodedAudioChunk({