I encountered a Linux camera identity mismatch with two USB cameras that advertise the same real device name. The browser preview could show one physical camera while the saved camera_index selected the other for recording.
This is on current main, commit c0ec4e930c71e2b562272058166ed4c338041e7e.
Environment and observed result
- Ubuntu 22.04.5 LTS, Firefox (Snap), local LeLab installation.
- Two UVC USB cameras with the same advertised name,
icspring camera: icspring camer, plus a laptop camera.
- The two USB capture devices were
/dev/video0 and /dev/video4 in this session.
- A configured camera had
camera_index: 4, while inspecting the browser's open device handle showed that its preview was capturing /dev/video0.
No recording session was started to diagnose this; the mismatch was between the visible preview, the open device handle and the saved recording configuration.
Reproduction
- Connect two USB cameras with identical advertised names.
- Configure a camera and enable its browser preview.
- Rescan available cameras while the preview is holding a device. On this setup, the busy device could not be opened by OpenCV and disappeared from backend discovery.
- Compare the preview's physical camera with its saved OpenCV index.
_linux_cameras() discovers devices by opening them. useAvailableCameras then greedily matches backend names against browser labels. A busy device disappearing from that list, combined with duplicate real names, can make the remaining index match the wrong browser device. Merely returning real names does not make this association unique.
Expected: discovery should retain connected cameras even while they are in use, and a preview and its recording configuration should refer to the same physical device without relying on a unique display name.
Relationship to previous work
I found #12, #16 and the naming fix in #26, as well as the backend-preview discussion in #35. This case persists with real but identical names. #66 already provides backend frames during recording; the proposal below concerns configuration/teleoperation previews and consistent camera identity before a recording or inference session starts.
Working prototype for discussion
I preserved the locally tested changes in a fork branch (comparison). I would appreciate feedback on the approach before opening a PR:
- Enumerate Linux capture devices through sysfs without opening them.
- Save a stable
/dev/v4l/by-id/… path, or a physical USB-port path when no by-id alias exists.
- Serve Linux previews from the backend using that same path, and forward it to LeRobot for recording/inference. A missing saved path fails instead of silently selecting another numeric index.
- Release preview capture handles, with acknowledgement and a bounded wait, before allowing recording/inference to start. Keep the existing recording-frame feed.
- Retain the existing browser-preview approach for other platforms.
The prototype uses sequential JPEG requests rather than a new streaming dependency. It includes camera ownership and cleanup regression tests. I re-saved the local camera entries with stable paths; automatic migration of existing browser-ID configurations is not included. The by-path fallback follows the USB port, so moving such a camera to another port can require reselection.
Validation and limits
- 96 focused Python tests and all 23 frontend tests passed; the production frontend build succeeded.
- Both real cameras produced simultaneous previews and remained discoverable while open. Preview handles released cleanly.
- Both cameras also opened through LeRobot's OpenCV camera driver at the requested 640×480, 30 fps mode using those same paths.
- Both feeds were confirmed visible in the updated LeLab UI.
- Recording/inference handoff was tested with fake operation handlers; no physical recording, policy execution or robot movement was part of this verification.
- Windows/macOS hardware was not tested.
Would this Linux backend-preview/stable-path approach fit the project's direction, or would you prefer a narrower change? I can split the contribution according to the preferred scope.
I encountered a Linux camera identity mismatch with two USB cameras that advertise the same real device name. The browser preview could show one physical camera while the saved
camera_indexselected the other for recording.This is on current
main, commitc0ec4e930c71e2b562272058166ed4c338041e7e.Environment and observed result
icspring camera: icspring camer, plus a laptop camera./dev/video0and/dev/video4in this session.camera_index: 4, while inspecting the browser's open device handle showed that its preview was capturing/dev/video0.No recording session was started to diagnose this; the mismatch was between the visible preview, the open device handle and the saved recording configuration.
Reproduction
_linux_cameras()discovers devices by opening them.useAvailableCamerasthen greedily matches backend names against browser labels. A busy device disappearing from that list, combined with duplicate real names, can make the remaining index match the wrong browser device. Merely returning real names does not make this association unique.Expected: discovery should retain connected cameras even while they are in use, and a preview and its recording configuration should refer to the same physical device without relying on a unique display name.
Relationship to previous work
I found #12, #16 and the naming fix in #26, as well as the backend-preview discussion in #35. This case persists with real but identical names. #66 already provides backend frames during recording; the proposal below concerns configuration/teleoperation previews and consistent camera identity before a recording or inference session starts.
Working prototype for discussion
I preserved the locally tested changes in a fork branch (comparison). I would appreciate feedback on the approach before opening a PR:
/dev/v4l/by-id/…path, or a physical USB-port path when no by-id alias exists.The prototype uses sequential JPEG requests rather than a new streaming dependency. It includes camera ownership and cleanup regression tests. I re-saved the local camera entries with stable paths; automatic migration of existing browser-ID configurations is not included. The by-path fallback follows the USB port, so moving such a camera to another port can require reselection.
Validation and limits
Would this Linux backend-preview/stable-path approach fit the project's direction, or would you prefer a narrower change? I can split the contribution according to the preferred scope.