Skip to content

feat(multi-camera): pick cameras and record them one at a time - #200

Merged
gbradham merged 1 commit into
mainfrom
feat/multicam-per-camera-record
Oct 19, 2026
Merged

gbradham merged 1 commit into
mainfrom
feat/multicam-per-camera-record

Conversation

@gbradham

Copy link
Copy Markdown
Member

What

The Multi-Camera window can now switch individual cameras off, and record each camera on its own.

Each row of the status table has a checkbox and its own Record / Stop button.

  • Unticking a camera disconnects it. That frees its USB bandwidth, and it is neither previewed nor recorded. The row stays, greyed out as "off", so it can be ticked back on. The choice is remembered in ~/.glider/camera_selection.json.
  • The camera panel's Multi-Camera mode leaves switched-off cameras out too, so an experiment run does not record them. If camera 0 is off, the first camera that is on becomes primary.
  • A camera that is recording cannot be unticked, because disconnecting it would cut its file off unfinished.
  • A row's button starts or stops that camera alone; the others carry on. Each row shows that camera's own take time.
  • Record All adds the cameras not yet recording to a run already going (before, it did nothing during a run). Stop All stops every camera.

How

  • MultiVideoRecorder.start_camera() / stop_camera(). A run lasts from the first camera starting until the last one stops. A stopped camera's file is drained, closed and frame-rate-corrected on a worker thread, so the other previews keep running. stop() waits for any file still saving, and returns every file of the run, including cameras stopped earlier.
  • A restart within the same second writes _take2 instead of opening the first take's file over the top (filenames carry a one-second timestamp).
  • enumerate_cameras(skip_indices=...): Refresh Cameras no longer probes cameras that are already streaming. Those can refuse a second open, read as missing, and end the scan before a switched-off camera further up.
  • set_camera_labels is now accepted mid-run. Files already open keep their names, but a camera started later uses its new one.
  • Smaller fixes in the same window:
    • Cameras are listed in number order (cam_2 before cam_10).
    • Row buttons fill their cells; the tool theme's item padding was clipping them.
    • The preview tiles show each camera's frame rate instead of "-- FPS".

Testing

  • New unit tests for the recorder, status table, selection store and window, using spec'd mocks. Each fix was checked by reintroducing the bug and confirming the tests fail.
  • Full suite: 5910 passed, 17 skipped. ruff and black are clean.
  • End to end against five simulated cameras. Everything from CameraManager up is real: the Windows connect path, capture threads, the window clicked with a real mouse, the recorder, and real .mp4 files. Only cv2.VideoCapture is replaced. The simulated cameras run at their own rates (one at 25 fps), can only be opened once at a time, one ignores the requested size (800x600), and there is a gap in the numbering. All 53 checks passed, including:
    • Every recorded file contains only its own camera's frames, with no dropped or repeated frames.
    • The other previews kept running (longest gap 36 ms) while a camera's file was finished.
    • _take2 was written on a same-second restart.
    • The selection persisted into a new window and into the camera panel.
  • This run found two of the bugs fixed above: a row stuck on "Saving…" for up to half a second after its file was done, and the clipped row buttons.

Not yet tested on real cameras. Reconnecting a real DirectShow camera after switching it off and on, and real USB bandwidth, need a run on the rig.

Each row of the Multi-Camera window's status table now has a checkbox and
its own Record/Stop button.

- Unticking a camera disconnects it (frees its USB bandwidth), so it is
  neither previewed nor recorded. The choice persists in
  ~/.glider/camera_selection.json, and the camera panel's Multi-Camera mode
  honours it too, so an experiment run does not record those cameras. A
  camera with a file open cannot be switched off.
- A row's button starts or stops that camera alone. MultiVideoRecorder gains
  start_camera()/stop_camera(); a run lasts from the first camera starting
  to the last one stopping. A stopped camera's file is finished on a worker
  thread so the other previews keep running; stop() waits for any still
  saving and returns every file of the run.
- Record All adds the cameras not yet recording to a run already going
  instead of doing nothing; Stop All stops every camera.
- Each camera has its own take time. A restart within the same second
  writes _take2 rather than overwriting the first take.
- Enumeration can skip indices already open, so Refresh Cameras does not
  probe streaming cameras (which can refuse a second open and end the scan
  early).
- Cameras are listed in number order (cam_2 before cam_10), row buttons
  fill their cells under the tool theme's item padding, and the preview
  tiles show each camera's fps.
@gbradham
gbradham merged commit 3ab22f1 into main Oct 19, 2026
4 checks passed
@gbradham
gbradham deleted the feat/multicam-per-camera-record branch October 19, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant