hacksider/Deep-Live-Cam · error · ValueError

Invalid device index {device_index}. Available devices: {len

Error message

Invalid device index {device_index}. Available devices: {len(devices)}

What it means

ValueError raised in the VideoCapture constructor (modules/video_capture.py, Windows-only path) when the requested device_index is >= the number of cameras returned by pygrabber FilterGraph.get_input_devices() (DirectShow enumeration). It is a fail-fast check at construction time so a bogus index doesn't reach OpenCV, where it would fail more obscurely. Note the message embeds len(devices) but the validation is done in __init__ before any capture starts.

Source

Thrown at modules/video_capture.py:32

    def __init__(self, device_index: int):
        self.device_index = device_index
        self.frame_callback = None
        self._current_frame = None
        self._frame_ready = threading.Event()
        self.is_running = False
        self.cap = None
        # Actual values reported by the camera after configuration
        self.actual_width: int = 0
        self.actual_height: int = 0
        self.actual_fps: float = 0.0

        # Initialize Windows-specific components if on Windows
        if platform.system() == "Windows":
            self.graph = FilterGraph()
            # Verify device exists
            devices = self.graph.get_input_devices()
            if self.device_index >= len(devices):
                raise ValueError(
                    f"Invalid device index {device_index}. Available devices: {len(devices)}"
                )

    def start(self, width: int = 960, height: int = 540, fps: int = 60) -> bool:
        """Initialize and start video capture"""
        try:
            if platform.system() == "Windows":
                # device_index comes from pygrabber.FilterGraph (DirectShow
                # enumeration), so open with DSHOW first to preserve mapping.
                # MSMF and DirectShow enumerate cameras in different orders, so
                # opening MSMF with a DSHOW index silently selects the wrong
                # camera. MSMF/ANY remain as fallbacks for cameras DSHOW can't
                # open.
                #
                # Pass codec + resolution + fps as construction params (OpenCV
                # 4.6+). DSHOW locks the pixel format at open time and ignores
                # later cap.set(CAP_PROP_FOURCC, ...) — without this, DSHOW
                # falls back to uncompressed YUYV at 1080p, which is USB-

View on GitHub (pinned to 987f6b392b)

Solutions

  1. Enumerate devices with the same method and pick a valid index dynamically: from pygrabber.dshow_graph import FilterGraph; n = len(FilterGraph().get_input_devices()); use 0 <= index < n.
  2. If the camera is genuinely present but not listed, enable it in Windows privacy settings (Settings > Privacy > Camera) and confirm its driver exposes a DirectShow filter; update or switch the driver if MSMF-only.
  3. Persist device selection by name rather than index where possible, resolving the name to an index at startup, since enumeration order changes across reboots/hot-plugs.
  4. If no camera is attached, connect one or point the app at a video file/stream instead.

Example fix

# before
cap = VideoCapture(device_index=1)  # single camera attached -> ValueError

# after
from pygrabber.dshow_graph import FilterGraph
names = FilterGraph().get_input_devices()
if not names:
    raise SystemExit("No DirectShow cameras found")
device_index = names.index("My Webcam") if "My Webcam" in names else 0
cap = VideoCapture(device_index=device_index)
Defensive patterns

Strategy: validation

Validate before calling

from pygrabber.dshow_graph import FilterGraph  # Windows only
devices = FilterGraph().get_input_devices()
if not devices:
    raise SystemExit("No DirectShow cameras found")
if not (0 <= device_index < len(devices)):
    device_index = 0  # or surface a device picker with `devices` names
cap = VideoCapture(device_index=device_index)

Type guard

def is_valid_device_index(index: int) -> bool:
    if index < 0:
        return False
    try:
        from pygrabber.dshow_graph import FilterGraph
        return index < len(FilterGraph().get_input_devices())
    except Exception:
        return False  # enumeration unavailable; let VideoCapture decide

Try / catch

try:
    cap = VideoCapture(device_index=i)
except ValueError as e:
    if "Invalid device index" in str(e):
        # re-enumerate and pick a live camera instead of a hardcoded index
        i = 0
        cap = VideoCapture(device_index=i)
    else:
        raise

Prevention

When it happens

Trigger: Constructing VideoCapture with an index >= camera count on Windows (e.g. index 1 with a single camera, index 0 with none); a camera being unplugged or disabled between enumeration in the UI and object construction; an index saved from a previous session when the machine had more cameras; virtual cameras not exposing a DirectShow filter so they aren't counted.

Common situations: Hardcoded camera index from a different machine; device disconnected/privacy-killed (Windows camera privacy toggle hides it from DirectShow); hot-plug races; the camera existing but its driver not registering a DirectShow capture filter (some modern drivers are MSMF-only), making the DSHOW device list shorter than expected.

Related errors


AI-assisted analysis of hacksider/Deep-Live-Cam@987f6b392b (2026-08-14). Data as JSON: /api/errors/30a778d663ab64af. Report an issue: GitHub.