remotion-dev/remotion · error · Error

The primary audio track uses ${sourceCodec ?? 'an unknown co

Error message

The primary audio track uses ${sourceCodec ?? 'an unknown codec'}, which cannot be decoded in this browser. The audio cannot be converted to Opus.

What it means

prepareAudio() checks the primary audio track's codec via audioTrack.canDecode(). If the browser cannot decode the source codec (e.g. no AAC or E-AC-3 decoder in WebKit/Firefox), the track cannot be converted to Opus, and prepareAudio throws with the codec name (or 'an unknown codec' if the box reports none).

Source

Thrown at packages/video-matting/src/prepare-audio.ts:289

				} finally {
					await stopPacketIterator();
					closePacketSources();
				}
			},
			cancel: async () => {
				if (finished || canceled) {
					return;
				}

				canceled = true;
				pendingPacket = undefined;
				await stopPacketIterator();
			},
		};
	}

	if (!(await audioTrack.canDecode())) {
		throw new Error(
			`The primary audio track uses ${sourceCodec ?? 'an unknown codec'}, which ` +
				'cannot be decoded in this browser. The audio cannot be converted to Opus.',
		);
	}

	const originalNumberOfChannels = await audioTrack.getNumberOfChannels();
	const originalSampleRate = await audioTrack.getSampleRate();
	const quality = audioQuality ?? new Quality('medium');
	let outputNumberOfChannels = originalNumberOfChannels;
	let outputSampleRate = originalSampleRate;

	if (
		!(await canEncodeAudio('opus', {
			numberOfChannels: outputNumberOfChannels,
			sampleRate: outputSampleRate,
			quality,
		}))
	) {

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Remux/transcode the input's audio to Opus or AAC-decodable format before calling prepareAudio (e.g. with ffmpeg).
  2. Test support first with the track's canDecode() or AudioDecoder.isConfigSupported() and show a user-facing message.
  3. Prefer MP4 inputs with universally decodable audio (AAC/AAC-LC) or Opus-in-WebM inputs.
  4. If rendering server-side, use a headless Chrome build with the needed proprietary codecs.

Example fix

// before
const audio = await prepareAudio({input: movFile}); // AAC undecodable here
// after
if (!(await getPrimaryAudioTrack(input)).canDecode()) {
  input = await remuxToOpusWebM(input); // pre-transcode
}
const audio = await prepareAudio({input});
Defensive patterns

Strategy: fallback

Validate before calling

const track = await getPrimaryAudioTrack(input);
const decodable = await track.canDecode();
if (!decodable) input = await transcodeAudioToOpus(input);

Type guard

null

Try / catch

try { audio = await prepareAudio({input}); } catch (e) { if (e.message.includes('cannot be decoded')) { input = await transcodeWithFfmpeg(input); audio = await prepareAudio({input}); } else throw e; }

Prevention

When it happens

Trigger: Calling prepareAudio() on an MP4/MOV whose audio is AAC in a browser lacking AudioDecoder support for 'mp4a.40.2' (e.g. some WebKit builds); a codec string that WebCodecs cannot recognize at all.

Common situations: Safari/WebKit missing AAC decode support in the WebCodecs path; MOV files with proprietary audio codecs; running in an environment where AudioDecoder.isConfigSupported always rejects; server-side rendering without codec support.

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


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09). Data as JSON: /api/errors/6dfe714017a3b6d7. Report an issue: GitHub.