Skip to content

Add PTZ passthrough and audio advertisement for virtual Onvif devices - #28

Open
coolham123 wants to merge 3 commits into
daniela-hase:mainfrom
coolham123:ptz-audio-passthrough
Open

Add PTZ passthrough and audio advertisement for virtual Onvif devices#28
coolham123 wants to merge 3 commits into
daniela-hase:mainfrom
coolham123:ptz-audio-passthrough

Conversation

@coolham123

Copy link
Copy Markdown

Overview

This PR adds two optional, config-gated features to the virtual Onvif devices. Both are off by default — configs without the new keys produce byte-identical profiles to current main.

1. PTZ passthrough (ptz: config key)

Upstream is Profile S only, so clients like Unifi Protect see a fixed camera even when the real camera supports PTZ. With a ptz: block on a camera entry:

  • The virtual device advertises a PTZ service in GetCapabilities and GetServices, and embeds the camera's real PTZConfiguration into the virtual profiles.
  • /onvif/ptz_service on the virtual device is a raw SOAP relay to the camera's real PTZ endpoint — not a SOAP server. Clients sign PTZ requests with WS-Security UsernameToken digests computed from the camera's own credentials, so the relayed envelope authenticates on the camera as-is. The relay stores no client credentials.
  • The only body transformation is rewriting the virtual profile tokens (main_stream/sub_stream) to the camera's real PTZ-capable profile token. All other tokens originate from relayed camera responses and pass through valid.
  • The camera's PTZ profile and endpoint are discovered once at startup (startPtz()), using credentials from the config only for that discovery step. Failures are logged but don't kill the server.
    ptz:
      port: 8000               # Onvif port of the real camera
      username: <camera user>  # used once at startup for profile discovery
      password: <camera pass>
      # profileToken: '001'    # optional override

2. Audio advertisement (audio: config key)

Audio (e.g. AAC) already flows through the RTSP TCP proxy, but the virtual profiles contained no audio configurations, so clients assumed there is no microphone. With audio: true (or an object overriding encoding/bitrate/samplerate, default AAC 64 kbps / 16 kHz):

  • Profiles gain AudioSourceConfiguration and AudioEncoderConfiguration in schema-correct element order.
  • New media service handlers: GetAudioSources, GetAudioSourceConfigurations, GetAudioEncoderConfigurations, GetAudioEncoderConfiguration, GetAudioEncoderConfigurationOptions (empty results when audio is not configured).

Testing

Deployed and verified against a dual-lens Reolink camera adopted as two virtual cameras in Unifi Protect: PTZ control works end-to-end through the relay, and audio is detected and recorded after adoption. Also regression-checked that entries without ptz:/audio: produce profiles identical to upstream. One operational note for Protect users: it probes PTZ/audio capabilities only at adoption, so existing cameras must be re-adopted to pick up the new capabilities.

README documentation for both keys is included.

🤖 Generated with Claude Code

coolham123 and others added 3 commits July 11, 2026 23:51
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 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