mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 17:26:42 +00:00
Improve WebRTC stream error handling and cleanup (#10302)
This commit is contained in:
parent
d5b98d306d
commit
a8486eda9f
@ -39,6 +39,10 @@ class HaWebRtcPlayer extends LitElement {
|
|||||||
// don't cache this, as we remove it on disconnects
|
// don't cache this, as we remove it on disconnects
|
||||||
@query("#remote-stream") private _videoEl!: HTMLVideoElement;
|
@query("#remote-stream") private _videoEl!: HTMLVideoElement;
|
||||||
|
|
||||||
|
private _peerConnection?: RTCPeerConnection;
|
||||||
|
|
||||||
|
private _remoteStream?: MediaStream;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this._error) {
|
if (this._error) {
|
||||||
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
return html`<ha-alert alert-type="error">${this._error}</ha-alert>`;
|
||||||
@ -71,6 +75,7 @@ class HaWebRtcPlayer extends LitElement {
|
|||||||
|
|
||||||
private async _startWebRtc(): Promise<void> {
|
private async _startWebRtc(): Promise<void> {
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
|
|
||||||
const peerConnection = new RTCPeerConnection();
|
const peerConnection = new RTCPeerConnection();
|
||||||
// Some cameras (such as nest) require a data channel to establish a stream
|
// Some cameras (such as nest) require a data channel to establish a stream
|
||||||
// however, not used by any integrations.
|
// however, not used by any integrations.
|
||||||
@ -93,6 +98,7 @@ class HaWebRtcPlayer extends LitElement {
|
|||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this._error = "Failed to start WebRTC stream: " + err.message;
|
this._error = "Failed to start WebRTC stream: " + err.message;
|
||||||
|
peerConnection.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,21 +108,39 @@ class HaWebRtcPlayer extends LitElement {
|
|||||||
remoteStream.addTrack(event.track);
|
remoteStream.addTrack(event.track);
|
||||||
this._videoEl.srcObject = remoteStream;
|
this._videoEl.srcObject = remoteStream;
|
||||||
});
|
});
|
||||||
|
this._remoteStream = remoteStream;
|
||||||
|
|
||||||
// Initiate the stream with the remote device
|
// Initiate the stream with the remote device
|
||||||
const remoteDesc = new RTCSessionDescription({
|
const remoteDesc = new RTCSessionDescription({
|
||||||
type: "answer",
|
type: "answer",
|
||||||
sdp: webRtcAnswer.answer,
|
sdp: webRtcAnswer.answer,
|
||||||
});
|
});
|
||||||
await peerConnection.setRemoteDescription(remoteDesc);
|
try {
|
||||||
|
await peerConnection.setRemoteDescription(remoteDesc);
|
||||||
|
} catch (err: any) {
|
||||||
|
this._error = "Failed to connect WebRTC stream: " + err.message;
|
||||||
|
peerConnection.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._peerConnection = peerConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _cleanUp() {
|
private _cleanUp() {
|
||||||
|
if (this._remoteStream) {
|
||||||
|
this._remoteStream.getTracks().forEach((track) => {
|
||||||
|
track.stop();
|
||||||
|
});
|
||||||
|
this._remoteStream = undefined;
|
||||||
|
}
|
||||||
if (this._videoEl) {
|
if (this._videoEl) {
|
||||||
const videoEl = this._videoEl;
|
const videoEl = this._videoEl;
|
||||||
videoEl.removeAttribute("src");
|
videoEl.removeAttribute("src");
|
||||||
videoEl.load();
|
videoEl.load();
|
||||||
}
|
}
|
||||||
|
if (this._peerConnection) {
|
||||||
|
this._peerConnection.close();
|
||||||
|
this._peerConnection = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user