fix(camera): share one ffmpeg connection for /api/camera/stream #91

Open
Pavulon87 wants to merge 1 commits from Pavulon87/KX-Bridge-Release:fix/camera-fix into nightly
Contributor

Description

This PR adds support for multiple concurrent MJPEG stream consumers by introducing a shared MJPEG streaming pipeline.

Previously, every request to /api/camera/stream spawned a separate ffmpeg process and opened a new connection to the printer. Since the printer only supports a very limited number of concurrent camera clients, this could lead to HTTP 429 errors and intermittent "stream unavailable" issues when multiple clients (dashboard, Moonraker-compatible clients, plugins, etc.) accessed the camera simultaneously.

The new implementation introduces a dedicated ffmpeg process that generates a shared MJPEG stream, which is then distributed to all connected /api/camera/stream subscribers. This approach provides:

  • A single printer connection per output type instead of one per HTTP client.
  • Support for multiple simultaneous MJPEG consumers.
  • Continued support for multiple simultaneous H.264 consumers.
  • Reduced ffmpeg process creation and improved resource usage.
  • More reliable camera streaming with fewer connection conflicts.

This implementation was developed with assistance from Claude AI and has been tested locally for several days. It appears to work well in my testing, but I'd appreciate additional review and testing since there may still be edge cases that I haven't encountered.

Closes #90

Type

  • Bug fix
  • Feature
  • Documentation
  • Refactoring

Tested with

  • OrcaSlicer Version: 2.5.0-dev-kx1
  • Printer: Kobra X
  • Moonraker/Klipper Version:

Checklist

  • Tests added/updated
  • CHANGELOG.md updated
  • No debug code included
## Description This PR adds support for multiple concurrent MJPEG stream consumers by introducing a shared MJPEG streaming pipeline. Previously, every request to `/api/camera/stream` spawned a separate ffmpeg process and opened a new connection to the printer. Since the printer only supports a very limited number of concurrent camera clients, this could lead to HTTP 429 errors and intermittent "stream unavailable" issues when multiple clients (dashboard, Moonraker-compatible clients, plugins, etc.) accessed the camera simultaneously. The new implementation introduces a dedicated ffmpeg process that generates a shared MJPEG stream, which is then distributed to all connected `/api/camera/stream` subscribers. This approach provides: - A single printer connection per output type instead of one per HTTP client. - Support for multiple simultaneous MJPEG consumers. - Continued support for multiple simultaneous H.264 consumers. - Reduced ffmpeg process creation and improved resource usage. - More reliable camera streaming with fewer connection conflicts. This implementation was developed with assistance from Claude AI and has been tested locally for several days. It appears to work well in my testing, but I'd appreciate additional review and testing since there may still be edge cases that I haven't encountered. ## Related Issue Closes #90 ## Type - [ ] Bug fix - [X] Feature - [ ] Documentation - [ ] Refactoring ## Tested with - OrcaSlicer Version: 2.5.0-dev-kx1 - Printer: Kobra X - Moonraker/Klipper Version: ## Checklist - [ ] Tests added/updated - [ ] CHANGELOG.md updated - [X] No debug code included
Pavulon87 added 1 commit 2026-07-16 15:03:46 +02:00
fix(camera): share one ffmpeg connection for /api/camera/stream
Some checks failed
PR Check / lint-and-test (pull_request) Has been cancelled
ba59b47c27
Owner

Thanks for this, @Pavulon87 — the shared-fanout approach for /api/camera/stream is exactly right and matches the existing handle_camera_h264 pattern well. Couldn't merge the PR branch directly though: the diff contains unresolved git conflict markers (<<<<<<< HEAD / ======= / >>>>>>> c185c76) inside handle_camera_stream, most likely from a local rebase against nightly that never got resolved before pushing — merging as-is would have left literal conflict markers in the Python source.

I pulled the fix in manually instead: new mjpeg_subscribers fanout channel in CameraCache (same shape as the h264 channel), plus the two related fixes you found (the ensure_running() race where two callers could both see "no process yet" and spawn duplicate ffmpeg processes, and reset() not waking a task stuck in its backoff sleep). Verified locally that two concurrent /api/camera/stream clients now share a single ffmpeg process instead of one each.

Closing this in favor of the manually-integrated version, but the credit for the fix and the race-condition finds is yours. Thanks for the thorough writeup and testing notes!

Thanks for this, @Pavulon87 — the shared-fanout approach for /api/camera/stream is exactly right and matches the existing handle_camera_h264 pattern well. Couldn't merge the PR branch directly though: the diff contains unresolved git conflict markers (`<<<<<<< HEAD` / `=======` / `>>>>>>> c185c76`) inside handle_camera_stream, most likely from a local rebase against nightly that never got resolved before pushing — merging as-is would have left literal conflict markers in the Python source. I pulled the fix in manually instead: new `mjpeg_subscribers` fanout channel in `CameraCache` (same shape as the h264 channel), plus the two related fixes you found (the `ensure_running()` race where two callers could both see "no process yet" and spawn duplicate ffmpeg processes, and `reset()` not waking a task stuck in its backoff sleep). Verified locally that two concurrent `/api/camera/stream` clients now share a single ffmpeg process instead of one each. Closing this in favor of the manually-integrated version, but the credit for the fix and the race-condition finds is yours. Thanks for the thorough writeup and testing notes!
Some checks failed
PR Check / lint-and-test (pull_request) Has been cancelled
This pull request has changes conflicting with the target branch.
  • kobrax_moonraker_bridge.py
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u fix/camera-fix:Pavulon87-fix/camera-fix
git checkout Pavulon87-fix/camera-fix
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: viewit/KX-Bridge-Release#91
No description provided.