remotion-dev/remotion · error

Only supporting layer 0 for .aac

Error message

Only supporting layer 0 for .aac

What it means

Thrown by parseAac when the 2-bit 'layer' field in an ADTS header is non-zero. Per the ADTS specification, valid AAC streams must have layer=0 (indicating MPEG-4 Audio). A non-zero layer means the bitstream is either not AAC or the header is corrupted, so the parser refuses to continue.

Source

Thrown at packages/media-parser/src/containers/aac/parse-aac.ts:29

export const parseAac = async (state: ParserState): Promise<ParseResult> => {
	const {iterator} = state;
	const startOffset = iterator.counter.getOffset();

	iterator.startReadingBits();
	const syncWord = iterator.getBits(12);
	if (syncWord !== 0xfff) {
		throw new Error('Invalid syncword: ' + syncWord);
	}

	const id = iterator.getBits(1);
	if (id !== 0) {
		throw new Error('Only supporting MPEG-4 for .aac');
	}

	const layer = iterator.getBits(2);
	if (layer !== 0) {
		throw new Error('Only supporting layer 0 for .aac');
	}

	const protectionAbsent = iterator.getBits(1); // protection absent
	const audioObjectType = iterator.getBits(2); // 1 = 'AAC-LC'

	const samplingFrequencyIndex = iterator.getBits(4);
	const sampleRate = getSampleRateFromSampleFrequencyIndex(
		samplingFrequencyIndex,
	);
	iterator.getBits(1); // private bit
	const channelConfiguration = iterator.getBits(3);
	const codecPrivate = createAacCodecPrivate({
		audioObjectType,
		sampleRate,
		channelConfiguration,
		codecPrivate: null,
	});
	iterator.getBits(1); // originality

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Check the actual format with `ffprobe input.aac` — if it reports MP3 or another codec, rename/re-handle accordingly.
  2. If ID3 tags are prepended, strip them: `ffmpeg -i input.aac -c:a copy -map_metadata -1 output.aac`.
  3. Re-encode from a known-good source to produce valid ADTS: `ffmpeg -i input.wav -c:a aac -f adts output.aac`.
  4. Switch to Mediabunny (https://www.remotion.dev/docs/mediabunny/metadata) for broader format handling.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: verify ADTS layer bits are 0 (bits 13-14 of ADTS header)
async function isAdtsLayerZero(filePath: string): Promise<boolean> {
  const buf = await readFile(filePath);
  if (buf.length < 2) return false;
  // Byte 1, bits 1-2 = layer field; should be 00
  return (buf[1] & 0x06) === 0x00;
}

Try / catch

try {
  const result = await parseMedia({src, fields: {/* ... */}});
} catch (e) {
  if (e instanceof Error && e.message === 'Only supporting layer 0 for .aac') {
    console.error('ADTS layer is non-zero. File may be corrupt or mislabeled. Run: ffprobe <file>');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Parsing a .aac file where the ADTS header's layer field (bits 13-14 after sync) is 1, 2, or 3 instead of 0. This can result from bit corruption, a file that is actually MP3 with an AAC extension, or a misaligned read position.

Common situations: Files mislabeled with a .aac extension that are actually MP3 or another MPEG audio layer. Corrupted downloads where header bits are flipped. Byte streams with a prepended ID3 tag or other metadata that offsets the read position.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/171af76424de1a1a. Report an issue: GitHub.