commaai/openpilot · error · RuntimeError

ffmpeg failed: {result.stderr.decode()}

Error message

ffmpeg failed: {result.stderr.decode()}

What it means

When decoding a qcamera segment with the ffmpeg subprocess (stdin raw file, stdout rawvideo nv12), a non-zero exit code triggers this RuntimeError carrying ffmpeg's stderr. The qcamera file is an HEVC stream inside a ts container; failures usually mean ffmpeg cannot parse the container, was built without the needed demuxer/decoder, or got truncated input via the pipe.

Source

Thrown at openpilot/tools/clip/run.py:160

  current_seg: int = -1
  get_frame: Callable[[int], np.ndarray] | None = None

  for global_idx in range(start_frame, end_frame):
    seg_idx, local_idx = global_idx // frames_per_seg, global_idx % frames_per_seg

    if seg_idx != current_seg:
      current_seg = seg_idx
      path = camera_paths[seg_idx] if seg_idx < len(camera_paths) else None
      if not path:
        raise RuntimeError(f"No camera file for segment {seg_idx}")

      if use_qcam:
        w, h = frame_size or get_frame_dimensions(path)
        with FileReader(path) as f:
          result = subprocess.run(["ffmpeg", "-v", "quiet", "-i", "-", "-f", "rawvideo", "-pix_fmt", "nv12", "-"],
                                  input=f.read(), capture_output=True)
        if result.returncode != 0:
          raise RuntimeError(f"ffmpeg failed: {result.stderr.decode()}")
        seg_frames = np.frombuffer(result.stdout, dtype=np.uint8).reshape(-1, w * h * 3 // 2)
        get_frame = seg_frames.__getitem__
      else:
        get_frame = FrameReader(path, pix_fmt="nv12").get

    assert get_frame is not None
    yield global_idx, get_frame(local_idx)


class FrameQueue:
  def __init__(self, camera_paths, start_time, end_time, fps=20, prefetch_count=60, use_qcam=False):
    # Probe first valid camera file for dimensions
    first_path = next((p for p in camera_paths if p), None)
    if not first_path:
      raise RuntimeError("No valid camera paths")
    self.frame_w, self.frame_h = get_frame_dimensions(first_path)

    self._queue, self._stop, self._error = queue.Queue(maxsize=prefetch_count), threading.Event(), None

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Run the same command manually to see the real error: ffmpeg -i <qcamera.ts> -f rawvideo -pix_fmt nv12 out.yuv
  2. Install a full ffmpeg build with HEVC support (e.g. ffmpeg from ffmpeg.org, not a codec-stripped distro package)
  3. Re-download the qcamera file if it is truncated/corrupt (verify size against the server listing)
  4. If stderr is empty due to -v quiet, temporarily raise verbosity to '-v error' to capture the cause

Example fix

# before
result = subprocess.run(["ffmpeg", "-v", "quiet", ...])

# after (surface the real cause)
result = subprocess.run(["ffmpeg", "-v", "error", ...])
if result.returncode != 0:
    raise RuntimeError(f"ffmpeg failed: {result.stderr.decode(errors='replace') or 'no stderr (check ffmpeg build has hevc)'}")
Defensive patterns

Strategy: try-catch

Validate before calling

import shutil, subprocess
assert shutil.which('ffmpeg'), 'ffmpeg not on PATH'
probe = subprocess.run(['ffmpeg', '-decoders'], capture_output=True, text=True)
assert 'hevc' in probe.stdout.lower(), 'system ffmpeg cannot decode HEVC qcamera streams'

Try / catch

try:
    result = subprocess.run(cmd, input=f.read(), capture_output=True)
except RuntimeError as e:
    msg = str(e)
    if 'ffmpeg failed' in msg:
        if 'decode' in msg or not msg.strip('ffmpeg failed: '):
            raise SystemExit('install a full ffmpeg build with HEVC support')
        raise SystemExit(f'qcamera decode failed: {msg}')
    raise

Prevention

When it happens

Trigger: use_qcam=True path in iter_segment_frames(): subprocess ffmpeg exits non-zero because the .ts is corrupt/truncated; system ffmpeg lacks hevc decoding (--disable-decoders builds, distro 'ffmpeg-free' packages); piping the whole file via stdin when the container needs seekable input.

Common situations: Partially downloaded qcamera.ts; Fedora-style ffmpeg builds without libde265/hevc; old ffmpeg versions with poor hevc-in-mpegts demuxing; empty stderr because '-v quiet' suppressed diagnostics so the message looks empty.

Related errors


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/8abe445152c73ab3. Report an issue: GitHub.