{"record":{"id":"0fd1bf2bb694a574","repo":"remotion-dev/remotion","slug":"cannot-get-duration-of-vbr-mp3-file-no-frames","errorCode":null,"errorMessage":"Cannot get duration of VBR MP3 file - no frames","messagePattern":"Cannot get duration of VBR MP3 file - no frames","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/mp3/get-duration.ts","lineNumber":15,"sourceCode":"import type {ParserState} from '../../state/parser-state';\nimport {getMpegFrameLength} from './get-frame-length';\nimport type {XingData} from './parse-xing';\nimport {getSamplesPerMpegFrame} from './samples-per-mpeg-file';\n\nexport const getDurationFromMp3Xing = ({\n\txingData,\n\tsamplesPerFrame,\n}: {\n\txingData: XingData;\n\tsamplesPerFrame: number;\n}) => {\n\tconst xingFrames = xingData.numberOfFrames;\n\tif (!xingFrames) {\n\t\tthrow new Error('Cannot get duration of VBR MP3 file - no frames');\n\t}\n\n\tconst {sampleRate} = xingData;\n\tif (!sampleRate) {\n\t\tthrow new Error('Cannot get duration of VBR MP3 file - no sample rate');\n\t}\n\n\tconst xingSamples = xingFrames * samplesPerFrame;\n\treturn xingSamples / sampleRate;\n};\n\nexport const getDurationFromMp3 = (state: ParserState): number | null => {\n\tconst mp3Info = state.mp3.getMp3Info();\n\tconst mp3BitrateInfo = state.mp3.getMp3BitrateInfo();\n\tif (!mp3Info || !mp3BitrateInfo) {\n\t\treturn null;\n\t}\n","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/mp3/get-duration.ts#L1-L33","documentation":"Thrown by `getDurationFromMp3Xing` when computing the duration of a variable-bitrate (VBR) MP3 file from its Xing header, but `xingData.numberOfFrames` is zero or falsy. The Xing/VBR header's frame count field is required to compute duration; without it the calculation is impossible.","triggerScenarios":"An MP3 file with a Xing header where the `numberOfFrames` field is 0 or missing. The `parseXing` function parsed the header successfully but the frame-count bytes were zero, indicating a corrupt or incomplete Xing table of contents.","commonSituations":"Corrupt or truncated MP3 files with a damaged Xing header. Files produced by encoders that write a Xing marker but don't populate the frame count. Files that have been concatenated or re-tagged in ways that corrupt the VBR header region.","solutions":["Re-encode the MP3 file with a standard encoder (e.g., LAME) that writes a complete Xing header.","Try converting the file to CBR MP3 to avoid the VBR/Xing path entirely.","If the file is user-supplied, validate it with an audio tool (e.g., `ffprobe`) before parsing.","Wrap `parseMedia` in a try-catch and fall back to a different file or format."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-validate an MP3 file's Xing header before parsing\nasync function hasValidXingFrames(file: File): Promise<boolean> {\n  const buf = await file.slice(0, 4096).arrayBuffer();\n  const bytes = new Uint8Array(buf);\n  const text = new TextDecoder().decode(bytes);\n  const xingIdx = text.indexOf('Xing');\n  if (xingIdx === -1) return true; // not VBR, no issue\n  // Xing flags + frame count are at xingIdx+4 (flags) and xingIdx+8 (frames)\n  if (xingIdx + 12 > bytes.length) return false;\n  const view = new DataView(buf, xingIdx + 8, 4);\n  return view.getUint32(0) > 0;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await parseMedia({src, fields: {durationInSeconds: true}});\n} catch (e) {\n  if (e instanceof Error && e.message.includes('no frames')) {\n    console.error('The VBR MP3 has a corrupt Xing header with no frame count.');\n    // Re-encode or use a different file\n  }\n  throw e;\n}","preventionTips":["Re-encode VBR MP3 files with LAME to ensure a complete Xing header.","Validate MP3 files with ffprobe before parsing.","Prefer CBR MP3 or AAC/M4A formats for reliable parsing.","Wrap parseMedia in try-catch when handling user-uploaded audio."],"tags":["mp3","vbr","xing-header","corrupt-file","duration"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}