commaai/openpilot · error · RuntimeError

No camera file for segment {seg_idx}

Error message

No camera file for segment {seg_idx}

What it means

iter_segment_frames() in the clip tool maps global frame indices to route segments (frames_per_seg = fps * 60). When it moves to a new segment whose camera path is missing (index beyond camera_paths or an empty/None entry), it raises instead of skipping. This means the requested start_time/end_time window reaches segments that have no camera file (e.g. qcamera.ts) available.

Source

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

  probe = ffprobe(camera_path)
  stream = probe["streams"][0]
  return stream["width"], stream["height"]


def iter_segment_frames(camera_paths, start_time, end_time, fps=20, use_qcam=False, frame_size: tuple[int, int] | None = None):
  frames_per_seg = fps * 60
  start_frame, end_frame = int(start_time * fps), int(end_time * fps)
  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:

View on GitHub (pinned to 516ec1e682)

Solutions

  1. Clamp end_time to the last segment that actually has a camera file: end_time = min(end_time, len(camera_paths_with_files) * 60)
  2. Filter camera_paths to only existing files and confirm the count covers the requested window before starting
  3. Pass the fps matching the route (default 20) so segment boundary math matches reality

Example fix

# before
end_time = 125.0  # route only has 2 segments (120s) with camera files

# after
n_segs = sum(1 for p in camera_paths if p)
end_time = min(end_time, n_segs * 60.0)
Defensive patterns

Strategy: validation

Validate before calling

last_valid = max(i for i, p in enumerate(camera_paths) if p)
max_time = (last_valid + 1) * 60.0
assert end_time <= max_time, f"end_time {end_time}s exceeds last camera segment at {max_time}s"

Try / catch

try:
    yield from iter_segment_frames(camera_paths, start_time, end_time, fps)
except RuntimeError as e:
    if 'No camera file' in str(e):
        seg = int(str(e).rsplit(' ', 1)[-1])
        raise SystemExit(f"trim clip to segment {seg - 1}: window reaches missing camera data")
    raise

Prevention

When it happens

Trigger: Clipping a time range whose end crosses into a segment index with no camera file listed; camera_paths built from an rlog/segment list where some segments lack qcameras; passing camera_paths shorter than the number of segments spanned by start_time..end_time.

Common situations: Route partially uploaded (later segments missing qcamera.ts); off-by-one in end_time (one second past the last segment); mixing 20fps assumption with a route recorded at a different fps so segment math overshoots.

Related errors


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