Render the JSMPEG spinner until the last possible moment.
This commit is contained in:
+1
-1
@@ -22,7 +22,7 @@
|
|||||||
"@material/rtl": "^13.0.0",
|
"@material/rtl": "^13.0.0",
|
||||||
"custom-card-helpers": "^1.8.0",
|
"custom-card-helpers": "^1.8.0",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"embla-carousel": "^5.0.1",
|
"embla-carousel": "^6.1.0",
|
||||||
"home-assistant-js-websocket": "^5.11.1",
|
"home-assistant-js-websocket": "^5.11.1",
|
||||||
"lit": "^2.0.2",
|
"lit": "^2.0.2",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
|
|||||||
+37
-38
@@ -754,46 +754,46 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a JSMPEG player.
|
* Create a JSMPEG player.
|
||||||
|
* @param url The URL for the player to connect to.
|
||||||
* @returns A JSMPEG player.
|
* @returns A JSMPEG player.
|
||||||
*/
|
*/
|
||||||
protected _createJSMPEGPlayer(url: string): JSMpeg.VideoElement {
|
protected async _createJSMPEGPlayer(url: string): Promise<JSMpeg.VideoElement> {
|
||||||
let videoDecoded = false;
|
return new Promise<JSMpeg.VideoElement>((resolve) => {
|
||||||
|
let videoDecoded = false;
|
||||||
const jsmpegOptions = {
|
const player = new JSMpeg.VideoElement(
|
||||||
pauseWhenHidden: false,
|
this,
|
||||||
protocols: [],
|
url,
|
||||||
audio: false,
|
{
|
||||||
videoBufferSize: 1024 * 1024 * 4,
|
canvas: this._jsmpegCanvasElement,
|
||||||
onVideoDecode: () => {
|
hooks: {
|
||||||
// This is the only callback that is called after the dimensions
|
play: () => {
|
||||||
// are available. It's called on every frame decode, so just
|
dispatchPlayEvent(this);
|
||||||
// ignore any subsequent calls.
|
},
|
||||||
if (!videoDecoded && this._jsmpegCanvasElement) {
|
pause: () => {
|
||||||
videoDecoded = true;
|
dispatchPauseEvent(this);
|
||||||
dispatchMediaShowEvent(this, this._jsmpegCanvasElement);
|
},
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Override with user-specified options.
|
|
||||||
Object.assign(jsmpegOptions, this.jsmpegConfig?.options);
|
|
||||||
|
|
||||||
return new JSMpeg.VideoElement(
|
|
||||||
this,
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
canvas: this._jsmpegCanvasElement,
|
|
||||||
hooks: {
|
|
||||||
play: () => {
|
|
||||||
dispatchPlayEvent(this);
|
|
||||||
},
|
|
||||||
pause: () => {
|
|
||||||
dispatchPauseEvent(this);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
jsmpegOptions,
|
pauseWhenHidden: false,
|
||||||
);
|
protocols: [],
|
||||||
|
audio: false,
|
||||||
|
videoBufferSize: 1024 * 1024 * 4,
|
||||||
|
// Override with user-specified options.
|
||||||
|
...this.jsmpegConfig?.options,
|
||||||
|
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;
|
||||||
|
dispatchMediaShowEvent(this, this._jsmpegCanvasElement);
|
||||||
|
resolve(player);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -856,8 +856,7 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
|||||||
|
|
||||||
const url = await this._getURL();
|
const url = await this._getURL();
|
||||||
if (url) {
|
if (url) {
|
||||||
this._jsmpegVideoPlayer = this._createJSMPEGPlayer(url);
|
this._jsmpegVideoPlayer = await this._createJSMPEGPlayer(url);
|
||||||
|
|
||||||
this._refreshPlayerTimerID = window.setTimeout(() => {
|
this._refreshPlayerTimerID = window.setTimeout(() => {
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}, (URL_SIGN_EXPIRY_SECONDS - URL_SIGN_REFRESH_THRESHOLD_SECONDS) * 1000);
|
}, (URL_SIGN_EXPIRY_SECONDS - URL_SIGN_REFRESH_THRESHOLD_SECONDS) * 1000);
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
|
|||||||
if (!this._carousel) {
|
if (!this._carousel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._carousel.containerNode().style.removeProperty('max-height')
|
this._carousel.containerNode().style.removeProperty('max-height');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,20 +119,24 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
|
|||||||
* different aspect ratios).
|
* different aspect ratios).
|
||||||
*/
|
*/
|
||||||
protected _adaptiveHeightSetHandler(): void {
|
protected _adaptiveHeightSetHandler(): void {
|
||||||
if (!this._carousel) {
|
// Don't gather slide heights until the next browser re-paint to ensure the
|
||||||
return;
|
// measured heights are correct on the media that has (potentially) just
|
||||||
}
|
// loaded.
|
||||||
const slides = this._carousel.slideNodes();
|
window.requestAnimationFrame(() => {
|
||||||
const heights = this._carousel.slidesInView(true).map((index) => {
|
if (!this._carousel) {
|
||||||
const firstChild = slides[index].querySelector("*");
|
return;
|
||||||
return firstChild ? firstChild.getBoundingClientRect().height : 0;
|
}
|
||||||
})
|
const slides = this._carousel.slideNodes();
|
||||||
const targetHeight = Math.max(...heights);
|
const heights = this._carousel.slidesInView(true).map((index) => {
|
||||||
if (targetHeight > 0) {
|
return slides[index].getBoundingClientRect().height;
|
||||||
this._carousel.containerNode().style.maxHeight = `${targetHeight}px`;
|
});
|
||||||
} else {
|
const targetHeight = Math.max(...heights);
|
||||||
this._carousel.containerNode().style.removeProperty('max-height')
|
if (targetHeight > 0) {
|
||||||
}
|
this._carousel.containerNode().style.maxHeight = `${targetHeight}px`;
|
||||||
|
} else {
|
||||||
|
this._carousel.containerNode().style.removeProperty('max-height');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
--video-max-height: none;
|
--video-max-height: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.embla__container {
|
||||||
|
// To support adaptive height animations.
|
||||||
|
transition: max-height 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
.embla__slide {
|
.embla__slide {
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100%;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user