unslothai/unsloth · error · SttAudioDecodeError

Could not decode the audio.

Error message

Could not decode the audio.

What it means

Raised inside the PyAV decode loop when the opened container exposes no audio stream (container.streams.audio is empty). The bytes opened fine as a media container, but there is no audio track to transcribe — e.g. a video-only file or an empty/misidentified file.

Source

Thrown at studio/backend/core/inference/stt_sidecar.py:1106

    )
    # Group frames before resampling so short clips need one resampler call
    # rather than one per codec frame.
    fifo = av.audio.fifo.AudioFifo()

    def write_frame(frame) -> None:
        nonlocal sample_count
        array = frame.to_ndarray()
        sample_count += array.size
        if sample_count > max_samples:
            max_minutes = _MAX_AUDIO_SECONDS // 60
            unit = "minute" if max_minutes == 1 else "minutes"
            raise SttAudioTooLongError(f"Audio must be {max_minutes} {unit} or shorter.")
        raw_buffer.write(array)

    try:
        with av.open(io.BytesIO(audio), mode = "r", metadata_errors = "ignore") as container:
            if not container.streams.audio:
                raise SttAudioDecodeError("Could not decode the audio.")
            frames = iter(container.decode(audio = 0))
            while True:
                try:
                    frame = next(frames)
                except StopIteration:
                    break
                except InvalidDataError:
                    # Skip a corrupt frame rather than fail the whole transcription.
                    continue
                if cancel_event is not None and cancel_event.is_set():
                    raise SttTranscriptionCancelledError("Transcription cancelled.")
                frame.pts = None
                fifo.write(frame)
                if fifo.samples >= 500000:
                    for resampled in resampler.resample(fifo.read()):
                        write_frame(resampled)
            if fifo.samples > 0:
                for resampled in resampler.resample(fifo.read()):

View on GitHub (pinned to 203007d190)

Solutions

  1. Inspect the file client-side (ffprobe or the browser's audio element) and reject non-audio inputs before upload.
  2. Check the file size is non-zero and the MIME type is an audio type before calling transcribe.
  3. If you expect audio from a recorder, verify the recorder actually produced samples (e.g. MediaRecorder ondataavailable events had data).

Example fix

// before
stt.transcribe(file_bytes);  // video-only mp4 -> SttAudioDecodeError
// after
if not has_audio_stream(file_bytes):  # ffprobe-style probe
    return error("File has no audio track")
stt.transcribe(file_bytes)
Defensive patterns

Strategy: validation

Validate before calling

import av, io
with av.open(io.BytesIO(audio), mode="r", metadata_errors="ignore") as c:
    if not c.streams.audio:
        reject("no audio track")

Try / catch

try:
    stt.transcribe(audio)
except SttAudioDecodeError as e:
    if "no audio" in context: reject_upload()  # distinguish via upstream probe
    else: raise

Prevention

When it happens

Trigger: Calling transcribe() with a video file that has no audio track, a zero-byte or truncated file that PyAV still opens, or a container whose streams are all video/data.

Common situations: Drag-and-drop upload accepting video files; a recorder producing an empty webm when permission was denied; a file with the wrong extension that FFmpeg probes as a non-audio container.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/06424fdf08badca3. Report an issue: GitHub.