Skip to content

Prefer the go2rtc restream for HomeKit camera streams - #175605

Draft
RaHehl wants to merge 5 commits into
home-assistant:devfrom
RaHehl:homekit-go2rtc-stream-source
Draft

Prefer the go2rtc restream for HomeKit camera streams#175605
RaHehl wants to merge 5 commits into
home-assistant:devfrom
RaHehl:homekit-go2rtc-stream-source

Conversation

@RaHehl

@RaHehl RaHehl commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Breaking change

Proposed change

Depends on #175600 — until that merges, this draft's diff includes both changes; only the HomeKit commit is new here.

Make HomeKit consume camera streams through the go2rtc restream instead of opening a connection to the camera per streaming session:

  • _async_get_stream_source prefers go2rtc.async_get_rtsp_stream_url; when it returns None (go2rtc absent, user-provided server, unsupported source) the previous raw-source path is used unchanged.
  • A manually configured stream_source option keeps absolute priority, so users pointing HomeKit at a substream or external restream are unaffected.
  • go2rtc is added to HomeKit's after_dependencies.

Today each HomeKit live session spawns an ffmpeg pulling directly from the camera (up to stream_count, default 3, per camera) — on top of go2rtc's own upstream for dashboard WebRTC. With this change all HomeKit sessions, dashboard WebRTC views and go2rtc snapshots share go2rtc's single upstream connection per camera; ffmpeg keeps its per-session role (SRTP toward the Apple device, Opus audio, scaling) with a local, already-primed input.

Validated live against a UniFi Protect camera: real HomeKit sessions each consumed rtsp://127.0.0.1:18554/<identifier>, parallel consumers resulted in exactly one upstream connection to the camera, and go2rtc released it after the last consumer ended. (Dev-machine validation of the managed-server path; only the docker environment detection was bypassed, everything behind it is unmodified production code.)

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copilot AI review requested due to automatic review settings July 4, 2026 11:11
@home-assistant home-assistant Bot added cla-signed has-tests integration: go2rtc integration: homekit new-feature Top 100 Integration is ranked within the top 100 by usage Top 200 Integration is ranked within the top 200 by usage Top 50 Integration is ranked within the top 50 by usage labels Jul 4, 2026
@home-assistant

home-assistant Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Hey there @home-assistant/core, mind taking a look at this pull request as it has been labeled with an integration (go2rtc) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of go2rtc can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant mark-draft Mark the pull request as draft.
  • @home-assistant ready-for-review Remove the draft status from the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign go2rtc Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant update-branch Update the pull request branch with the base branch.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) on the pull request.

@home-assistant

home-assistant Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Hey there @bdraco, mind taking a look at this pull request as it has been labeled with an integration (homekit) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of homekit can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant mark-draft Mark the pull request as draft.
  • @home-assistant ready-for-review Remove the draft status from the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign homekit Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant update-branch Update the pull request branch with the base branch.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) on the pull request.

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 updates HomeKit camera streaming to prefer consuming streams via the Home Assistant–managed go2rtc RTSP restream, reducing per-session upstream connections to the camera.

Changes:

  • Prefer go2rtc’s managed RTSP restream URL in HomeKit camera streaming when available, with fallback to the camera’s raw stream source.
  • Expose a go2rtc helper (async_get_rtsp_stream_url) and a shared managed RTSP port constant to keep server config and consumers in sync.
  • Add/extend tests covering the new helper behavior and HomeKit’s selection logic, and ensure HomeKit loads after go2rtc.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
homeassistant/components/homekit/type_cameras.py Prefer go2rtc RTSP restream URL before falling back to the raw camera stream source.
homeassistant/components/homekit/manifest.json Ensure HomeKit is set up after go2rtc so the restream preference can be used when available.
homeassistant/components/go2rtc/__init__.py Add a public helper to return the managed RTSP restream URL and make the stream registration method public.
homeassistant/components/go2rtc/const.py Introduce HA_MANAGED_RTSP_PORT constant for the managed RTSP endpoint.
homeassistant/components/go2rtc/server.py Use the managed RTSP port constant in the generated go2rtc server config.
tests/components/go2rtc/test_init.py Add test coverage for the new RTSP restream helper and its fallback/None cases.
tests/components/homekit/test_type_cameras.py Add tests verifying HomeKit prefers go2rtc restream and that configured stream sources bypass go2rtc.

