remotion-dev/remotion · error · Error
Expected AAC codec private data
Error message
Expected AAC codec private data
What it means
Thrown by getActualDecoderParameters when an audio track is labeled codec 'aac' and codecPrivate is non-null, but codecPrivate.type is not 'aac-config'. The function only knows how to derive real channel count and sample rate from a properly shaped AAC-specific config blob; any other shape is a logic/data mismatch rather than a missing field. It is an internal contract violation: the upstream codecPrivate producer mislabeled the payload.
Source
Thrown at packages/media-parser/src/containers/iso-base-media/get-actual-number-of-channels.ts:41
audioCodec: MediaParserAudioCodec;
codecPrivate: MediaParserCodecData | null;
numberOfChannels: number;
sampleRate: number;
}): AudioDecoderConfig => {
if (audioCodec !== 'aac') {
return {
numberOfChannels,
sampleRate,
codecPrivate,
};
}
if (codecPrivate === null) {
return {numberOfChannels, sampleRate, codecPrivate};
}
if (codecPrivate.type !== 'aac-config') {
throw new Error('Expected AAC codec private data');
}
const parsed = parseAacCodecPrivate(codecPrivate.data);
const actual = createAacCodecPrivate({
...parsed,
codecPrivate: codecPrivate.data,
});
return {
numberOfChannels: parsed.channelConfiguration,
sampleRate: parsed.sampleRate,
codecPrivate: {type: 'aac-config', data: actual},
};
};
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Re-mux the audio track with ffmpeg: `ffmpeg -i in.mp4 -c:a aac -b:a 128k out.mp4` to regenerate a clean esds.
- If you control the caller, narrow audioCodec before invoking getActualDecoderParameters: only pass AAC private data when codecPrivate.type === 'aac-config'.
- File a media-parser issue with the offending file; this typically indicates a parser regression.
- Wrap the call in try/catch and fall back to the original numberOfChannels/sampleRate when private-data parsing fails.
Example fix
// before
const actual = getActualDecoderParameters({ audioCodec, codecPrivate, numberOfChannels, sampleRate });
// after
const actual =
audioCodec === 'aac' && codecPrivate && codecPrivate.type !== 'aac-config'
? { numberOfChannels, sampleRate, codecPrivate: null } // fall back: ignore mismatched private data
: getActualDecoderParameters({ audioCodec, codecPrivate, numberOfChannels, sampleRate }); Defensive patterns
Strategy: type-guard
Validate before calling
import type {MediaParserCodecData} from '../../codec-data';
function isAacConfigPrivate(data: MediaParserCodecData | null): data is { type: 'aac-config'; data: Uint8Array } {
return data !== null && data.type === 'aac-config';
} Type guard
import type {MediaParserCodecData} from '../../codec-data';
function isAacCodecPrivate(data: MediaParserCodecData | null): boolean {
return data === null || data.type === 'aac-config';
}
// Use before getActualDecoderParameters:
if (audioCodec === 'aac' && !isAacCodecPrivate(codecPrivate)) {
codecPrivate = null; // discard mismatched private data
} Try / catch
try {
const actual = getActualDecoderParameters({ audioCodec, codecPrivate, numberOfChannels, sampleRate });
} catch (err) {
if (/Expected AAC codec private data/i.test(String(err?.message))) {
// Fall back to declared channel count; ignore the bad private data
return { numberOfChannels, sampleRate, codecPrivate: null };
}
throw err;
} Prevention
- Narrow codecPrivate by type before passing it into AAC-specific helpers.
- If you produce codecPrivate objects, always set type to 'aac-config' for AAC.
- Wrap audio decoder parameter resolution in a fallback that drops codecPrivate on mismatch.
- Re-mux audio tracks with a recent ffmpeg AAC encoder to regenerate a clean esds.
When it happens
Trigger: Reachable when getCodecPrivateFromTrak or the esds parser yields a codecPrivate object whose type is something like 'av1-config' or a raw buffer wrapper, while getAudioCodecFromTrack separately classified the track as AAC. Most often a parser bug or a malformed esds box where the descriptor type does not match the audio codec family.
Common situations: MP4 files with non-standard or corrupted esds (Elementary Stream Descriptor) boxes. Files where the audio object type is ambiguous and one code path labels it AAC while another attaches non-AAC codec private data. Mismatch after a partial media-parser upgrade that changed the codecPrivate discriminated union.
Related errors
- Unsupported version ${version}
- Unexpected sampling frequency index ${samplingFrequencyIndex
- Unexpected sample rate ${sampleRate}
- Invalid channel configuration ${channelConfiguration}
- Invalid AAC codec private length
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/edfa343979fa3b15.
Report an issue: GitHub.