Improve video user experience by loading camera thumbnail as initial video background image (#13943)

This commit is contained in:
Allen Porter 2022-10-03 09:38:25 -07:00 committed by GitHub
parent 66bfdb6d12
commit 9c923e45c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 5 deletions

View File

@ -15,6 +15,7 @@ import {
CAMERA_SUPPORT_STREAM,
computeMJPEGStreamUrl,
fetchStreamUrl,
fetchThumbnailUrlWithCache,
STREAM_TYPE_HLS,
STREAM_TYPE_WEB_RTC,
} from "../data/camera";
@ -37,6 +38,9 @@ class HaCameraStream extends LitElement {
@property({ type: Boolean, attribute: "allow-exoplayer" })
public allowExoPlayer = false;
// Video background image before its loaded
@state() private _posterUrl?: string;
// We keep track if we should force MJPEG if there was a failure
// to get the HLS stream url. This is reset if we change entities.
@state() private _forceMJPEG?: string;
@ -51,12 +55,14 @@ class HaCameraStream extends LitElement {
!this._shouldRenderMJPEG &&
this.stateObj &&
(changedProps.get("stateObj") as CameraEntity | undefined)?.entity_id !==
this.stateObj.entity_id &&
this.stateObj!.attributes.frontend_stream_type === STREAM_TYPE_HLS
this.stateObj.entity_id
) {
this._forceMJPEG = undefined;
this._url = undefined;
this._getStreamUrl();
this._getPosterUrl();
if (this.stateObj!.attributes.frontend_stream_type === STREAM_TYPE_HLS) {
this._forceMJPEG = undefined;
this._url = undefined;
this._getStreamUrl();
}
}
}
@ -94,6 +100,7 @@ class HaCameraStream extends LitElement {
.controls=${this.controls}
.hass=${this.hass}
.url=${this._url}
.posterUrl=${this._posterUrl}
></ha-hls-player>`
: html``;
}
@ -105,6 +112,7 @@ class HaCameraStream extends LitElement {
.controls=${this.controls}
.hass=${this.hass}
.entityid=${this.stateObj.entity_id}
.posterUrl=${this._posterUrl}
></ha-web-rtc-player>`;
}
return html``;
@ -129,6 +137,20 @@ class HaCameraStream extends LitElement {
return !isComponentLoaded(this.hass!, "stream");
}
private async _getPosterUrl(): Promise<void> {
try {
this._posterUrl = await fetchThumbnailUrlWithCache(
this.hass!,
this.stateObj!.entity_id,
this.clientWidth,
this.clientHeight
);
} catch (err: any) {
// poster url is optional
this._posterUrl = undefined;
}
}
private async _getStreamUrl(): Promise<void> {
try {
const { url } = await fetchStreamUrl(

View File

@ -23,6 +23,8 @@ class HaHLSPlayer extends LitElement {
@property() public url!: string;
@property() public posterUrl!: string;
@property({ type: Boolean, attribute: "controls" })
public controls = false;
@ -78,6 +80,7 @@ class HaHLSPlayer extends LitElement {
: ""}
${!this._errorIsFatal
? html`<video
.poster=${this.posterUrl}
?autoplay=${this.autoPlay}
.muted=${this.muted}
?playsinline=${this.playsInline}

View File

@ -34,6 +34,8 @@ class HaWebRtcPlayer extends LitElement {
@property({ type: Boolean, attribute: "playsinline" })
public playsInline = false;
@property() public posterUrl!: string;
@state() private _error?: string;
// don't cache this, as we remove it on disconnects
@ -54,6 +56,7 @@ class HaWebRtcPlayer extends LitElement {
.muted=${this.muted}
?playsinline=${this.playsInline}
?controls=${this.controls}
.poster=${this.posterUrl}
></video>
`;
}