Rename live providers to avoid WebRTC confusion
This commit is contained in:
+28
-23
@@ -13,7 +13,7 @@ import {
|
||||
JSMPEGConfig,
|
||||
LiveConfig,
|
||||
MediaShowInfo,
|
||||
WebRTCConfig,
|
||||
WebRTCCardConfig,
|
||||
FrigateCardError,
|
||||
FrigateCardMediaPlayer,
|
||||
LiveOverrides,
|
||||
@@ -635,10 +635,13 @@ export class FrigateCardLiveProvider extends LitElement {
|
||||
|
||||
protected _getResolvedProvider(): LiveProvider {
|
||||
if (this.cameraConfig?.live_provider === 'auto') {
|
||||
if (this.cameraConfig?.webrtc?.entity || this.cameraConfig?.webrtc?.url) {
|
||||
return 'webrtc';
|
||||
if (
|
||||
this.cameraConfig?.webrtc_card?.entity ||
|
||||
this.cameraConfig?.webrtc_card?.url
|
||||
) {
|
||||
return 'webrtc-card';
|
||||
} else if (this.cameraConfig?.camera_entity) {
|
||||
return 'frigate';
|
||||
return 'ha';
|
||||
} else if (this.cameraConfig?.camera_name) {
|
||||
return 'frigate-jsmpeg';
|
||||
}
|
||||
@@ -665,21 +668,21 @@ export class FrigateCardLiveProvider extends LitElement {
|
||||
const provider = this._getResolvedProvider();
|
||||
|
||||
return html`
|
||||
${provider == 'frigate'
|
||||
? html` <frigate-card-live-frigate
|
||||
${provider == 'ha'
|
||||
? html` <frigate-card-live-ha
|
||||
${ref(this._providerRef)}
|
||||
.hass=${this.hass}
|
||||
.cameraEntity=${this.cameraConfig.camera_entity}
|
||||
>
|
||||
</frigate-card-live-frigate>`
|
||||
: provider == 'webrtc'
|
||||
? html`<frigate-card-live-webrtc
|
||||
</frigate-card-live-ha>`
|
||||
: provider == 'webrtc-card'
|
||||
? html`<frigate-card-live-webrtc-card
|
||||
${ref(this._providerRef)}
|
||||
.hass=${this.hass}
|
||||
.cameraConfig=${this.cameraConfig}
|
||||
.webRTCConfig=${this.liveConfig.webrtc}
|
||||
.webRTCConfig=${this.liveConfig.webrtc_card}
|
||||
>
|
||||
</frigate-card-live-webrtc>`
|
||||
</frigate-card-live-webrtc-card>`
|
||||
: html` <frigate-card-live-jsmpeg
|
||||
${ref(this._providerRef)}
|
||||
.hass=${this.hass}
|
||||
@@ -691,7 +694,7 @@ export class FrigateCardLiveProvider extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
@customElement('frigate-card-live-frigate')
|
||||
@customElement('frigate-card-live-ha')
|
||||
export class FrigateCardLiveFrigate extends LitElement {
|
||||
@property({ attribute: false })
|
||||
protected hass?: HomeAssistant & ExtendedHomeAssistant;
|
||||
@@ -763,12 +766,12 @@ export class FrigateCardLiveFrigate extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
// Create a wrapper for the WebRTC element
|
||||
// Create a wrapper for AlexxIT's WebRTC card
|
||||
// - https://github.com/AlexxIT/WebRTC
|
||||
@customElement('frigate-card-live-webrtc')
|
||||
export class FrigateCardLiveWebRTC extends LitElement {
|
||||
@customElement('frigate-card-live-webrtc-card')
|
||||
export class FrigateCardLiveWebRTCCard extends LitElement {
|
||||
@property({ attribute: false, hasChanged: contentsChanged })
|
||||
protected webRTCConfig?: WebRTCConfig;
|
||||
protected webRTCConfig?: WebRTCCardConfig;
|
||||
|
||||
@property({ attribute: false })
|
||||
protected cameraConfig?: CameraConfig;
|
||||
@@ -776,7 +779,7 @@ export class FrigateCardLiveWebRTC extends LitElement {
|
||||
protected hass?: HomeAssistant & ExtendedHomeAssistant;
|
||||
|
||||
// A task to await the load of the WebRTC component.
|
||||
protected _webrtcTask = new Task(this, this._getWebRTCElement, () => [1]);
|
||||
protected _webrtcTask = new Task(this, this._getWebRTCCardElement, () => [1]);
|
||||
|
||||
/**
|
||||
* Play the video.
|
||||
@@ -826,7 +829,9 @@ export class FrigateCardLiveWebRTC extends LitElement {
|
||||
return this.renderRoot?.querySelector('#video') as HTMLVideoElement | null;
|
||||
}
|
||||
|
||||
protected async _getWebRTCElement(): Promise<CustomElementConstructor | undefined> {
|
||||
protected async _getWebRTCCardElement(): Promise<
|
||||
CustomElementConstructor | undefined
|
||||
> {
|
||||
await customElements.whenDefined('webrtc-camera');
|
||||
return customElements.get('webrtc-camera');
|
||||
}
|
||||
@@ -848,10 +853,10 @@ export class FrigateCardLiveWebRTC extends LitElement {
|
||||
// then take values from the camera configuration instead (if there are
|
||||
// any).
|
||||
if (!config.url) {
|
||||
config.url = this.cameraConfig?.webrtc?.url;
|
||||
config.url = this.cameraConfig?.webrtc_card?.url;
|
||||
}
|
||||
if (!config.entity) {
|
||||
config.entity = this.cameraConfig?.webrtc?.entity;
|
||||
config.entity = this.cameraConfig?.webrtc_card?.entity;
|
||||
}
|
||||
webrtc.setConfig(config);
|
||||
webrtc.hass = this.hass;
|
||||
@@ -874,7 +879,7 @@ export class FrigateCardLiveWebRTC extends LitElement {
|
||||
this,
|
||||
e instanceof FrigateCardError
|
||||
? (e as FrigateCardError).message
|
||||
: localize('error.webrtc_reported_error') + ': ' + (e as Error).message,
|
||||
: localize('error.webrtc_card_reported_error') + ': ' + (e as Error).message,
|
||||
);
|
||||
}
|
||||
return html`${webrtcElement}`;
|
||||
@@ -884,8 +889,8 @@ export class FrigateCardLiveWebRTC extends LitElement {
|
||||
// load, but yet still have the card load be followed by the updated()
|
||||
// lifecycle callback (unlike just using `until`).
|
||||
return html`${this._webrtcTask.render({
|
||||
initial: () => renderProgressIndicator(localize('error.webrtc_waiting')),
|
||||
pending: () => renderProgressIndicator(localize('error.webrtc_waiting')),
|
||||
initial: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
|
||||
pending: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
|
||||
error: (e: unknown) => dispatchErrorMessageEvent(this, (e as Error).message),
|
||||
complete: () => render(),
|
||||
})}`;
|
||||
|
||||
+94
-7
@@ -7,14 +7,13 @@ import {
|
||||
CONF_CAMERAS_ARRAY_LABEL,
|
||||
CONF_CAMERAS_ARRAY_LIVE_PROVIDER,
|
||||
CONF_CAMERAS_ARRAY_URL,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_ENTITY,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_URL,
|
||||
CONF_CAMERAS_ARRAY_ZONE,
|
||||
CONF_EVENT_VIEWER_AUTO_PLAY,
|
||||
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE,
|
||||
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE,
|
||||
CONF_IMAGE_SRC,
|
||||
CONF_LIVE_PRELOAD,
|
||||
CONF_LIVE_WEBRTC_CARD,
|
||||
CONF_MENU,
|
||||
CONF_MENU_BUTTON_SIZE,
|
||||
CONF_MENU_MODE,
|
||||
@@ -142,7 +141,7 @@ const isNotObject = function (value: unknown) {
|
||||
* @returns A number or undefined.
|
||||
*/
|
||||
const toNumberOrIgnore = function (value: unknown) {
|
||||
return isNaN(value as number) ? undefined : Number(value)
|
||||
return isNaN(value as number) ? undefined : Number(value);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -198,6 +197,86 @@ const upgradeMoveTo = function (
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Upgrade a property by changing it if it is present.
|
||||
* @param path The property path.
|
||||
* @param transform A callback that transforms the old value to the new value,
|
||||
* if undefined is returned the property is removed.
|
||||
* @returns `true` if the configuration was modified.
|
||||
*/
|
||||
const upgradeChangeIfPresent = function (
|
||||
path: string,
|
||||
transform: (valueIn: unknown) => unknown,
|
||||
): (obj: RawFrigateCardConfig) => boolean {
|
||||
return function (obj: RawFrigateCardConfig): boolean {
|
||||
const oldValue = getConfigValue(obj, path);
|
||||
if (oldValue !== undefined) {
|
||||
const newValue = transform(oldValue);
|
||||
if (newValue === undefined) {
|
||||
deleteConfigValue(obj, path);
|
||||
return true;
|
||||
} else if (newValue !== oldValue) {
|
||||
setConfigValue(obj, path, newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Upgrade by moving a property from one location to another, and moving a
|
||||
* property specified in a top-level overrides object.
|
||||
* @param oldPath The old property path.
|
||||
* @param newPath The new property path.
|
||||
* @param transform An optional transform for the value.
|
||||
* @returns A function that returns `true` if the configuration was modified.
|
||||
*/
|
||||
const upgradeMoveToWithOverrides = function (
|
||||
oldPath: string,
|
||||
newPath: string,
|
||||
transform?: (valueIn: unknown) => unknown,
|
||||
): (obj: RawFrigateCardConfig) => boolean {
|
||||
return function (obj: RawFrigateCardConfig): boolean {
|
||||
let modified = upgradeMoveTo(oldPath, newPath, transform)(obj);
|
||||
modified =
|
||||
upgradeArrayValue(
|
||||
CONF_OVERRIDES,
|
||||
upgradeMoveTo(oldPath, newPath, transform),
|
||||
(obj) => obj.overrides as RawFrigateCardConfig | undefined,
|
||||
)(obj) || modified;
|
||||
return modified;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a path to an array, apply an upgrade to each object in the array.
|
||||
* @param arrayPath The path to the array to upgrade.
|
||||
* @param upgrade A function that applies an upgrade to an object.
|
||||
* @param getObject A optional function that takes an item in the array and
|
||||
* returns the object to modify within it.
|
||||
* @returns A function that returns `true` if the configuration was modified.
|
||||
*/
|
||||
const upgradeArrayValue = function (
|
||||
arrayPath: string,
|
||||
upgrade: (obj: RawFrigateCardConfig) => boolean,
|
||||
getObject?: (obj: RawFrigateCardConfig) => RawFrigateCardConfig | undefined,
|
||||
): (obj: RawFrigateCardConfig) => boolean {
|
||||
return function (obj: RawFrigateCardConfig): boolean {
|
||||
let modified = false;
|
||||
const array = getConfigValue(obj, arrayPath);
|
||||
if (Array.isArray(array)) {
|
||||
array.forEach((item) => {
|
||||
const object = getObject ? getObject(item) : item;
|
||||
if (object && typeof object === 'object') {
|
||||
modified = upgrade(object) || modified;
|
||||
}
|
||||
});
|
||||
}
|
||||
return modified;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Upgrade from a singular camera model to multiple.
|
||||
* @param key A string key.
|
||||
@@ -220,8 +299,8 @@ const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) =>
|
||||
'frigate.label': CONF_CAMERAS_ARRAY_LABEL,
|
||||
'frigate.url': CONF_CAMERAS_ARRAY_URL,
|
||||
'frigate.zone': CONF_CAMERAS_ARRAY_ZONE,
|
||||
'live.webrtc.entity': CONF_CAMERAS_ARRAY_WEBRTC_ENTITY,
|
||||
'live.webrtc.url': CONF_CAMERAS_ARRAY_WEBRTC_URL,
|
||||
'live.webrtc.entity': `cameras.#.webrtc.entity`,
|
||||
'live.webrtc.url': `cameras.#.webrtc.url`,
|
||||
'live.provider': CONF_CAMERAS_ARRAY_LIVE_PROVIDER,
|
||||
};
|
||||
Object.keys(imports).forEach((key) => {
|
||||
@@ -278,7 +357,7 @@ const UPGRADES = [
|
||||
upgradeMoveTo('live_provider', 'live.provider'),
|
||||
upgradeMoveTo('live_preload', CONF_LIVE_PRELOAD),
|
||||
upgradeMoveTo('webrtc', 'live.webrtc'),
|
||||
upgradeMoveTo('autoplay_clip', "event_viewer.autoplay_clip"),
|
||||
upgradeMoveTo('autoplay_clip', 'event_viewer.autoplay_clip'),
|
||||
upgradeMoveTo('controls.nextprev', CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE),
|
||||
upgradeMoveTo('controls.nextprev_size', CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE),
|
||||
upgradeMoveTo('menu_mode', CONF_MENU_MODE),
|
||||
@@ -289,9 +368,17 @@ const UPGRADES = [
|
||||
// v2.0.0 -> v2.1.0
|
||||
upgradeMoveTo('update_entities', CONF_VIEW_UPDATE_ENTITIES),
|
||||
|
||||
// v2.1.0 -> v3.0.0
|
||||
// v2.1.0 -> v3.0.0-rc.1
|
||||
upgradeToMultipleCameras(),
|
||||
updateMenuConditionToMenuOverride(),
|
||||
upgradeMoveTo('view.timeout', CONF_VIEW_TIMEOUT_SECONDS, toNumberOrIgnore),
|
||||
upgradeMoveTo('event_viewer.autoplay_clip', CONF_EVENT_VIEWER_AUTO_PLAY),
|
||||
|
||||
// v3.0.0-rc.1 -> v3.0.0-rc.2
|
||||
upgradeArrayValue(
|
||||
CONF_CAMERAS,
|
||||
upgradeChangeIfPresent('live_provider', (val) => (val === 'frigate' ? 'ha' : val)),
|
||||
),
|
||||
upgradeArrayValue(CONF_CAMERAS, upgradeMoveTo('webrtc', 'webrtc_card')),
|
||||
upgradeMoveToWithOverrides('live.webrtc', CONF_LIVE_WEBRTC_CARD),
|
||||
];
|
||||
|
||||
+4
-6
@@ -13,9 +13,9 @@ export const CONF_CAMERAS_ARRAY_ZONE = `${CONF_CAMERAS}.#.zone` as const;
|
||||
export const CONF_CAMERAS_ARRAY_ID = `${CONF_CAMERAS}.#.id` as const;
|
||||
export const CONF_CAMERAS_ARRAY_TITLE = `${CONF_CAMERAS}.#.title` as const;
|
||||
export const CONF_CAMERAS_ARRAY_ICON = `${CONF_CAMERAS}.#.icon` as const;
|
||||
export const CONF_CAMERAS_ARRAY_WEBRTC_ENTITY =
|
||||
`${CONF_CAMERAS}.#.webrtc.entity` as const;
|
||||
export const CONF_CAMERAS_ARRAY_WEBRTC_URL = `${CONF_CAMERAS}.#.webrtc.url` as const;
|
||||
export const CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY =
|
||||
`${CONF_CAMERAS}.#.webrtc_card.entity` as const;
|
||||
export const CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL = `${CONF_CAMERAS}.#.webrtc_card.url` as const;
|
||||
export const CONF_CAMERAS_ARRAY_LIVE_PROVIDER =
|
||||
`${CONF_CAMERAS}.#.live_provider` as const;
|
||||
|
||||
@@ -73,9 +73,7 @@ export const CONF_LIVE_LAZY_LOAD = `${CONF_LIVE}.lazy_load` as const;
|
||||
export const CONF_LIVE_LAZY_UNLOAD = `${CONF_LIVE}.lazy_unload` as const;
|
||||
export const CONF_LIVE_PRELOAD = `${CONF_LIVE}.preload` as const;
|
||||
export const CONF_LIVE_TRANSITION_EFFECT = `${CONF_LIVE}.transition_effect` as const;
|
||||
export const CONF_LIVE_WEBRTC = `${CONF_LIVE}.webrtc` as const;
|
||||
export const CONF_LIVE_WEBRTC_ENTITY = `${CONF_LIVE_WEBRTC}.entity` as const;
|
||||
export const CONF_LIVE_WEBRTC_URL = `${CONF_LIVE_WEBRTC}.url` as const;
|
||||
export const CONF_LIVE_WEBRTC_CARD = `${CONF_LIVE}.webrtc_card` as const;
|
||||
|
||||
export const CONF_IMAGE = 'image' as const;
|
||||
export const CONF_IMAGE_REFRESH_SECONDS = `${CONF_IMAGE}.refresh_seconds` as const;
|
||||
|
||||
+6
-6
@@ -22,8 +22,8 @@ import {
|
||||
CONF_CAMERAS_ARRAY_LIVE_PROVIDER,
|
||||
CONF_CAMERAS_ARRAY_TITLE,
|
||||
CONF_CAMERAS_ARRAY_URL,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_ENTITY,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_URL,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL,
|
||||
CONF_CAMERAS_ARRAY_ZONE,
|
||||
CONF_DIMENSIONS_ASPECT_RATIO,
|
||||
CONF_DIMENSIONS_ASPECT_RATIO_MODE,
|
||||
@@ -491,9 +491,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
const liveProviders = new Map([
|
||||
['', ''],
|
||||
['auto', localize('config.cameras.live_providers.auto')],
|
||||
['frigate', localize('config.cameras.live_providers.frigate')],
|
||||
['ha', localize('config.cameras.live_providers.ha')],
|
||||
['frigate-jsmpeg', localize('config.cameras.live_providers.frigate-jsmpeg')],
|
||||
['webrtc', localize('config.cameras.live_providers.webrtc')],
|
||||
['webrtc-card', localize('config.cameras.live_providers.webrtc-card')],
|
||||
]);
|
||||
|
||||
// Make a new config and update the editor with changes on it,
|
||||
@@ -605,11 +605,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
getArrayConfigPath(CONF_CAMERAS_ARRAY_ID, cameraIndex),
|
||||
)}
|
||||
${this._renderDropdown(
|
||||
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_ENTITY, cameraIndex),
|
||||
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY, cameraIndex),
|
||||
cameraEntities,
|
||||
)}
|
||||
${this._renderStringInput(
|
||||
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_URL, cameraIndex),
|
||||
getArrayConfigPath(CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL, cameraIndex),
|
||||
)}
|
||||
</div>`
|
||||
: ``}
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
"live_provider": "Live view provider for this camera",
|
||||
"live_providers": {
|
||||
"auto": "Automatic",
|
||||
"frigate": "Frigate",
|
||||
"ha": "Home Assistant (i.e. HLS, LL-HLS, WebRTC native)",
|
||||
"frigate-jsmpeg": "Frigate JSMpeg",
|
||||
"webrtc": "WebRTC"
|
||||
"webrtc-card": "WebRTC Card (i.e. AlexxIT's WebRTC Card)"
|
||||
},
|
||||
"webrtc": {
|
||||
"entity": "WebRTC Camera Entity (Not a Frigate camera)",
|
||||
"url": "WebRTC Camera URL"
|
||||
"webrtc_card": {
|
||||
"entity": "WebRTC Card Camera Entity (Not a Frigate camera)",
|
||||
"url": "WebRTC Card Camera URL"
|
||||
},
|
||||
"zone": "Frigate zone"
|
||||
},
|
||||
@@ -210,8 +210,8 @@
|
||||
"invalid_configuration": "Invalid configuration",
|
||||
"invalid_configuration_no_hint": "No location hint available (bad or missing type?)",
|
||||
"upgrade_available": "An automated card configuration upgrade is available, please visit the visual card editor",
|
||||
"webrtc_reported_error": "WebRTC component reported an error",
|
||||
"webrtc_waiting": "Waiting for WebRTC Card to load ...",
|
||||
"webrtc_card_reported_error": "WebRTC card reported an error",
|
||||
"webrtc_card_waiting": "Waiting for WebRTC card to load ...",
|
||||
"no_cameras": "No valid cameras found, you must configure at least one camera entry",
|
||||
"no_camera_id": "Could not determine camera id for the following camera, may need to set 'id' parameter manually",
|
||||
"duplicate_camera_id": "Duplicate Frigate camera id for the following camera, use the 'id' parameter to uniquely identify cameras",
|
||||
|
||||
+6
-6
@@ -53,7 +53,7 @@ const FRIGATE_MENU_MODES = [
|
||||
'above',
|
||||
'below',
|
||||
] as const;
|
||||
const LIVE_PROVIDERS = ['auto', 'frigate', 'frigate-jsmpeg', 'webrtc'] as const;
|
||||
const LIVE_PROVIDERS = ['auto', 'ha', 'frigate-jsmpeg', 'webrtc-card'] as const;
|
||||
export type LiveProvider = typeof LIVE_PROVIDERS[number];
|
||||
|
||||
export class FrigateCardError extends Error {}
|
||||
@@ -281,7 +281,7 @@ export const cameraConfigDefault = {
|
||||
client_id: 'frigate' as const,
|
||||
live_provider: 'auto' as const,
|
||||
};
|
||||
const webrtcCameraConfigSchema = z.object({
|
||||
const webrtcCardCameraConfigSchema = z.object({
|
||||
entity: z.string().optional(),
|
||||
url: z.string().optional(),
|
||||
});
|
||||
@@ -306,7 +306,7 @@ const cameraConfigSchema = z
|
||||
id: z.string().optional(),
|
||||
|
||||
// Camera identifiers for WebRTC.
|
||||
webrtc: webrtcCameraConfigSchema.optional(),
|
||||
webrtc_card: webrtcCardCameraConfigSchema.optional(),
|
||||
})
|
||||
.default(cameraConfigDefault);
|
||||
export type CameraConfig = z.infer<typeof cameraConfigSchema>;
|
||||
@@ -484,8 +484,8 @@ const liveConfigDefault = {
|
||||
},
|
||||
};
|
||||
|
||||
const webrtcConfigSchema = webrtcCameraConfigSchema.passthrough().optional();
|
||||
export type WebRTCConfig = z.infer<typeof webrtcConfigSchema>;
|
||||
const webrtcCardConfigSchema = webrtcCardCameraConfigSchema.passthrough().optional();
|
||||
export type WebRTCCardConfig = z.infer<typeof webrtcCardConfigSchema>;
|
||||
|
||||
const jsmpegConfigSchema = z
|
||||
.object({
|
||||
@@ -512,7 +512,7 @@ export type JSMPEGConfig = z.infer<typeof jsmpegConfigSchema>;
|
||||
|
||||
const liveOverridableConfigSchema = z
|
||||
.object({
|
||||
webrtc: webrtcConfigSchema,
|
||||
webrtc_card: webrtcCardConfigSchema,
|
||||
jsmpeg: jsmpegConfigSchema,
|
||||
controls: z
|
||||
.object({
|
||||
|
||||
Reference in New Issue
Block a user