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

  1. Run the same probe yourself to see the real error: ffmpeg -i yourfile -f s16le -ac 1 -ar 16000 - (read stderr)
  2. Re-encode the input to WAV first: ffmpeg -i input -ac 1 -ar 16000 fixed.wav, then transcribe the WAV
  3. Install/upgrade a full ffmpeg build (apt install ffmpeg / brew install ffmpeg) if a decoder is missing
  4. 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

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.