From 1ee4f07714bf256cafd5eecaf0ef27c4ca3f774c Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 6 Feb 2022 21:30:27 -0800 Subject: [PATCH] Add support for the new HA native WebRTC. --- src/card.ts | 1 + src/patches/ha-camera-stream.ts | 72 +++++++++++++++++------------ src/patches/ha-web-rtc-player.ts | 78 ++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 30 deletions(-) create mode 100644 src/patches/ha-web-rtc-player.ts diff --git a/src/card.ts b/src/card.ts index 15709ce0..c6f6fc4d 100644 --- a/src/card.ts +++ b/src/card.ts @@ -65,6 +65,7 @@ import './components/viewer.js'; import './components/thumbnail-carousel.js'; import './patches/ha-camera-stream.js'; import './patches/ha-hls-player.js'; +import './patches/ha-web-rtc-player.ts'; import cardStyle from './scss/card.scss'; import { ResolvedMediaCache } from './resolved-media.js'; diff --git a/src/patches/ha-camera-stream.ts b/src/patches/ha-camera-stream.ts index 54b22bb9..c7f01af5 100644 --- a/src/patches/ha-camera-stream.ts +++ b/src/patches/ha-camera-stream.ts @@ -32,6 +32,9 @@ customElements.whenDefined('ha-camera-stream').then(() => { ? computeObjectId(stateObj.entity_id).replace(/_/g, ' ') : stateObj.attributes.friendly_name || ''; + const STREAM_TYPE_HLS = 'hls'; + const STREAM_TYPE_WEB_RTC = 'web_rtc'; + @customElement('frigate-card-ha-camera-stream') // eslint-disable-next-line @typescript-eslint/no-unused-vars class FrigateCardHaCameraStream extends customElements.get('ha-camera-stream') { @@ -45,7 +48,7 @@ customElements.whenDefined('ha-camera-stream').then(() => { /** * Play the video. */ - public play(): void { + public play(): void { this._playerRef.value?.play(); } @@ -59,7 +62,7 @@ customElements.whenDefined('ha-camera-stream').then(() => { /** * Mute the video. */ - public mute(): void { + public mute(): void { this.muted = true; } @@ -79,33 +82,41 @@ customElements.whenDefined('ha-camera-stream').then(() => { return html``; } - return html` - ${this._shouldRenderMJPEG - ? html` - { - dispatchMediaShowEvent(this, e); - }} - .src=${typeof this._connected == 'undefined' || this._connected - ? computeMJPEGStreamUrl(this.stateObj) - : ''} - .alt=${`Preview of the ${computeStateName(this.stateObj)} camera.`} - /> - ` - : this._url - ? html` - - ` - : ''} - `; + if (this._shouldRenderMJPEG) { + return html` + { + dispatchMediaShowEvent(this, e); + }} + .src=${typeof this._connected == 'undefined' || this._connected + ? computeMJPEGStreamUrl(this.stateObj) + : ''} + .alt=${`Preview of the ${computeStateName(this.stateObj)} camera.`} + /> + `; + } + if (this.stateObj.attributes.frontend_stream_type === STREAM_TYPE_HLS) { + return this._url + ? html` ` + : html``; + } + if (this.stateObj.attributes.frontend_stream_type === STREAM_TYPE_WEB_RTC) { + return html``; + } } static get styles(): CSSResultGroup { @@ -115,7 +126,8 @@ customElements.whenDefined('ha-camera-stream').then(() => { :host { width: 100%; height: 100%; - }` + } + `, ]; } } diff --git a/src/patches/ha-web-rtc-player.ts b/src/patches/ha-web-rtc-player.ts new file mode 100644 index 00000000..e12217b2 --- /dev/null +++ b/src/patches/ha-web-rtc-player.ts @@ -0,0 +1,78 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck + +// ==================================================================== +// ** Keep modifications to this file to a minimum ** +// +// Type checking is disabled since this is a modified copy-and-paste of +// underlying render() function, but the rest of the class source it not +// available as compilation time. +// ==================================================================== + +import { Ref, createRef, ref } from 'lit/directives/ref'; +import { TemplateResult, html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { dispatchErrorMessageEvent, dispatchMediaShowEvent } from '../common.js'; + +customElements.whenDefined('ha-web-rtc-player').then(() => { + @customElement('frigate-card-ha-web-rtc-player') + // eslint-disable-next-line @typescript-eslint/no-unused-vars + class FrigateCardHaWebRtcPlayer extends customElements.get('ha-web-rtc-player') { + protected _videoRef: Ref = createRef(); + + /** + * Play the video. + */ + public play(): void { + this._videoRef.value?.play(); + } + + /** + * Pause the video. + */ + public pause(): void { + this._videoRef.value?.pause(); + } + + /** + * Mute the video. + */ + public mute(): void { + this.muted = true; + } + + /** + * Unmute the video. + */ + public unmute(): void { + this.muted = false; + } + + // ===================================================================================== + // Minor modifications from: + // - https://github.com/home-assistant/frontend/blob/dev/src/components/ha-web-rtc-player.ts + // ===================================================================================== + protected render(): TemplateResult | void { + if (this._error) { + // Use native Frigate card error handling, and attach the entityid to + // clarify which camera the error refers to. + return dispatchErrorMessageEvent( + this, + `${this._error} (${this.entityid})`); + } + return html` + + `; + } + } +});