Panniantong/Agent-Reach · error · TranscribeError

ffprobe could not parse a valid audio duration

Error message

ffprobe could not parse a valid audio duration

What it means

Raised by _probe_audio_duration() in agent_reach/transcribe.py when ffprobe exits 0 but its stdout cannot be parsed as a float (float() raises TypeError/ValueError). The command requests only format=duration, so a missing or malformed duration line (e.g. 'N/A' or empty output for streams without duration metadata) hits this path. from None keeps the traceback clean.

Source

Thrown at agent_reach/transcribe.py:134

            "ffprobe timed out while reading audio duration "
            f"after {FFPROBE_TIMEOUT_SECONDS}s"
        ) from None
    except OSError as exc:
        raise TranscribeError(
            f"ffprobe could not read audio duration: {exc}"
        ) from exc

    if proc.returncode != 0:
        detail = proc.stderr.strip()[:300] or "unknown ffprobe error"
        raise TranscribeError(
            f"ffprobe failed while reading audio duration: {detail}"
        )

    raw_duration = proc.stdout.strip()
    try:
        duration = float(raw_duration)
    except (TypeError, ValueError):
        raise TranscribeError(
            "ffprobe could not parse a valid audio duration"
        ) from None
    if not math.isfinite(duration) or duration <= 0:
        raise TranscribeError(
            "ffprobe could not parse a valid positive audio duration"
        )
    return duration


def _require_duration_within_budget(path: Path) -> float:
    """Reject audio that cannot fit within the bounded chunk budget."""
    duration = _probe_audio_duration(path)
    if duration > MAX_AUDIO_SECONDS:
        max_minutes = MAX_AUDIO_SECONDS // 60
        raise TranscribeError(
            f"audio duration exceeds safety limit of {max_minutes} minutes"
        )
    return duration

View on GitHub (pinned to 93ae1d18c3)

Solutions

  1. Re-mux the file so duration is computed: ffmpeg -i in.wav -c copy out.m4a, then retry
  2. Strip duration-less headers by re-encoding: ffmpeg -i in.webm out.m4a
  3. Check manually: ffprobe -v error -show_entries format=duration -i file

Example fix

# before: duration prints 'N/A' -> TranscribeError
transcribe_audio(Path('live_stream.webm'))

# after
subprocess.run(['ffmpeg', '-i', 'live_stream.webm', '-c', 'copy', 'fixed.m4a'])
transcribe_audio(Path('fixed.m4a'))
Defensive patterns

Strategy: validation

Validate before calling

out = subprocess.run(['ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', '-i', str(path)], capture_output=True, text=True).stdout.strip()
try:
    d = float(out)
except ValueError:
    d = None  # re-mux before calling transcribe

Type guard

def has_parsable_duration(path) -> bool:
    out = subprocess.run(['ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', '-i', str(path)], capture_output=True, text=True).stdout.strip()
    try:
        float(out); return True
    except ValueError:
        return False

Try / catch

from agent_reach.transcribe import TranscribeError
try:
    transcribe_audio(path)
except TranscribeError as e:
    if 'parse a valid audio duration' in str(e):
        transcribe_audio(remux_to_m4a(path))
    else:
        raise

Prevention

When it happens

Trigger: Live-recorded streams, some WAV/PCM files, or freshly created media where the container lacks a duration field, making ffprobe print 'N/A' or nothing.

Common situations: Microphone recordings produced by tools that omit header duration; pipe-sourced media; unusual containers ffprobe reports duration-less.

Related errors


AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14). Data as JSON: /api/errors/c4b23df19d8831b9. Report an issue: GitHub.