Skip to content

Start improving high-throughput multi-camera recording path and diagnostics#85

Draft
C-Achard wants to merge 11 commits into
cy/preserve-mono-supportfrom
cy/improve-encoding-speed
Draft

Start improving high-throughput multi-camera recording path and diagnostics#85
C-Achard wants to merge 11 commits into
cy/preserve-mono-supportfrom
cy/improve-encoding-speed

Conversation

@C-Achard

Copy link
Copy Markdown
Contributor

Summary

Improves multi-camera recording behavior under high-throughput conditions by separating recording frame delivery from the heavier GUI/DLC processing path, adding clearer recorder backlog/queue diagnostics, and introducing an optional faster encoding mode for supported FFmpeg codecs.
This is a first quick remediation to the deeper architectural concern requiring the recording to be moved closer to camera SDK frame grabbing.

Main changes

  1. Adds a dedicated recording_frame_ready(camera_id, frame, timestamp) signal for full-rate recording frames.
  2. Recording frames are now handled by a lean recording-only path instead of _on_multi_frame_processing_ready().
  3. Recording-frame emission is disabled by default and only enabled while recording is active.
  4. Adds a "Use faster encoding" parameters checkbox in the Recording panel.
    For libx264/libx265, this applies:
    • Preset ultrafast
    • Tune zerolatency
  5. Centralizes WriteGear/FFmpeg option generation in RecordingSettings.writegear_options().
  6. Adds recorder better diagnostics
  7. Updates multi-camera recorder summaries to aggregate queue/backlog/writer throughput across cameras.
  8. Switches Basler grabbing to GrabStrategy_OneByOne so recording-oriented acquisition does not silently prefer only the latest image.
  9. Reduces noisy Basler trigger debug logs behind an explicit DEBUG_TRIGGER_LOGS flag.
  10. Adds profiling artifacts to .gitignore.
  11. Updates tests for the new recording signal, fast encoding options, recorder stats formatting, and multi-camera recording aggregation.

What this improves

This makes it easier to diagnose when the recorder is falling behind before drops occur. Previously, dropped = 0 could hide the fact that recorder queues were filling. The new stats expose that state directly through queue fill and backlog.
The fast encoding option also provides a user-controlled way to trade compression efficiency/file size for higher recording throughput.

Not solved yet

  • Recording frames still pass through the Qt/main-window path before reaching VideoRecorder.write().
  • The actual encoder write is already threaded, but the producer/enqueue side can still add main-thread pressure at very high frame rates.
  • This PR does not introduce a dedicated recording router thread or direct camera-worker-to-recorder routing.
  • This does not guarantee full-rate recording for extreme cases, but makes bottlenecks more visible and improves slightly the x264 fast path at the cost of worst file size.

Testing

Added/updated unit tests for:

  • Recording-frame signal enable/disable behavior
  • Recording overlay routing
  • RecordingSettings.writegear_options()
  • Fast encoding option propagation
  • Recorder queue/backlog stats formatting
  • Multi-recorder stats aggregation

  • Note before merge: disable debug logging

C-Achard added 6 commits June 26, 2026 15:21
Switch Basler camera startup to `pylon.GrabStrategy_OneByOne` instead of `LatestImageOnly`, and update the nearby identity-persistence comment for clarity.
Add ignore patterns for generated profiling files (`profile*.svg`, `scalene*.json`, and `scalene*.html`) so local performance analysis outputs are not accidentally committed.
Introduce a new `profiling` optional dependency group in `pyproject.toml` and include `scalene` so profiling tools can be installed independently from test and framework extras.
Adds a dedicated full-rate `recording_frame_ready` signal path so recording is decoupled from the inference/display frame flow, reducing processing overhead during capture. The GUI now exposes a fast-encoding toggle and persists it into recording settings, and recorder startup passes codec-specific writer options through to `VideoRecorder`.

