Skip to content

Fix media_player.play_media by using go2rtc /api/ffmpeg#942

Open
mayerwin wants to merge 1 commit intoAlexxIT:masterfrom
mayerwin:fix/media-player-codec-autoneg
Open

Fix media_player.play_media by using go2rtc /api/ffmpeg#942
mayerwin wants to merge 1 commit intoAlexxIT:masterfrom
mayerwin:fix/media-player-codec-autoneg

Conversation

@mayerwin
Copy link
Copy Markdown

Problem

media_player.play_media on platform: webrtc fails with HTTP 500 "can't find consumer" on many real setups (reported across multiple issues by Reolink / Amcrest / Dahua users trying to use the entity for TTS or alarm playback).

Root cause: the integration sends

POST /api/streams?dst=<stream>&src=ffmpeg:<url>#audio=<user_codec>#input=file

so the ffmpeg producer advertises one hardcoded codec (whatever the user put in audio:). If the camera's backchannel does not accept that exact codec — e.g. the user configures audio: pcma but the Reolink backchannel negotiates PCMU/8000 — go2rtc's matchMedia returns false and stream.Play returns "can't find consumer" at play.go#L108. The error message is misleading; its actual meaning is "no codec match between producer offer and backchannel consumer."

Fix

Switch async_play_media to go2rtc's /api/ffmpeg helper. Per ffmpeg/api.go#L27, this endpoint hardcodes #audio=auto on the ffmpeg producer, so the producer advertises the full codec menu (Opus 48k, L16/PCMA/PCMU at 16k then 8k, AAC) and go2rtc picks whichever the camera's backchannel actually supports.

Both endpoints ultimately call the same stream.Play(src)/api/ffmpeg just builds src with audio=auto instead of passing through whatever the caller supplied, making it a strict superset for async_play_media's use case.

audio: config option is now Optional (kept for backwards compat so existing YAML still validates) but unused — codec selection is entirely auto-negotiated by go2rtc. The old #-fragment source string is gone, which incidentally removes some subtle URL-encoding risk for file= values that contain query params.

Diff summary

  • custom_components/webrtc/media_player.py: schema audio Required → Optional; async_play_media uses utils.api_ffmpeg with params={dst, file}.
  • custom_components/webrtc/utils.py: api_ffmpeg() helper mirroring api_streams().

Total: +15 / -10 lines.

Verified on

  • Reolink camera with ONVIF source (port 8000), go2rtc 1.9.9. Before: consistent HTTP 500 "can't find consumer" on every codec value tried (pcma, pcma/8000, pcmu, pcmu/8000, opus, opus/48000/2, aac). After: media_player.play_media with TTS (Piper via HA media_source) and with a plain mp3 URL both succeed within ~5s, audio plays at the camera speaker.
  • Inspection of go2rtc's producers/consumers state after a successful /api/ffmpeg call confirmed the newly-added consumer advertises audio, sendonly, PCMU/8000 — i.e. the camera's actual preferred codec, not the pcma we'd been forcing.

Compatibility

Existing configs with audio: pcma (or similar) continue to validate and work — the field is now simply ignored. No user-facing breaking change.

The existing implementation POSTs to /api/streams with a hardcoded audio
codec from the user's `audio:` config:

    src = f"ffmpeg:{media_id}#audio={self.audio}#input=file"

When the codec doesn't match what the camera's backchannel advertises
(e.g. `audio: pcma` in config vs PCMU/8000 on a Reolink), go2rtc's
stream.Play falls through matchMedia and returns HTTP 500
"can't find consumer" — a misleading error whose actual meaning is
"no codec match between producer offer and backchannel consumer".

/api/ffmpeg is a go2rtc helper that wraps the same stream.Play path
but forces `audio=auto` on the ffmpeg producer, so the producer
advertises the full codec menu (Opus 48k, L16/PCMA/PCMU at 16k then 8k,
AAC) and matchMedia picks whichever the camera actually supports. For
the WebRTC integration's async_play_media use case, /api/ffmpeg is a
strict superset of /api/streams.

`audio:` is now Optional (kept for backwards compat with existing
configs, but unused). The src-fragment string and its URL-encoding
pitfalls are gone.
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