{"record":{"id":"4dad144eba175d7d","repo":"remotion-dev/remotion","slug":"expected-vorbis-private-data-version-2","errorCode":null,"errorMessage":"Expected vorbis private data version 2","messagePattern":"Expected vorbis private data version 2","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/webm/description.ts","lineNumber":21,"sourceCode":"import {getCodecSegment, getPrivateData} from './traversal';\n\nexport const getAudioDescription = (\n\ttrack: TrackEntry,\n): undefined | Uint8Array => {\n\tconst codec = getCodecSegment(track);\n\tif (!codec || codec.value !== 'A_VORBIS') {\n\t\treturn undefined;\n\t}\n\n\t// how to parse vorbis private\n\t// https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java#L2466\n\tconst privateData = getPrivateData(track);\n\tif (!privateData) {\n\t\treturn undefined;\n\t}\n\n\tif (privateData[0] !== 2) {\n\t\tthrow new Error('Expected vorbis private data version 2');\n\t}\n\n\tlet offset = 1;\n\tlet vorbisInfoLength = 0;\n\tlet vorbisSkipLength = 0;\n\n\twhile ((privateData[offset] & 0xff) === 0xff) {\n\t\tvorbisInfoLength += 0xff;\n\t\toffset++;\n\t}\n\n\tvorbisInfoLength += privateData[offset++] & 0xff;\n\n\twhile ((privateData[offset] & 0xff) === 0xff) {\n\t\tvorbisSkipLength += 0xff;\n\t\toffset++;\n\t}\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/webm/description.ts#L3-L39","documentation":"For a Vorbis track the Matroska CodecPrivate starts with a Xiph-lacing header whose first byte is packet-count-minus-1. Vorbis uses exactly 3 header packets (identification, comment, setup), so that count byte must be 2. getAudioDescription rejects any other value because the lacing model assumes three packets.","triggerScenarios":"A Vorbis track whose CodecPrivate[0] !== 2: wrong packet count, corrupted lacing byte, truncated CodecPrivate, or a non-Vorbis stream tagged A_VORBIS.","commonSituations":"Broken muxer output; truncated/corrupted CodecPrivate; legacy or non-standard Vorbis packaging.","solutions":["Re-encode the audio: ffmpeg -i in.webm -c:a libvorbis out.webm.","Verify the Vorbis headers with ffprobe.","Use Mediabunny; try/catch parseMedia()."],"exampleFix":"# re-encode Vorbis audio cleanly\nffmpeg -i in.webm -c:v copy -c:a libvorbis out.webm\n\nawait parseMedia({ src: 'out.webm' });","handlingStrategy":"try-catch","validationCode":"// ffprobe confirms Vorbis headers are intact\n// ffprobe -v error -show_streams in.webm","typeGuard":null,"tryCatchPattern":"try {\n  await parseMedia({ src: 'in.webm' });\n} catch (err) {\n  if (err instanceof Error && /vorbis private data version 2/i.test(err.message)) {\n    // re-encode Vorbis or skip\n  } else throw err;\n}","preventionTips":["Re-encode Vorbis audio with ffmpeg libvorbis for clean headers.","Probe WebM files before parsing.","Use Mediabunny for broader Vorbis packaging support."],"tags":["webm","matroska","media-parser","vorbis","corrupt-file","codec","audio"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}