Recording telemetry was expanded to report enqueued vs written frames, writer FPS, queue fill against buffer size, backlog, and drops, improving visibility into recording throughput and pressure.
Turns on timing logging for multi-camera worker, recorder, and Basler backend diagnostics. Recording settings now include a `fast_encoding` flag, with `writegear_options` made more robust for missing/invalid FPS and optional low-latency FFmpeg options (`ultrafast` + `zerolatency`) for x264/x265. Recorder stats were expanded with buffer capacity awareness (`buffer_size`), derived backlog/fill-ratio properties, and richer formatted output showing queue fill and backlog.
Updates test fixtures and unit tests around recording flow changes: FakeVideoRecorder now mirrors new constructor/runtime fields, Basler fake includes one-by-one grab strategy, and GUI/controller tests validate recording-frame emission gating plus overlay recording via `_on_recording_frame_ready`. Tests also cover `RecordingSettings.writegear_options` (including fast x264 options and FPS fallback), RecordingManager writer option wiring, and richer recorder stats formatting/aggregation with backlog and queue capacity output.
@C-Achard C-Achard self-assigned this Jun 26, 2026
@C-Achard C-Achard added enhancement New feature or request camera Related to cameras and camera backends config Related to user configs, oading, saving, etc labels Jun 26, 2026
@C-Achard C-Achard added this to the Trigger config feature milestone Jun 26, 2026
@C-Achard C-Achard requested a review from Copilot June 29, 2026 09:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves multi-camera recording robustness and diagnostics under high-throughput load by adding a dedicated full-rate recording signal/path, enhancing recorder backlog/queue reporting, and introducing optional “fast encoding” FFmpeg parameters via centralized WriteGear option generation.

Changes:

  • Added a dedicated recording_frame_ready(camera_id, frame, timestamp) signal and routed recording through a leaner handler in the main window.
  • Expanded recorder stats to include buffer capacity, queue fill, and backlog; updated aggregated multi-camera summaries accordingly.
  • Added RecordingSettings.writegear_options() (incl. optional “fast encoding”), updated Basler grab strategy, and extended tests/ignores/extras to support these features.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/utils/test_stats.py Updates recorder stats formatting tests for backlog/buffer-capacity output.
tests/test_config.py Adds unit tests for RecordingSettings.writegear_options() and fast-encoding behavior.
tests/services/test_multicam_controller.py Adds test for recording-frame emission enable/disable behavior.
tests/gui/test_rec_manager.py Updates multi-recorder summary aggregation tests and checks writer options propagation.
tests/gui/test_pose_overlay.py Updates overlay-recording test to use the new recording-frame handler.
tests/conftest.py Extends FakeVideoRecorder to accept new constructor args (buffer/writer options).
tests/cameras/backends/conftest.py Updates Basler fake to include GrabStrategy_OneByOne.
pyproject.toml Adds optional “profiling” dependency group.
dlclivegui/utils/stats.py Adds recorder backlog/fill helpers and extends recorder stats formatting output.
dlclivegui/services/video_recorder.py Adds writer_options, improves logging, and adjusts stats computation.
dlclivegui/services/multi_camera_controller.py Adds recording_frame_ready signal and togglable emission during capture.
dlclivegui/gui/recording_manager.py Centralizes writer option generation and expands stats aggregation/summaries.
dlclivegui/gui/main_window.py Adds “fast encoding” UI toggle, connects new recording signal, and routes recording via lean handler.
dlclivegui/config.py Adds fast_encoding to recording settings; changes timing-log defaults.
dlclivegui/cameras/backends/basler_backend.py Switches Basler grab strategy and gates trigger debug logging behind a flag.
.gitignore Ignores common profiling artifacts (scalene/profile outputs).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/test_stats.py Outdated
Comment thread dlclivegui/services/video_recorder.py Outdated
Comment thread dlclivegui/services/video_recorder.py Outdated
Comment thread dlclivegui/services/video_recorder.py
Comment thread dlclivegui/config.py Outdated
Comment thread dlclivegui/gui/main_window.py Outdated
Comment thread dlclivegui/gui/main_window.py
C-Achard added 5 commits June 29, 2026 16:23
Wire the fast encoding checkbox to QSettings so its value is restored on startup and saved when toggled. This adds typed get/set helpers for `recording/fast_encoding` in `DLCLiveGUISettingsStore`, updates `main_window` to prefer persisted values over config defaults, and includes a roundtrip unit test for the new setting. It also removes an obsolete commented-out recording block in the frame processing path.
Remove defensive `hasattr` checks when connecting recording settings signals in `DLCLiveMainWindow`. The widgets are expected to exist, so connecting unconditionally avoids silently skipping persistence and recording path preview updates if an expected widget is missing or renamed.
Turns off multi-camera, recorder, and Basler timing logs by default to reduce debug noise in normal runs. Also cleans up stale priority wording in main window comments, updates VideoRecorder docstrings to reflect `writer_options`, and fixes stats tests to import `RecorderStats` from `dlclivegui.utils.stats`.
Ensure ffmpeg writer defaults (`-input_framerate`, `-vcodec`, `-crf`) are always applied, even when custom writer options are provided, while still allowing overrides via `writer_options`. Also improve recorder stats by estimating `buffer_seconds` from average or last frame latency when write FPS is unavailable, avoiding zero/underreported buffer duration.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

camera Related to cameras and camera backends config Related to user configs, oading, saving, etc enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants