Skip to content

Commit

Permalink
Improve video user experience by loading camera thumbnail as initial …
Browse files Browse the repository at this point in the history
…video background image (home-assistant#13943)
  • Loading branch information
allenporter authored Oct 3, 2022
1 parent 66bfdb6 commit 9c923e4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
32 changes: 27 additions & 5 deletions src/components/ha-camera-stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
CAMERA_SUPPORT_STREAM,
computeMJPEGStreamUrl,
fetchStreamUrl,
fetchThumbnailUrlWithCache,
STREAM_TYPE_HLS,
STREAM_TYPE_WEB_RTC,
} from "../data/camera";
Expand All @@ -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;
Expand All @@ -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();
}
}
}

Expand Down Expand Up @@ -94,6 +100,7 @@ class HaCameraStream extends LitElement {
.controls=${this.controls}
.hass=${this.hass}
.url=${this._url}
.posterUrl=${this._posterUrl}
></ha-hls-player>`
: html``;
}
Expand All @@ -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``;
Expand All @@ -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(
Expand Down
3 changes: 3 additions & 0 deletions src/components/ha-hls-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class HaHLSPlayer extends LitElement {

@property() public url!: string;

@property() public posterUrl!: string;

@property({ type: Boolean, attribute: "controls" })
public controls = false;

Expand Down Expand Up @@ -78,6 +80,7 @@ class HaHLSPlayer extends LitElement {
: ""}
${!this._errorIsFatal
? html`<video
.poster=${this.posterUrl}
?autoplay=${this.autoPlay}
.muted=${this.muted}
?playsinline=${this.playsInline}
Expand Down
3 changes: 3 additions & 0 deletions src/components/ha-web-rtc-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -54,6 +56,7 @@ class HaWebRtcPlayer extends LitElement {
.muted=${this.muted}
?playsinline=${this.playsInline}
?controls=${this.controls}
.poster=${this.posterUrl}
></video>
`;
}
Expand Down

0 comments on commit 9c923e4

Please sign in to comment.