mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 17:26:42 +00:00
Improve robustness of hls media player (#11672)
This commit is contained in:
parent
d86a18b80b
commit
a8c1fdd21e
@ -43,6 +43,8 @@ class HaHLSPlayer extends LitElement {
|
|||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
|
@state() private _errorIsFatal = false;
|
||||||
|
|
||||||
private _hlsPolyfillInstance?: HlsLite;
|
private _hlsPolyfillInstance?: HlsLite;
|
||||||
|
|
||||||
private _exoPlayer = false;
|
private _exoPlayer = false;
|
||||||
@ -53,6 +55,7 @@ class HaHLSPlayer extends LitElement {
|
|||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
HaHLSPlayer.streamCount += 1;
|
HaHLSPlayer.streamCount += 1;
|
||||||
if (this.hasUpdated) {
|
if (this.hasUpdated) {
|
||||||
|
this._resetError();
|
||||||
this._startHls();
|
this._startHls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,16 +67,23 @@ class HaHLSPlayer extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this._error) {
|
|
||||||
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
|
||||||
}
|
|
||||||
return html`
|
return html`
|
||||||
<video
|
${this._error
|
||||||
?autoplay=${this.autoPlay}
|
? html`<ha-alert
|
||||||
.muted=${this.muted}
|
alert-type="error"
|
||||||
?playsinline=${this.playsInline}
|
class=${this._errorIsFatal ? "fatal" : "retry"}
|
||||||
?controls=${this.controls}
|
>
|
||||||
></video>
|
${this._error}
|
||||||
|
</ha-alert>`
|
||||||
|
: ""}
|
||||||
|
${!this._errorIsFatal
|
||||||
|
? html`<video
|
||||||
|
?autoplay=${this.autoPlay}
|
||||||
|
.muted=${this.muted}
|
||||||
|
?playsinline=${this.playsInline}
|
||||||
|
?controls=${this.controls}
|
||||||
|
></video>`
|
||||||
|
: ""}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,12 +97,11 @@ class HaHLSPlayer extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._cleanUp();
|
this._cleanUp();
|
||||||
|
this._resetError();
|
||||||
this._startHls();
|
this._startHls();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _startHls(): Promise<void> {
|
private async _startHls(): Promise<void> {
|
||||||
this._error = undefined;
|
|
||||||
|
|
||||||
const masterPlaylistPromise = fetch(this.url);
|
const masterPlaylistPromise = fetch(this.url);
|
||||||
|
|
||||||
const Hls: typeof HlsType = (await import("hls.js/dist/hls.light.min"))
|
const Hls: typeof HlsType = (await import("hls.js/dist/hls.light.min"))
|
||||||
@ -110,8 +119,8 @@ class HaHLSPlayer extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hlsSupported) {
|
if (!hlsSupported) {
|
||||||
this._error = this.hass.localize(
|
this._setFatalError(
|
||||||
"ui.components.media-browser.video_not_supported"
|
this.hass.localize("ui.components.media-browser.video_not_supported")
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -219,9 +228,16 @@ class HaHLSPlayer extends LitElement {
|
|||||||
this._hlsPolyfillInstance = hls;
|
this._hlsPolyfillInstance = hls;
|
||||||
hls.attachMedia(videoEl);
|
hls.attachMedia(videoEl);
|
||||||
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
||||||
|
this._resetError();
|
||||||
hls.loadSource(url);
|
hls.loadSource(url);
|
||||||
});
|
});
|
||||||
hls.on(Hls.Events.ERROR, (_, data: any) => {
|
hls.on(Hls.Events.FRAG_LOADED, (_event, _data: any) => {
|
||||||
|
this._resetError();
|
||||||
|
});
|
||||||
|
hls.on(Hls.Events.ERROR, (_event, data: any) => {
|
||||||
|
// Some errors are recovered automatically by the hls player itself, and the others handled
|
||||||
|
// in this function require special actions to recover. Errors retried in this function
|
||||||
|
// are done with backoff to not cause unecessary failures.
|
||||||
if (!data.fatal) {
|
if (!data.fatal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -241,22 +257,22 @@ class HaHLSPlayer extends LitElement {
|
|||||||
error += " (" + data.response.code + ")";
|
error += " (" + data.response.code + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._error = error;
|
this._setRetryableError(error);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
case Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT:
|
case Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT:
|
||||||
this._error = "Timeout while starting stream";
|
this._setRetryableError("Timeout while starting stream");
|
||||||
return;
|
break;
|
||||||
default:
|
default:
|
||||||
this._error = "Unknown stream network error (" + data.details + ")";
|
this._setRetryableError("Stream network error");
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
this._error = "Error with media stream contents (" + data.details + ")";
|
hls.startLoad();
|
||||||
} else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {
|
} else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {
|
||||||
this._error = "Error with media stream contents (" + data.details + ")";
|
this._setRetryableError("Error with media stream contents");
|
||||||
|
hls.recoverMediaError();
|
||||||
} else {
|
} else {
|
||||||
this._error =
|
this._setFatalError("Error playing stream");
|
||||||
"Unknown error with stream (" + data.type + ", " + data.details + ")";
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -284,6 +300,21 @@ class HaHLSPlayer extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _resetError() {
|
||||||
|
this._error = undefined;
|
||||||
|
this._errorIsFatal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setFatalError(errorMessage: string) {
|
||||||
|
this._error = errorMessage;
|
||||||
|
this._errorIsFatal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setRetryableError(errorMessage: string) {
|
||||||
|
this._error = errorMessage;
|
||||||
|
this._errorIsFatal = false;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
:host,
|
:host,
|
||||||
@ -296,10 +327,14 @@ class HaHLSPlayer extends LitElement {
|
|||||||
max-height: var(--video-max-height, calc(100vh - 97px));
|
max-height: var(--video-max-height, calc(100vh - 97px));
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-alert {
|
.fatal {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 100px 16px;
|
padding: 100px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.retry {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user