Comment thread tests/components/homekit/test_type_cameras.py
Copilot AI review requested due to automatic review settings July 9, 2026 08:48

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread homeassistant/components/go2rtc/__init__.py
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 9, 2026 08:54

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

@bluetoothbot

Copy link
Copy Markdown

PR Review — Prefer the go2rtc restream for HomeKit camera streams

Solid, well-scoped change that routes HomeKit camera streams through the shared go2rtc restream. Merge-ready with minor nits.

Strengths:

  • The helper is genuinely defensive: manual stream_source keeps absolute priority, and every failure mode (go2rtc absent, external/unmanaged server, camera off/unknown, unsupported source) is caught and degrades to the existing raw-source path.

  • Correctly reuses get_camera_identifier, whose quote(..., safe=...) makes the RTSP path URL-safe — no injection via entity/unique_id.

  • after_dependencies + the module-level import are consistent with hassfest rules; the port literal was properly extracted into HA_MANAGED_RTSP_PORT to keep server config and consumer in sync.

  • Good test coverage of the helper's None branches and HomeKit's prefer/skip selection logic.

  • Host 127.0.0.1 is still duplicated between the helper and server.py (suggestion).

  • Selection-time fallback only; no runtime fallback if the restream registers but later fails (suggestion — matches WebRTC behavior, worth confirming).


🟢 Suggestions

1. Host `127.0.0.1` literal duplicated across modules
homeassistant/components/go2rtc/__init__.py:231

The returned URL hardcodes rtsp://127.0.0.1:{HA_MANAGED_RTSP_PORT}/..., while server.py independently builds the listen address as f"127.0.0.1:{HA_MANAGED_RTSP_PORT}".

The port was correctly extracted into HA_MANAGED_RTSP_PORT to keep the two in sync, but the host half is still a bare literal in two places. If the managed RTSP bind host ever changes (e.g. to bind a different interface), the two can silently drift and the URL HomeKit dials would no longer match where go2rtc listens.

  • Consider a shared HA_MANAGED_RTSP_HOST (or a small URL builder) in const.py so both the server config and this helper derive from one source, mirroring how HA_MANAGED_URL is already centralized.

Minor — not blocking.

return f"rtsp://127.0.0.1:{HA_MANAGED_RTSP_PORT}/{get_camera_identifier(camera)}"

Checklist

  • Failure paths degrade to raw source (error handling)
  • No injection via RTSP identifier
  • Constants shared to prevent config/consumer drift — suggestion #1
  • Behavior change scoped and reversible
  • Test coverage for new branches

Silent Failure Analysis

🟡 **MEDIUM** — fallback that hides failures (debug-only logging)
homeassistant/components/go2rtc/__init__.py:225-229

Risk: When registering the camera stream with go2rtc fails persistently (e.g. camera misconfiguration or a go2rtc client error), the intended single-upstream multiplexing optimization is silently abandoned and HomeKit falls back to per-session raw camera connections, but the only trace is a DEBUG log that operators will not see in production.

    try:
        camera = get_camera_from_entity_id(hass, entity_id)
        await provider.async_update_stream_source(camera)
    except (HomeAssistantError, Go2RtcClientError) as err:
        _LOGGER.debug("Not providing RTSP restream URL for %s: %s", entity_id, err)
        return None

Fix: Consider logging the Go2RtcClientError branch at a higher level (info/warning) since a persistent restream failure is a real operational regression, while keeping the expected-unavailable HomeAssistantError cases at debug.


Automated review by Kōan (Claude) HEAD=2bb0f97 4 min 16s

@bluetoothbot bluetoothbot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking issues found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed has-tests integration: go2rtc integration: homekit new-feature Quality Scale: internal Quality Scale: No score Top 50 Integration is ranked within the top 50 by usage Top 100 Integration is ranked within the top 100 by usage Top 200 Integration is ranked within the top 200 by usage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants