Dynamically extract dimensions from loaded media.
This commit is contained in:
+33
-9
@@ -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);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user