fix: Improve 2-way audio detection (#2293)

- For Frigate cameras, you must be running at least [integration
v5.12.0](https://github.com/blakeblackshear/frigate-hass-integration/releases/tag/v5.12.0).
 - Closes: #2191 

Includes a significant refactor of cameras, and the introduction of a
`2-way-audio` capability that is dynamically fetched from `go2rtc`. One
gotcha is if you previously had a substream with 2-way audio, you may
need to modify

```yaml
 - camera_entity: camera.foo
    capabilities:
      disable_except:
        - substream
```

... to ...

```yaml
 - camera_entity: camera.foo
    capabilities:
      disable_except:
        - substream
        - 2-way-audio
```
This commit is contained in:
Dermot Duffy
2025-12-20 13:06:09 -08:00
committed by GitHub
parent 588ed6c98a
commit 1e821f09c6
47 changed files with 2240 additions and 958 deletions
+30 -2
View File
@@ -17,7 +17,11 @@ import { VideoMediaPlayerController } from '../components-lib/media-player/video
import { renderMessage } from '../components/message.js';
import liveHAComponentsStyle from '../scss/live-ha-components.scss';
import { MediaPlayer, MediaPlayerController } from '../types.js';
import { mayHaveAudio } from '../utils/audio.js';
import {
addAudioTracksMuteStateListener,
AudioTracksMuteStateCleanup,
hasAudio,
} from '../utils/audio.js';
import {
hideMediaControlsTemporarily,
MEDIA_LOAD_CONTROLS_HIDE_SECONDS,
@@ -44,6 +48,8 @@ customElements.whenDefined('ha-web-rtc-player').then(() => {
() => this.controls,
);
protected _audioTracksMuteStateCleanup: AudioTracksMuteStateCleanup = null;
public async getMediaPlayerController(): Promise<MediaPlayerController | null> {
return this._mediaPlayerController;
}
@@ -132,10 +138,32 @@ customElements.whenDefined('ha-web-rtc-player').then(() => {
mediaPlayerController: this._mediaPlayerController,
capabilities: {
supportsPause: true,
hasAudio: mayHaveAudio(this._videoEl),
hasAudio: hasAudio(this._videoEl, this._peerConnection),
},
technology: ['webrtc'],
});
// Listen for audio track mute/unmute changes and re-dispatch
this._audioTracksMuteStateCleanup?.();
this._audioTracksMuteStateCleanup = addAudioTracksMuteStateListener(
this._peerConnection,
() => {
dispatchMediaLoadedEvent(this, this._videoEl, {
mediaPlayerController: this._mediaPlayerController,
capabilities: {
supportsPause: true,
hasAudio: hasAudio(this._videoEl, this._peerConnection),
},
technology: ['webrtc'],
});
},
);
}
private _cleanUp(): void {
super._cleanUp();
this._audioTracksMuteStateCleanup?.();
this._audioTracksMuteStateCleanup = null;
}
static get styles(): CSSResultGroup {