{"record":{"id":"37d6094633368795","repo":"openai/whisper","slug":"failed-to-load-audio-e-stderr-decode","errorCode":null,"errorMessage":"Failed to load audio: {e.stderr.decode()}","messagePattern":"Failed to load audio: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"whisper/audio.py","lineNumber":60,"sourceCode":"    # This launches a subprocess to decode audio while down-mixing\n    # and resampling as necessary.  Requires the ffmpeg CLI in PATH.\n    # fmt: off\n    cmd = [\n        \"ffmpeg\",\n        \"-nostdin\",\n        \"-threads\", \"0\",\n        \"-i\", file,\n        \"-f\", \"s16le\",\n        \"-ac\", \"1\",\n        \"-acodec\", \"pcm_s16le\",\n        \"-ar\", str(sr),\n        \"-\"\n    ]\n    # fmt: on\n    try:\n        out = run(cmd, capture_output=True, check=True).stdout\n    except CalledProcessError as e:\n        raise RuntimeError(f\"Failed to load audio: {e.stderr.decode()}\") from e\n\n    return np.frombuffer(out, np.int16).flatten().astype(np.float32) / 32768.0\n\n\ndef pad_or_trim(array, length: int = N_SAMPLES, *, axis: int = -1):\n    \"\"\"\n    Pad or trim the audio array to N_SAMPLES, as expected by the encoder.\n    \"\"\"\n    if torch.is_tensor(array):\n        if array.shape[axis] > length:\n            array = array.index_select(\n                dim=axis, index=torch.arange(length, device=array.device)\n            )\n\n        if array.shape[axis] < length:\n            pad_widths = [(0, 0)] * array.ndim\n            pad_widths[axis] = (0, length - array.shape[axis])\n            array = F.pad(array, [pad for sizes in pad_widths[::-1] for pad in sizes])","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/openai/whisper/blob/5f86d1d86363843179951550570367b37c5d6f78/whisper/audio.py#L42-L78","documentation":"whisper.load_audio()/transcribe() shells out to ffmpeg (pcm_s16le at 16 kHz) with check=True. When ffmpeg exits non-zero, the subprocess CalledProcessError is re-raised as RuntimeError with ffmpeg's stderr text, which usually names the real cause (unknown format, invalid data, no such file is a Python-level error, permission denied, unsupported codec).","triggerScenarios":"transcribe() on a file ffmpeg cannot decode: a non-audio file renamed to .mp3, a DRM-protected/odd-container video, a 0-byte file, a truncated upload, or a codec build of ffmpeg lacking the needed decoder; also output to a non-writable pipe. Any whisper CLI invocation on such a file hits this.","commonSituations":"Web-scraped or user-uploaded media that is actually HTML/error pages; .m4a files on a minimal ffmpeg build without AAC; files on network mounts that return I/O errors; headless containers with a stripped-down ffmpeg.","solutions":["Run the same probe yourself to see the real error: ffmpeg -i yourfile -f s16le -ac 1 -ar 16000 - (read stderr)","Re-encode the input to WAV first: ffmpeg -i input -ac 1 -ar 16000 fixed.wav, then transcribe the WAV","Install/upgrade a full ffmpeg build (apt install ffmpeg / brew install ffmpeg) if a decoder is missing","Discard or repair corrupt/truncated source files (e.g. re-download, ffprobe -v error check)"],"exampleFix":"# before\nwhisper.transcribe(model, \"interview.mp3\")  # RuntimeError: Failed to load audio: ...\n\n# after\nimport subprocess, whisper\nsubprocess.run([\"ffmpeg\", \"-i\", \"interview.mp3\", \"-ac\", \"1\", \"-ar\", \"16000\", \"interview.wav\"], check=True)\nwhisper.transcribe(model, \"interview.wav\")","handlingStrategy":"try-catch","validationCode":"import subprocess\n\ndef audio_is_readable(path: str) -> bool:\n    r = subprocess.run([\"ffmpeg\", \"-v\", \"error\", \"-i\", path, \"-f\", \"null\", \"-\"], capture_output=True)\n    return r.returncode == 0","typeGuard":null,"tryCatchPattern":"try:\n    result = whisper.transcribe(model, path)\nexcept RuntimeError as e:\n    if \"Failed to load audio\" in str(e):\n        # convert to wav, repair, or skip this file; log e for ffmpeg's stderr detail\n        raise","preventionTips":["Validate uploads server-side with ffprobe before queuing them for transcription","Test the exact ffmpeg invocation (16 kHz mono s16le) in your deployment image","Pin a full-featured ffmpeg in Dockerfiles rather than distro minimal builds"],"tags":["audio","ffmpeg","subprocess","file-format"],"backgroundTag":null,"analyzedSha":"5f86d1d86363843179951550570367b37c5d6f78","analyzedAt":"2026-08-14T18:53:59.547Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}