remotion-dev/remotion · error · Error
The primary video track cannot be decoded.
Error message
The primary video track cannot be decoded.
What it means
A primary video track exists, but videoTrack.canDecode() returned false: the browser has no decoder for the track's codec/profile. Since frames cannot be decoded, video layer separation cannot proceed and the library throws. This is a browser WebCodecs capability limit, not a file corruption signal per se.
Source
Thrown at packages/video-matting/src/separate-video-layers.ts:262
const probeVideoInput = async ({
input,
videoQuality,
}: {
input: Input;
videoQuality: Quality;
}): Promise<{videoTrack: InputVideoTrack; width: number; height: number}> => {
if (!(await input.canRead())) {
throw new Error('The input is not a supported media file.');
}
const videoTrack = await input.getPrimaryVideoTrack();
if (videoTrack === null) {
throw new Error('The input does not contain a video track.');
}
if (!(await videoTrack.canDecode())) {
throw new Error('The primary video track cannot be decoded.');
}
const [width, height] = await Promise.all([
videoTrack.getDisplayWidth(),
videoTrack.getDisplayHeight(),
]);
if (
!Number.isInteger(width) ||
width <= 0 ||
!Number.isInteger(height) ||
height <= 0
) {
throw new Error('The input video has invalid dimensions.');
}
const [canEncodeBase, canEncodeForeground] = await Promise.all([
canEncodeVideo('vp9', {
width,View on GitHub (pinned to b2f4e34732)
Solutions
- Transcode the source to a universally decodable codec first (H.264 baseline/main in MP4, or VP8/VP9 in WebM).
- Test with the same file in another browser to confirm it is a codec-support issue.
- Use Mediabunny's codec support probing (e.g. getFirstEncodableVideoCodec / canDecode equivalents) to pre-check before calling.
- On iOS, ensure the HEVC video is exported as H.264 (Settings > Camera > Formats > Most Compatible).
Example fix
// before
await separateVideoLayers({src: hevcVideo.mov});
// after
await separateVideoLayers({src: await transcodeToH264(hevcVideo)}); Defensive patterns
Strategy: fallback
Validate before calling
const input = new Input({source: new BlobSource(file), formats: ALL_FORMATS});
const track = await input.getPrimaryVideoTrack();
if (track && !(await track.canDecode())) {
file = await transcodeToH264(file); // pre-transcode before separating
} Try / catch
try {
await separateVideoLayers({src});
} catch (e) {
if (e instanceof Error && e.message.includes('cannot be decoded')) {
const transcoded = await transcodeToH264(src);
return separateVideoLayers({src: transcoded});
}
throw e;
} Prevention
- Prefer H.264/MP4 or VP9/WebM sources; avoid HEVC .mov from iPhones.
- Pre-check canDecode() on the primary video track before heavy work.
- Document supported codecs in your upload UI.
When it happens
Trigger: Passing an H.265/HEVC, VP9 profile without hardware/software decode support, AV1 in a browser without AV1, or an exotic codec (ProRes, MPEG-2) to separateVideoLayers in a browser lacking the decoder.
Common situations: iPhone-recorded HEVC .mov files in Chrome; 10-bit H.264 high profiles; Firefox builds without proprietary codecs; old Safari versions without VP9 decode.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- No supported configs
- This browser cannot encode the VP9 video streams required fo
- Your browser does not support the WebCodecs ImageDecoder API
- Could not find video codec
- Audio track cannot be decoded
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/2a774e1124e37749.
Report an issue: GitHub.