Support custom JSMPEG options.
This commit is contained in:
@@ -116,6 +116,7 @@ All variables listed are under a `live:` section.
|
||||
| `webrtc.entity` | | The RTSP entity to pass WebRTC. Specify this OR `webrtc.url` (above). |
|
||||
| `webrtc.*`| | Any other options in a `webrtc:` YAML dictionary are silently passed through to WebRTC. See [WebRTC Configuration](https://github.com/AlexxIT/WebRTC#configuration) for full details this external card provides.|
|
||||
| `actions` | | Actions to use for the `live` view. See [actions](#actions) below.|
|
||||
| `jsmpeg.options.{audio, video, pauseWhenHidden, disableGl, disableWebAssembly, preserveDrawingBuffer, progressive, throttled, chunkSize, maxAudioLag, videoBufferSize, audioBufferSize}` | | **Advanced users only**: Control the underlying [JSMPEG library options](https://github.com/phoboslab/jsmpeg#usage). This is not necessary for the vast majority of users: only set these flags if you know what you're doing, as you may entirely break video rendering in the card.|
|
||||
|
||||
#### Available Live Providers
|
||||
|
||||
|
||||
+34
-18
@@ -1,5 +1,11 @@
|
||||
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
|
||||
import type { ExtendedHomeAssistant, FrigateCardConfig, MediaShowInfo, WebRTCConfig } from '../types.js';
|
||||
import type {
|
||||
ExtendedHomeAssistant,
|
||||
FrigateCardConfig,
|
||||
JSMPEGConfig,
|
||||
MediaShowInfo,
|
||||
WebRTCConfig,
|
||||
} from '../types.js';
|
||||
import { HomeAssistant } from 'custom-card-helpers';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { until } from 'lit/directives/until.js';
|
||||
@@ -93,6 +99,7 @@ export class FrigateCardLive extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.cameraName=${this.frigateCameraName}
|
||||
.clientId=${this.config.frigate.client_id}
|
||||
.jsmpegConfig=${this.config.live.jsmpeg}
|
||||
@frigate-card:media-show=${this._mediaShowHandler}
|
||||
>
|
||||
</frigate-card-live-jsmpeg>`}`;
|
||||
@@ -242,6 +249,9 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
||||
@property({ attribute: false })
|
||||
protected clientId?: string;
|
||||
|
||||
@property({ attribute: false })
|
||||
protected jsmpegConfig?: JSMPEGConfig;
|
||||
|
||||
protected hass?: HomeAssistant & ExtendedHomeAssistant;
|
||||
protected _jsmpegCanvasElement?: HTMLCanvasElement;
|
||||
protected _jsmpegVideoPlayer?: JSMpeg.VideoElement;
|
||||
@@ -262,7 +272,8 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
||||
response = await homeAssistantSignPath(
|
||||
this.hass,
|
||||
`/api/frigate/${this.clientId}` + `/jsmpeg/${this.cameraName}`,
|
||||
URL_SIGN_EXPIRY_SECONDS);
|
||||
URL_SIGN_EXPIRY_SECONDS,
|
||||
);
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
return null;
|
||||
@@ -279,11 +290,30 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
||||
*/
|
||||
protected _createJSMPEGPlayer(): JSMpeg.VideoElement {
|
||||
let videoDecoded = false;
|
||||
|
||||
const jsmpegOptions = {
|
||||
pauseWhenHidden: false,
|
||||
protocols: [],
|
||||
audio: false,
|
||||
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;
|
||||
dispatchMediaShowEvent(this, this._jsmpegCanvasElement);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Override with user-specified options.
|
||||
Object.assign(jsmpegOptions, this.jsmpegConfig?.options);
|
||||
|
||||
return new JSMpeg.VideoElement(
|
||||
this,
|
||||
this._jsmpegURL,
|
||||
{
|
||||
preserveDrawingBuffer: true,
|
||||
canvas: this._jsmpegCanvasElement,
|
||||
hooks: {
|
||||
play: () => {
|
||||
@@ -294,21 +324,7 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
pauseWhenHidden: false,
|
||||
protocols: [],
|
||||
audio: false,
|
||||
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;
|
||||
dispatchMediaShowEvent(this, this._jsmpegCanvasElement);
|
||||
}
|
||||
},
|
||||
},
|
||||
jsmpegOptions,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+31
-5
@@ -127,11 +127,13 @@ const actionSchema = z.union([
|
||||
]);
|
||||
export type ActionType = z.infer<typeof actionSchema>;
|
||||
|
||||
const actionBaseSchema = z.object({
|
||||
tap_action: actionSchema.optional(),
|
||||
hold_action: actionSchema.optional(),
|
||||
double_tap_action: actionSchema.optional(),
|
||||
}).passthrough();
|
||||
const actionBaseSchema = z
|
||||
.object({
|
||||
tap_action: actionSchema.optional(),
|
||||
hold_action: actionSchema.optional(),
|
||||
double_tap_action: actionSchema.optional(),
|
||||
})
|
||||
.passthrough();
|
||||
export type Actions = z.infer<typeof actionBaseSchema>;
|
||||
|
||||
const actionsSchema = z.object({
|
||||
@@ -369,11 +371,35 @@ const webrtcConfigSchema = z
|
||||
.optional();
|
||||
export type WebRTCConfig = z.infer<typeof webrtcConfigSchema>;
|
||||
|
||||
const jsmpegConfigSchema = z
|
||||
.object({
|
||||
options: z
|
||||
.object({
|
||||
// https://github.com/phoboslab/jsmpeg#usage
|
||||
audio: z.boolean().optional(),
|
||||
video: z.boolean().optional(),
|
||||
pauseWhenHidden: z.boolean().optional(),
|
||||
disableGl: z.boolean().optional(),
|
||||
disableWebAssembly: z.boolean().optional(),
|
||||
preserveDrawingBuffer: z.boolean().optional(),
|
||||
progressive: z.boolean().optional(),
|
||||
throttled: z.boolean().optional(),
|
||||
chunkSize: z.number().optional(),
|
||||
maxAudioLag: z.number().optional(),
|
||||
videoBufferSize: z.number().optional(),
|
||||
audioBufferSize: z.number().optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.optional();
|
||||
export type JSMPEGConfig = z.infer<typeof jsmpegConfigSchema>;
|
||||
|
||||
const liveConfigSchema = z
|
||||
.object({
|
||||
provider: z.enum(LIVE_PROVIDERS).default(liveConfigDefault.provider),
|
||||
preload: z.boolean().default(liveConfigDefault.preload),
|
||||
webrtc: webrtcConfigSchema,
|
||||
jsmpeg: jsmpegConfigSchema,
|
||||
})
|
||||
.merge(actionsSchema)
|
||||
.default(liveConfigDefault);
|
||||
|
||||
Reference in New Issue
Block a user