Skip to content

Capture an LED from several cameras at once (--device 1,2) - #91

Draft
gunicsba wants to merge 2 commits into
TheMariday:mainfrom
gunicsba:multi-camera
Draft

gunicsba wants to merge 2 commits into
TheMariday:mainfrom
gunicsba:multi-camera

Conversation

@gunicsba

@gunicsba gunicsba commented Oct 19, 2026 •

Copy link
Copy Markdown

--device now takes a comma separated list of cameras, and every LED is lit once and looked for in all of them at the same time:

marimapper wled --server 192.168.1.50 --device 1,2
marimapper_check_camera --device 1,192.168.1.20:4747     # webcams and network cameras can be mixed

Each camera is its own view of the scan, numbered in the order they are listed. The reconstruction already treats every view as a separate camera position sharing one camera model, so with identical cameras a scan gives you one view per camera for the price of one.

This builds on #90 (it uses its address parsing), so the first commit here is that pull request's. The change for this PR is the second commit.

What changes

  • find_leds and enable_and_find_leds look for one LED in every camera. The single camera functions are now thin wrappers around them, so there is one code path.
    • A camera that always sees some light is skipped for that LED (after the usual 3 seconds), the other cameras carry on.
    • The response time that feeds the timeout counts the slowest camera that saw the LED. A camera that never sees an LED would otherwise make the timeout grow by 50% every time.
  • Every camera finishes its own view, as done, or deleted if it moved or saw nothing. The scanner waits for all of them and moves on by one view per camera. A scan counts as successful if at least one view is. A camera that detected nothing now ends its view too (deleted); before, nothing was sent in that case, so the scanner would have kept waiting.
  • open_cameras opens every webcam with the same capture method and checks that each delivers a picture. Methods number the cameras differently (on Windows, DirectShow and Media Foundation list them in a different order), and the old per camera fallback could mix the two, so a list like 2,3 opened the wrong camera for the second entry. If no method works the error says why.
  • The 2D files were named after the second, so two cameras finishing together overwrote each other's file. A suffix is added when the name is taken.
  • marimapper_check_camera opens a window per camera, and the README has a short section on it.

Testing

  • Unit tests use a fake scene (cameras, an LED backend) to check which camera sees which LED, a camera that is blind or always sees light, the timeout not inflating, one result per camera, and the file names. open_cameras is tested with a fake OpenCV, including the case where one method can open only some of the cameras. The scanner side is tested with a scripted queue of events. All pass, flake8 is clean, and the existing tests pass.
  • On real hardware: three webcams at once (two identical USB webcams on separate ports and a laptop webcam), four scans with the WLED backend. That gave 10 views, and the live reconstruction placed 191 of 200 LEDs. One of the scans produced two files in the same second, which is the naming case above.

Notes

🤖 Generated with Claude Code

gunicsba and others added 2 commits October 19, 2026 12:03
--device now also accepts the address of a network camera, so an Android phone
running DroidCam can be used without a PC client:

    marimapper_check_camera --device 192.168.1.20:4747

A bare host or host:port is treated as DroidCam (default port 4747, stream path
/video); a path can be added, and full http:// or rtsp:// URLs are passed through.
Plain camera indexes work exactly as before.

Network streams are opened with the FFmpeg backend with a 5 second open/read
timeout (an unreachable address used to block for far longer) and a one frame
buffer. Exposure and focus can't be set over a network stream; the existing
"failed to set exposure" warning covers that.

Tests parse the address forms and read frames from a local MJPEG server that
behaves like the DroidCam app.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
--device takes a comma separated list of cameras, e.g. --device 1,2 or --device
1,192.168.1.20:4747, and every led is then switched on once and looked for in all of them
at the same time. Each camera is its own view of the scan, numbered in the order they are
listed, so a scan with two cameras gives two views and the reconstruction (which already
treats every view as a separate camera position sharing one camera model) uses them all.

- find_leds and enable_and_find_leds look in every camera for one led. The single camera
  functions are now thin wrappers around them. A camera that always sees light is skipped
  for that led, and a camera that never sees the led doesn't make the timeout grow.
- Each camera finishes its own view: done, or deleted if it moved or saw nothing. The
  scanner waits for all of them, and moves on by one view per camera.
- Webcams are numbered differently by each capture method (DirectShow and Media Foundation
  on Windows), so open_cameras opens all of them with the same method, checks that each
  gets a picture, and says what went wrong if none works, rather than mixing methods.
- The 2D files were named by the second, so cameras finishing together overwrote each
  other's file. They now get a suffix when the name is taken.
- marimapper_check_camera opens one window per camera.

Needs the address parsing from the DroidCam pull request.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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