Skip to content

Talk to a camera speaker (talkdown) on mobile

NovaVMS mobile can send your voice from the phone’s microphone to a camera’s built-in speaker. Press and hold the Hold to Talk button on the live view; release to stop transmitting. This is the headline mobile-only feature in v1 — the web app does not have talkdown.

Talkdown uses a dedicated audio-only WebRTC PeerConnection, separate from the live-view connection. This separation keeps the live-view RTCP / ICE state clean and lets the mic reconnect independently of the video.

Where the button appears

The Hold to Talk button renders in the bottom-area of the live view, next to the PTZ pad if the camera also has PTZ.

The button only appears when the camera reports supports_backchannel = true. On cameras that do not support backchannel — for example, most consumer-grade Wi-Fi cameras and some older ONVIF Profile S devices — the button is absent, not disabled. The app deliberately does not render a button that would silently fail when held.

If a camera you know to have a speaker (e.g. an LC-TA3R or some Vivotek pairs) does not show the button, ask your admin to override the supports_backchannel capability — the gateway’s auto-probe (3-layer detection) occasionally misses cameras whose backchannel works in practice. See the camera-troubleshooting flow on the web manual.

First time you press the button

The first time you press and hold Hold to Talk on any camera, iOS or Android prompts for microphone permission. NovaVMS uses the OS-level usage strings:

  • iOS: “NovaVMS uses the microphone for talkdown to camera speakers.”
  • Android: the runtime RECORD_AUDIO permission.

Tap Allow. If you tap Don’t Allow, the button enters an error state and shows “Error” instead of “Hold to Talk”. Re-enable in OS Settings → NovaVMS → Microphone.

What the button looks like at each state

StateVisual
IdleGrey circle with mic icon, caption “Hold to Talk”
StartingGrey circle with spinner (negotiating WHIP)
TransmittingRed circle with mic icon + red glow, caption “Transmitting”
ErrorRed-tinted circle, caption “Error”
UnavailableDimmed (when supports_backchannel is false — but the button itself is normally absent in this case)

A medium-impact haptic fires on press-down (matches iOS button-hold feel); a light-impact haptic fires on release.

How transmission works

  1. Press and hold: the app acquires your microphone via getUserMedia({ audio: true }).
  2. The app creates a fresh RTCPeerConnection (separate from the live-view PC) and adds the mic audio track as a sendonly transceiver.
  3. The app posts the WebRTC SDP offer to the cloud WHIP talkdown endpoint (see Phase 8 API reference for the full path) and receives the answer.
  4. The server forwards the audio to the gateway, which sends it to the camera’s backchannel.

The wire codec is Opus end-to-end in v1. The cloud forwards Opus to the gateway, and the gateway forwards Opus to the camera’s RTSP backchannel — Opus → PCMU/PCMA transcode on the gateway is out of scope for v1 (see gateway/internal/onvif/backchannel.go). Cameras whose backchannel speaker only accepts PCMU/PCMA will NOT play talkdown audio until the transcode path ships in a future release. See Troubleshoot mobile for the user-visible symptom (talkdown indicator goes green but no audio at the camera).

When you release the button, the app closes the PC and releases the mic. The next press starts a fresh session.

What you should hear vs. what the camera should hear

  • Through your phone: nothing local — your voice goes one direction (mic → camera). The phone speaker stays quiet. Use Listen on the same camera to monitor the room while transmitting.
  • At the camera: your voice through the camera’s speaker, in roughly half-duplex push-to-talk style (you talk while holding; the camera mic is not opened to your phone).

Why push-to-talk and not open-mic

Talkdown is intentionally push-to-talk (not a continuous open-mic call). Two reasons:

  1. Battery + bandwidth. Holding the mic open means a continuous Opus encode + WHIP session; releasing tears it down. Push-to-talk fits the typical use case (a one-or-two-sentence verbal intervention) without paying that cost.
  2. Background-audio policy. The app is built without the FOREGROUND_SERVICE_MEDIA_PLAYBACK permission on Android — it cannot continue audio (in either direction) while another app is in front. Push-to-talk while held is compatible with that policy; a continuous open-mic call would require a foreground service and a Play Console media-playback declaration.

If transmission fails

  • The button shows “Error” immediately on press: microphone permission was denied. Re-enable in OS Settings → NovaVMS → Microphone.
  • The button stays on “Starting” and never turns red: the WHIP request failed. Possible causes:
    • HTTP 403 — your role is not operator or higher. Viewer-role users cannot transmit talkdown.
    • HTTP 404 — the cloud could not route to a gateway for this camera (offline gateway).
    • HTTP 5xx — server error. Try again in a few seconds.
  • “Transmitting” lights up but the camera speaker is silent:
    • The camera might only accept PCMU/PCMA on its backchannel and the Opus→PCMU transcode is not yet implemented for that camera. Confirm by playing a known-good talkdown sentence on a different camera in the same site (e.g. a Tapo C200 or LC-TA3R confirmed in production).
    • The camera’s speaker may be physically muted on-device, or the audio_enabled toggle is off in Camera settings → Audio.
  • Talkdown works on Wi-Fi but not on LTE: WebRTC ICE may be selecting a TURN relay that your carrier filters. Less common; try Wi-Fi to confirm.

See Troubleshoot mobile for more recovery steps.

What talkdown does NOT do (v1)

  • No two-way duplex call. Talkdown is one-direction (phone-mic → camera-speaker). The camera’s mic does NOT come back to your phone over the talkdown session — use Listen on the live view for that.
  • No background talkdown. Releasing the button is the only stop. Switching apps while holding releases.
  • No multi-camera broadcast. One camera at a time.
  • No volume control. Mic level is the OS-default (loud-side-of-normal). Speak at conversational level near the phone.