openai/whisper · error · RuntimeError
Failed to load audio: {e.stderr.decode()}
Error message
Failed to load audio: {e.stderr.decode()} What it means
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).
Source
Thrown at whisper/audio.py:60
# This launches a subprocess to decode audio while down-mixing
# and resampling as necessary. Requires the ffmpeg CLI in PATH.
# fmt: off
cmd = [
"ffmpeg",
"-nostdin",
"-threads", "0",
"-i", file,
"-f", "s16le",
"-ac", "1",
"-acodec", "pcm_s16le",
"-ar", str(sr),
"-"
]
# fmt: on
try:
out = run(cmd, capture_output=True, check=True).stdout
except CalledProcessError as e:
raise RuntimeError(f"Failed to load audio: {e.stderr.decode()}") from e
return np.frombuffer(out, np.int16).flatten().astype(np.float32) / 32768.0
def pad_or_trim(array, length: int = N_SAMPLES, *, axis: int = -1):
"""
Pad or trim the audio array to N_SAMPLES, as expected by the encoder.
"""
if torch.is_tensor(array):
if array.shape[axis] > length:
array = array.index_select(
dim=axis, index=torch.arange(length, device=array.device)
)
if array.shape[axis] < length:
pad_widths = [(0, 0)] * array.ndim
pad_widths[axis] = (0, length - array.shape[axis])
array = F.pad(array, [pad for sizes in pad_widths[::-1] for pad in sizes])View on GitHub (pinned to 5f86d1d863)
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)
Example fix
# before whisper.transcribe(model, "interview.mp3") # RuntimeError: Failed to load audio: ... # after import subprocess, whisper subprocess.run(["ffmpeg", "-i", "interview.mp3", "-ac", "1", "-ar", "16000", "interview.wav"], check=True) whisper.transcribe(model, "interview.wav")
Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess
def audio_is_readable(path: str) -> bool:
r = subprocess.run(["ffmpeg", "-v", "error", "-i", path, "-f", "null", "-"], capture_output=True)
return r.returncode == 0 Try / catch
try:
result = whisper.transcribe(model, path)
except RuntimeError as e:
if "Failed to load audio" in str(e):
# convert to wav, repair, or skip this file; log e for ffmpeg's stderr detail
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
AI-assisted analysis of openai/whisper@5f86d1d863 (2026-08-14).
Data as JSON: /api/errors/37d6094633368795.
Report an issue: GitHub.