Stop video content when the view is changed.

This commit is contained in:
Dermot Duffy
2021-08-08 21:52:52 -07:00
parent 848a4f6af3
commit 7f4dfc43e6
2 changed files with 68 additions and 8 deletions
+62 -8
View File
@@ -5,8 +5,6 @@
// TODO comments per method. // TODO comments per method.
// TODO: Stop the live view video when I hide it.
// TODO Check for HA state presence and validity before using it, otherwise warn. // TODO Check for HA state presence and validity before using it, otherwise warn.
// TODO Add material tooltips // TODO Add material tooltips
@@ -38,7 +36,7 @@ import './editor';
import style from './frigate-card.scss' import style from './frigate-card.scss'
import type { FrigateCardConfig, FrigateEvent, GetEventsParameters } from './types'; import type { FrigateCardConfig, FrigateEvent, GetEventsParameters, ControlVideosParameters } from './types';
import { actionHandler } from './action-handler-directive'; import { actionHandler } from './action-handler-directive';
import { CARD_VERSION } from './const'; import { CARD_VERSION } from './const';
import { localize } from './localize/localize'; import { localize } from './localize/localize';
@@ -120,7 +118,7 @@ export class FrigateCard extends LitElement {
if (cardConfig.camera_entity.includes(".")) { if (cardConfig.camera_entity.includes(".")) {
cardConfig.frigate_camera_name = cardConfig.camera_entity.split('.', 2)[1] cardConfig.frigate_camera_name = cardConfig.camera_entity.split('.', 2)[1]
} else { } else {
throw new Error(localize('common.invalid_configuration_missing') + ": camera"); throw new Error(localize('common.invalid_configuration_missing') + ": camera_entity");
} }
} }
@@ -271,23 +269,78 @@ export class FrigateCard extends LitElement {
</div>` </div>`
} }
protected _controlVideos({
stop,
control_live = false,
control_clip = false}: ControlVideosParameters): void {
const controlVideo = (stop: boolean, is_live: boolean, video: HTMLVideoElement) => {
if (video) {
if (stop) {
video.pause();
video.currentTime = 0;
} else {
if (is_live) {
// If it's a live view, 'fast-forward' to most recent content.
const duration = video.duration;
video.currentTime = duration;
}
video.play();
}
}
}
if (!this.shadowRoot) {
return;
}
if (control_clip) {
controlVideo(
stop,
false,
this.shadowRoot?.querySelector(
`#frigate-card-clip-player`) as HTMLVideoElement);
}
if (control_live) {
// Don't have direct access to the live video player as it is buried in
// multiple components/shadow-roots, so need to navigate the path to get to <video>.
const ha_camera_stream = this.shadowRoot?.querySelector(`#frigate-card-live-player`);
if (ha_camera_stream && ha_camera_stream?.shadowRoot) {
const ha_hls_player = ha_camera_stream.shadowRoot.querySelector(`ha-hls-player`);
if (ha_hls_player && ha_hls_player?.shadowRoot) {
controlVideo(
stop,
true,
ha_hls_player.shadowRoot.querySelector(`video`) as HTMLVideoElement);
}
}
}
}
protected _renderNavigationBar(): TemplateResult { protected _renderNavigationBar(): TemplateResult {
return html` return html`
<div class="frigate-card-navbar" > <div class="frigate-card-navbar" >
<ha-icon-button <ha-icon-button
class="button" class="button"
icon="mdi:cctv" icon="mdi:cctv"
@click=${() => this._viewMode = FrigateCardView.LIVE} @click=${() => {
this._controlVideos({stop: true, control_clip: true});
this._controlVideos({stop: false, control_live: true});
this._viewMode = FrigateCardView.LIVE
}}
></ha-icon-button> ></ha-icon-button>
<ha-icon-button <ha-icon-button
class="button" class="button"
icon = "mdi:filmstrip" icon = "mdi:filmstrip"
@click=${() => this._viewMode = FrigateCardView.CLIPS} @click=${() => {
this._controlVideos({stop: true, control_live: true});
this._viewMode = FrigateCardView.CLIPS
}}
></ha-icon-button> ></ha-icon-button>
<ha-icon-button <ha-icon-button
class="button" class="button"
icon = "mdi:camera" icon = "mdi:camera"
@click=${() => this._viewMode = FrigateCardView.SNAPSHOTS} @click=${() => {
this._controlVideos({stop: true, control_clip: true, control_live: true});
this._viewMode = FrigateCardView.SNAPSHOTS
}}
></ha-icon-button> ></ha-icon-button>
</div>` </div>`
} }
@@ -313,7 +366,7 @@ export class FrigateCard extends LitElement {
const url = `${this.config.frigate_url}/clips/` + const url = `${this.config.frigate_url}/clips/` +
`${event.camera}-${event.id}.mp4`; `${event.camera}-${event.id}.mp4`;
return html` return html`
<video class="frigate-card-viewer" autoplay controls> <video id="frigate-card-clip-player" class="frigate-card-viewer" autoplay controls>
<source src="${url}" type="video/mp4"> <source src="${url}" type="video/mp4">
</video>` </video>`
} }
@@ -360,6 +413,7 @@ export class FrigateCard extends LitElement {
protected _renderLiveViewer(): TemplateResult { protected _renderLiveViewer(): TemplateResult {
return html` return html`
<ha-camera-stream <ha-camera-stream
id="frigate-card-live-player"
.hass=${this.hass} .hass=${this.hass}
.stateObj=${this.hass.states[this.config.camera_entity]} .stateObj=${this.hass.states[this.config.camera_entity]}
.controls=${true} .controls=${true}
+6
View File
@@ -44,3 +44,9 @@ export interface GetEventsParameters {
has_snapshot?: boolean; has_snapshot?: boolean;
limit?: number; limit?: number;
} }
export interface ControlVideosParameters {
stop: boolean;
control_live?: boolean;
control_clip?: boolean;
}