mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 03:06:41 +00:00
Improve video user experience by loading camera thumbnail as initial video background image (#13943)
This commit is contained in:
parent
66bfdb6d12
commit
9c923e45c5
@ -15,6 +15,7 @@ import {
|
|||||||
CAMERA_SUPPORT_STREAM,
|
CAMERA_SUPPORT_STREAM,
|
||||||
computeMJPEGStreamUrl,
|
computeMJPEGStreamUrl,
|
||||||
fetchStreamUrl,
|
fetchStreamUrl,
|
||||||
|
fetchThumbnailUrlWithCache,
|
||||||
STREAM_TYPE_HLS,
|
STREAM_TYPE_HLS,
|
||||||
STREAM_TYPE_WEB_RTC,
|
STREAM_TYPE_WEB_RTC,
|
||||||
} from "../data/camera";
|
} from "../data/camera";
|
||||||
@ -37,6 +38,9 @@ class HaCameraStream extends LitElement {
|
|||||||
@property({ type: Boolean, attribute: "allow-exoplayer" })
|
@property({ type: Boolean, attribute: "allow-exoplayer" })
|
||||||
public allowExoPlayer = false;
|
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
|
// 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.
|
// to get the HLS stream url. This is reset if we change entities.
|
||||||
@state() private _forceMJPEG?: string;
|
@state() private _forceMJPEG?: string;
|
||||||
@ -51,12 +55,14 @@ class HaCameraStream extends LitElement {
|
|||||||
!this._shouldRenderMJPEG &&
|
!this._shouldRenderMJPEG &&
|
||||||
this.stateObj &&
|
this.stateObj &&
|
||||||
(changedProps.get("stateObj") as CameraEntity | undefined)?.entity_id !==
|
(changedProps.get("stateObj") as CameraEntity | undefined)?.entity_id !==
|
||||||
this.stateObj.entity_id &&
|
this.stateObj.entity_id
|
||||||
this.stateObj!.attributes.frontend_stream_type === STREAM_TYPE_HLS
|
|
||||||
) {
|
) {
|
||||||
this._forceMJPEG = undefined;
|
this._getPosterUrl();
|
||||||
this._url = undefined;
|
if (this.stateObj!.attributes.frontend_stream_type === STREAM_TYPE_HLS) {
|
||||||
this._getStreamUrl();
|
this._forceMJPEG = undefined;
|
||||||
|
this._url = undefined;
|
||||||
|
this._getStreamUrl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +100,7 @@ class HaCameraStream extends LitElement {
|
|||||||
.controls=${this.controls}
|
.controls=${this.controls}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.url=${this._url}
|
.url=${this._url}
|
||||||
|
.posterUrl=${this._posterUrl}
|
||||||
></ha-hls-player>`
|
></ha-hls-player>`
|
||||||
: html``;
|
: html``;
|
||||||
}
|
}
|
||||||
@ -105,6 +112,7 @@ class HaCameraStream extends LitElement {
|
|||||||
.controls=${this.controls}
|
.controls=${this.controls}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.entityid=${this.stateObj.entity_id}
|
.entityid=${this.stateObj.entity_id}
|
||||||
|
.posterUrl=${this._posterUrl}
|
||||||
></ha-web-rtc-player>`;
|
></ha-web-rtc-player>`;
|
||||||
}
|
}
|
||||||
return html``;
|
return html``;
|
||||||
@ -129,6 +137,20 @@ class HaCameraStream extends LitElement {
|
|||||||
return !isComponentLoaded(this.hass!, "stream");
|
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> {
|
private async _getStreamUrl(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { url } = await fetchStreamUrl(
|
const { url } = await fetchStreamUrl(
|
||||||
|
@ -23,6 +23,8 @@ class HaHLSPlayer extends LitElement {
|
|||||||
|
|
||||||
@property() public url!: string;
|
@property() public url!: string;
|
||||||
|
|
||||||
|
@property() public posterUrl!: string;
|
||||||
|
|
||||||
@property({ type: Boolean, attribute: "controls" })
|
@property({ type: Boolean, attribute: "controls" })
|
||||||
public controls = false;
|
public controls = false;
|
||||||
|
|
||||||
@ -78,6 +80,7 @@ class HaHLSPlayer extends LitElement {
|
|||||||
: ""}
|
: ""}
|
||||||
${!this._errorIsFatal
|
${!this._errorIsFatal
|
||||||
? html`<video
|
? html`<video
|
||||||
|
.poster=${this.posterUrl}
|
||||||
?autoplay=${this.autoPlay}
|
?autoplay=${this.autoPlay}
|
||||||
.muted=${this.muted}
|
.muted=${this.muted}
|
||||||
?playsinline=${this.playsInline}
|
?playsinline=${this.playsInline}
|
||||||
|
@ -34,6 +34,8 @@ class HaWebRtcPlayer extends LitElement {
|
|||||||
@property({ type: Boolean, attribute: "playsinline" })
|
@property({ type: Boolean, attribute: "playsinline" })
|
||||||
public playsInline = false;
|
public playsInline = false;
|
||||||
|
|
||||||
|
@property() public posterUrl!: string;
|
||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
// don't cache this, as we remove it on disconnects
|
// don't cache this, as we remove it on disconnects
|
||||||
@ -54,6 +56,7 @@ class HaWebRtcPlayer extends LitElement {
|
|||||||
.muted=${this.muted}
|
.muted=${this.muted}
|
||||||
?playsinline=${this.playsInline}
|
?playsinline=${this.playsInline}
|
||||||
?controls=${this.controls}
|
?controls=${this.controls}
|
||||||
|
.poster=${this.posterUrl}
|
||||||
></video>
|
></video>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user