unslothai/unsloth · error · SttAudioTooLongError
Audio must be {max_minutes} {unit} or shorter.
Error message
Audio must be {max_minutes} {unit} or shorter. What it means
Raised during frame-by-frame decoding when the cumulative resampled sample count exceeds _MAX_AUDIO_SECONDS * _TARGET_SAMPLE_RATE, i.e. the clip is longer than the hard cap (shown in whole minutes). The cap is enforced as frames arrive so long uploads are rejected early rather than after a full decode.
Source
Thrown at studio/backend/core/inference/stt_sidecar.py:1100
sample_count = 0
raw_buffer = io.BytesIO()
resampler = av.audio.resampler.AudioResampler(
format = "s16",
layout = "mono",
rate = _TARGET_SAMPLE_RATE,
)
# 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 = NoneView on GitHub (pinned to 203007d190)
Solutions
- Trim or split the audio client-side into segments within the cap (the engine windows at 30s internally, but the total input cap still applies).
- If self-hosting and longer input is acceptable, raise _MAX_AUDIO_SECONDS consciously — it exists to bound memory/CPU of decode.
- Show the limit in the upload UI so users pre-split long files.
Example fix
// before
stt.transcribe(hour_long_mp3); // SttAudioTooLongError
// after
for chunk in split_audio(hour_long_mp3, max_seconds=(_MAX_AUDIO_SECONDS - 5)):
results.append(stt.transcribe(chunk)) Defensive patterns
Strategy: validation
Validate before calling
MAX_S = _MAX_AUDIO_SECONDS # import from stt_sidecar
if estimate_duration_seconds(audio_path) > MAX_S - 5: # small safety margin
split_or_reject(audio_path) Try / catch
try:
text = stt.transcribe(audio)
except SttAudioTooLongError as e:
show_user(str(e)); suggest_splitting() Prevention
- Enforce a client-side duration limit matching _MAX_AUDIO_SECONDS
- Cap recorder recording time in the UI
- Split long media into per-chunk transcribe() calls and join texts
When it happens
Trigger: Uploading audio longer than the cap (e.g. >10 min at 16 kHz if _MAX_AUDIO_SECONDS is 600) to transcribe(); the count is checked inside write_frame after each resampled batch, so any decode whose cumulative samples exceed max_samples raises.
Common situations: Users dictating or uploading long recordings (meetings, podcasts); clients that concatenate clips before sending; changed constants after an upgrade lowering the cap.
Related errors
- Could not decode the audio.
- MiniMax-H3 reference audio runs up to {H3_REF_VIDEO_MAX_SECO
- load error: {p.get('error')}
- model load did not reach ready within {timeout_s}s
- load error: {p.get('error')}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/be2ba13a8bcad1ba.
Report an issue: GitHub.