Dynamically extract dimensions from loaded media.

This commit is contained in:
Dermot Duffy
2021-09-23 20:38:39 -07:00
parent c75e99e09c
commit e3ccbb0787
13 changed files with 312 additions and 44 deletions
+33 -9
View File
@@ -7,7 +7,7 @@ import { signedPathSchema } from '../types';
import type { ExtendedHomeAssistant, FrigateCardConfig } from '../types';
import { localize } from '../localize/localize';
import { homeAssistantWSRequest } from '../common';
import { dispatchMediaLoadEvent, homeAssistantWSRequest } from '../common';
import {
renderMessage,
renderErrorMessage,
@@ -68,13 +68,13 @@ export class FrigateCardViewerFrigate extends LitElement {
if (!(this.cameraEntity in this.hass.states)) {
return renderMessage(localize('error.no_live_camera'), 'mdi:camera-off');
}
return html` <ha-camera-stream
return html` <frigate-card-ha-camera-stream
.hass=${this.hass}
.stateObj=${this.hass.states[this.cameraEntity]}
.controls=${true}
.muted=${true}
>
</ha-camera-stream>`;
</frigate-card-ha-camera-stream>`;
}
static get styles(): CSSResultGroup {
@@ -119,6 +119,19 @@ export class FrigateCardViewerWebRTC extends LitElement {
return html`${this._webRTCElement}`;
}
public updated(): void {
// Extract the video component after it has been rendered and generate the
// media load event.
this.updateComplete.then(() => {
const video = this.renderRoot.querySelector('#video') as HTMLVideoElement;
if (video) {
video.onloadedmetadata = () => {
dispatchMediaLoadEvent(this, video);
}
}
})
}
static get styles(): CSSResultGroup {
return unsafeCSS(liveStyle);
}
@@ -135,7 +148,7 @@ export class FrigateCardViewerJSMPEG extends LitElement {
@property({ attribute: false })
protected clientId!: string;
protected _jsmpegCanvasElement: HTMLElement | null = null;
protected _jsmpegCanvasElement: HTMLCanvasElement | null = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected _jsmpegVideoPlayer: any | null = null;
@@ -187,10 +200,7 @@ export class FrigateCardViewerJSMPEG extends LitElement {
return renderErrorMessage('Could not retrieve or sign JSMPEG websocket path');
}
// Return the html canvas node only after the JSMPEG video has loaded and
// is playing, to reduce the amount of time the user is staring at a blank
// white canvas (instead they get the progress spinner until this promise
// resolves).
let videoDecoded = false;
return new Promise<TemplateResult>((resolve) => {
this._jsmpegVideoPlayer = new JSMpeg.VideoElement(
this,
@@ -198,12 +208,26 @@ export class FrigateCardViewerJSMPEG extends LitElement {
{
canvas: this._jsmpegCanvasElement,
hooks: {
// Don't resolve the promise until it's playing to minimize the
// amount of time the canvas is empty (and show the spinner
// instead).
play: () => {
resolve(html`${this._jsmpegCanvasElement}`);
},
},
},
{ protocols: [], videoBufferSize: 1024 * 1024 * 4 },
{ protocols: [],
videoBufferSize: 1024 * 1024 * 4,
onVideoDecode: () => {
// This is the only callback that is called after the dimensions
// are available. It's called on every frame decode, so just
// ignore any subsequent calls.
if (!videoDecoded && this._jsmpegCanvasElement) {
videoDecoded = true;
dispatchMediaLoadEvent(this, this._jsmpegCanvasElement);
}
}
},
);
});
}
+9 -4
View File
@@ -18,6 +18,7 @@ import type {
import { localize } from '../localize/localize';
import {
browseMediaQuery,
dispatchMediaLoadEvent,
dispatchPauseEvent,
dispatchPlayEvent,
getFirstTrueMediaChildIndex,
@@ -199,7 +200,7 @@ export class FrigateCardViewer extends LitElement {
const neighbors = this._getMediaNeighbors(parent, childIndex);
return html`
return html` <div>
${neighbors?.previousIndex != null
? html`<frigate-card-next-previous-control
.control=${'previous'}
@@ -211,7 +212,7 @@ export class FrigateCardViewer extends LitElement {
: ``}
${this.view.is('clip')
? resolvedMedia?.mime_type.toLowerCase() == 'application/x-mpegurl'
? html`<ha-hls-player
? html`<frigate-card-ha-hls-player
.hass=${this.hass}
.url=${resolvedMedia.url}
title="${mediaToRender.title}"
@@ -221,13 +222,14 @@ export class FrigateCardViewer extends LitElement {
allow-exoplayer
?autoplay="${autoplay}"
>
</ha-hls-player>`
</frigate-card-ha-hls-player>`
: html`<video
title="${mediaToRender.title}"
muted
controls
playsinline
?autoplay="${autoplay}"
@loadedmetadata=${(e) => dispatchMediaLoadEvent(this, e)}a
@play=${() => dispatchPlayEvent(this)}
@pause=${() => dispatchPauseEvent(this)}
>
@@ -247,6 +249,9 @@ export class FrigateCardViewer extends LitElement {
}
});
}}
@load=${(e) => {
dispatchMediaLoadEvent(this, e);
}}
/>`}
${neighbors?.nextIndex != null
? html`<frigate-card-next-previous-control
@@ -257,7 +262,7 @@ export class FrigateCardViewer extends LitElement {
.view=${this.view}
></frigate-card-next-previous-control>`
: ``}
`;
</div>`;
}
static get styles(): CSSResultGroup {