@camera.ui/server 2.2.5-beta.2 → 2.2.5-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/interface/assets/{404-BDvtK1qR.js → 404-YZOLos9r.js} +1 -1
- package/dist/interface/assets/{About-B4A35rRx.js → About-HtxMc8JZ.js} +1 -1
- package/dist/interface/assets/Assistant-bB8RBo-m.js +1 -0
- package/dist/interface/assets/Automation-D3DcUyui.js +3 -0
- package/dist/interface/assets/{AutomationImport-CEJdhE_d.js → AutomationImport-Dp_hT6hQ.js} +2 -2
- package/dist/interface/assets/AutomationStore-BKR7GXMk.js +2 -0
- package/dist/interface/assets/{AutomationStoreDetail-BenRMMtV.js → AutomationStoreDetail-B9yh51WQ.js} +2 -2
- package/dist/interface/assets/Automations-BdZZW2eN.js +2 -0
- package/dist/interface/assets/Camera-Ct7ndOxr.js +2 -0
- package/dist/interface/assets/{CameraConsole-D24yXOQn.js → CameraConsole-BI93OaRt.js} +2 -2
- package/dist/interface/assets/Cameras-Ctub8sVt.js +651 -0
- package/dist/interface/assets/Camview-BjQdTHNh.js +1 -0
- package/dist/interface/assets/{CertificateUpload-26LAL4MY.js → CertificateUpload-xW55NA1Q.js} +1 -1
- package/dist/interface/assets/Config-CBTbYd5v.js +2 -0
- package/dist/interface/assets/{ConfigActionAssistant-Cl_kr3hp.js → ConfigActionAssistant-B488rOp5.js} +1 -1
- package/dist/interface/assets/{ConfigActionCameraControl-CL4vXcNe.js → ConfigActionCameraControl-ZMUuBxOs.js} +1 -1
- package/dist/interface/assets/{ConfigActionDelay-DtPgmqWh.js → ConfigActionDelay-BJ11xvOW.js} +1 -1
- package/dist/interface/assets/{ConfigActionHttp-DnkZTP5l.js → ConfigActionHttp-DOUo69OR.js} +1 -1
- package/dist/interface/assets/{ConfigActionImageInput-3svn6YP9.js → ConfigActionImageInput-BMzuVZW9.js} +1 -1
- package/dist/interface/assets/{ConfigActionMqtt-BTsFTLgm.js → ConfigActionMqtt-Co_uksca.js} +1 -1
- package/dist/interface/assets/{ConfigActionNotification-Cr4xJrZp.js → ConfigActionNotification-CcZkstYx.js} +1 -1
- package/dist/interface/assets/{ConfigActionNotificationControl-Cxkb_g8p.js → ConfigActionNotificationControl--VeucoTw.js} +1 -1
- package/dist/interface/assets/{ConfigActionOutput-WTr7FGf_.js → ConfigActionOutput-CyDa1LGA.js} +1 -1
- package/dist/interface/assets/{ConfigActionPlugin-BpcJepbD.js → ConfigActionPlugin-Kfg3ZEQF.js} +1 -1
- package/dist/interface/assets/{ConfigActionSensor-BgD_F-hD.js → ConfigActionSensor-DhAF0HPw.js} +1 -1
- package/dist/interface/assets/{ConfigActionSnapshot-DjR-Z08N.js → ConfigActionSnapshot-zMe3SPvW.js} +1 -1
- package/dist/interface/assets/{ConfigActionVariable-gPuPbjpm.js → ConfigActionVariable-BE5q3NwY.js} +1 -1
- package/dist/interface/assets/{ConfigConditionIfElse-CUHKJmPx.js → ConfigConditionIfElse-BNIRtSVD.js} +1 -1
- package/dist/interface/assets/{ConfigConditionSensorState-D-gPRqMu.js → ConfigConditionSensorState-DTNd-SzI.js} +1 -1
- package/dist/interface/assets/{ConfigConditionSwitch-BRf1T5tJ.js → ConfigConditionSwitch-BU5wWMU1.js} +1 -1
- package/dist/interface/assets/{ConfigConditionTime-BC0n6sWO.js → ConfigConditionTime-KXTCIVIV.js} +1 -1
- package/dist/interface/assets/{ConfigSensorValueInput-BUHapx4M.js → ConfigSensorValueInput-BC1FpMm-.js} +1 -1
- package/dist/interface/assets/{ConfigTriggerDetection-Byd6SLGg.js → ConfigTriggerDetection-hIN1hi53.js} +1 -1
- package/dist/interface/assets/ConfigTriggerGeofence-Bl2ZacbY.js +1 -0
- package/dist/interface/assets/{ConfigTriggerManual-B2dWcFrl.js → ConfigTriggerManual-C5vwxS-e.js} +1 -1
- package/dist/interface/assets/{ConfigTriggerMqtt-B_aUDBu4.js → ConfigTriggerMqtt-B4PtWC3E.js} +1 -1
- package/dist/interface/assets/{ConfigTriggerSchedule-DAZo1PLj.js → ConfigTriggerSchedule-BZzUdGBa.js} +1 -1
- package/dist/interface/assets/{ConfigTriggerSensor-BCqAiPu4.js → ConfigTriggerSensor-D18nwMsj.js} +1 -1
- package/dist/interface/assets/{ConfigTriggerSystem-DuBydCiq.js → ConfigTriggerSystem-BhygWLB4.js} +1 -1
- package/dist/interface/assets/{ConfigTriggerWebhook-DDsnpwJr.js → ConfigTriggerWebhook-yyuBuhLD.js} +1 -1
- package/dist/interface/assets/Console-Cfk9MA9m.js +1 -0
- package/dist/interface/assets/CuiAssistantConversation-BHK_i56I.js +5 -0
- package/dist/interface/assets/CuiAssistantConversation-lkpZg3ML.css +1 -0
- package/dist/interface/assets/{CuiAutomationRunsDialog-C_sMg7E1.js → CuiAutomationRunsDialog-B0ohEHw0.js} +1 -1
- package/dist/interface/assets/{CuiBottomSheet-D_0LrjA_.js → CuiBottomSheet-DWefGWK2.js} +1 -1
- package/dist/interface/assets/CuiBottomSheet-NgX7VFao.js +1 -0
- package/dist/interface/assets/CuiCameraPipCard-C2qaGJlH.js +1 -0
- package/dist/interface/assets/CuiCameraRecordings-BTD-CQAg.js +1 -0
- package/dist/interface/assets/{CuiCameraShares-BIUB1xMa.js → CuiCameraShares-DcqOcePX.js} +1 -1
- package/dist/interface/assets/{CuiCameraTable-D-UhqHk4.js → CuiCameraTable-BOkfp_5M.js} +2 -2
- package/dist/interface/assets/CuiCameraTable-KPk46Xcl.js +1 -0
- package/dist/interface/assets/{CuiChartTable-CSK4Mzn3.js → CuiChartTable-DP38uBwK.js} +1 -1
- package/dist/interface/assets/{CuiConsole-DAbJXJBq.js → CuiConsole-C7xE_nQg.js} +2 -2
- package/dist/interface/assets/{CuiDataTable-DgcJsG-K.js → CuiDataTable-CsqH-RB1.js} +1 -1
- package/dist/interface/assets/CuiLightControl-ChGYpQAK.js +1 -0
- package/dist/interface/assets/{CuiLightControl-DFrZm_sv.css → CuiLightControl-D9sm8NZb.css} +1 -1
- package/dist/interface/assets/{CuiList-HdsA9vV1.js → CuiList-DJp0__mV.js} +1 -1
- package/dist/interface/assets/CuiPluginCard-CWImTZ6l.js +2 -0
- package/dist/interface/assets/{CuiPluginCategoryChip-C7R1jP7r.js → CuiPluginCategoryChip-Ch_upS6Y.js} +1 -1
- package/dist/interface/assets/{CuiPluginOAuthButton-BJJw0IaC.js → CuiPluginOAuthButton-DEQ9xILN.js} +2 -2
- package/dist/interface/assets/{CuiPluginTrustBadge-Bmm1qYdC.js → CuiPluginTrustBadge-sVWdvHcM.js} +1 -1
- package/dist/interface/assets/{CuiQRCode-DTSEFMBt.js → CuiQRCode-DqSF4SkD.js} +1 -1
- package/dist/interface/assets/CuiSchema-ytExUVhI.js +1 -0
- package/dist/interface/assets/CuiTopNavbarItem-B_KWykgq.js +1 -0
- package/dist/interface/assets/Faces-Cb6XMxDC.js +1 -0
- package/dist/interface/assets/FirstSteps-QNYTkEJo.js +1 -0
- package/dist/interface/assets/Floorplan-DbqADtN1.js +1 -0
- package/dist/interface/assets/Instances-DrMzPD65.js +1 -0
- package/dist/interface/assets/{Logs-BjcfuMQV.js → Logs-BSPT80vP.js} +2 -2
- package/dist/interface/assets/{Menu-BjjnSgdP.js → Menu-HHtuhIS2.js} +1 -1
- package/dist/interface/assets/Metrics-CqhUnVRA.js +12 -0
- package/dist/interface/assets/{OAuthDeviceFlow-9v-Czy_u.js → OAuthDeviceFlow-Bn1nlWNa.js} +1 -1
- package/dist/interface/assets/Plugin-DyOg_fbg.js +1 -0
- package/dist/interface/assets/{PluginConsole-C7sO42RG.js → PluginConsole-Cv-uhnPY.js} +2 -2
- package/dist/interface/assets/PluginDetail-cpOz7FkA.js +2 -0
- package/dist/interface/assets/{PluginSchema-D0eL9H-b.js → PluginSchema-DW3TGeTM.js} +1 -1
- package/dist/interface/assets/PluginSearch-BgecD9Ob.js +2 -0
- package/dist/interface/assets/PluginSearch-C8xHKikH.js +1 -0
- package/dist/interface/assets/{PluginUpdateProgress--MM9D8hs.js → PluginUpdateProgress-n6q6vzyd.js} +1 -1
- package/dist/interface/assets/Plugins-CuujWEtM.js +1 -0
- package/dist/interface/assets/{RecentEventsFilter-CvIJS8Se.js → RecentEventsFilter-CTR5JK_P.js} +1 -1
- package/dist/interface/assets/Recordings-ths9khZr.js +1 -0
- package/dist/interface/assets/SensorEdit-BzoIH7QC.js +1 -0
- package/dist/interface/assets/{SensorHistory-Efw0bZ-X.js → SensorHistory-9CdOpCPs.js} +1 -1
- package/dist/interface/assets/Sensors-CK5uExfU.js +2 -0
- package/dist/interface/assets/Settings-DN5hFtw_.js +1 -0
- package/dist/interface/assets/SettingsAccount-BCrmon5O.js +1 -0
- package/dist/interface/assets/SettingsAccount-CSy1BAIH.js +1 -0
- package/dist/interface/assets/{SettingsAccount-si-6gWl5.css → SettingsAccount-CY8YE_cy.css} +1 -1
- package/dist/interface/assets/SettingsAppearance-BY1xQMx4.js +1 -0
- package/dist/interface/assets/SettingsAppearance-h_XPZfQl.js +1 -0
- package/dist/interface/assets/SettingsAssistant-D8FmVbUL.js +1 -0
- package/dist/interface/assets/{SettingsBackup-BqKBKis5.js → SettingsBackup-D_weokqu.js} +1 -1
- package/dist/interface/assets/{SettingsList-BU191rmt.js → SettingsList-Bq24WTDU.js} +1 -1
- package/dist/interface/assets/SettingsMqtt-DCkLIYpF.js +1 -0
- package/dist/interface/assets/SettingsNotifications-8TZOUxg2.js +1 -0
- package/dist/interface/assets/{SettingsPermissions-sI64FPZG.js → SettingsPermissions-M8u_jrN0.js} +1 -1
- package/dist/interface/assets/{SettingsRecordings-CghrKErw.js → SettingsRecordings-C1Kp5xW_.js} +1 -1
- package/dist/interface/assets/SettingsRemote-DXlQKwlT.js +2 -0
- package/dist/interface/assets/{SettingsSystem-DP1p1Xns.js → SettingsSystem-Cetu2faJ.js} +2 -2
- package/dist/interface/assets/{SettingsUsers-Dpej-he1.js → SettingsUsers-CDwtQLdV.js} +1 -1
- package/dist/interface/assets/{Terminal-DPRPXCSt.js → Terminal-Dl-aAZME.js} +2 -2
- package/dist/interface/assets/{Training-Dwf5rXyC.css → Training-B1oQjAr8.css} +1 -1
- package/dist/interface/assets/Training-DdZjXgt1.js +1 -0
- package/dist/interface/assets/{Updates-QTvCp1aS.js → Updates-CkB1lXuo.js} +1 -1
- package/dist/interface/assets/{VariableInput-DhusSZPw.js → VariableInput-BxPj5wo6.js} +1 -1
- package/dist/interface/assets/{VariableSuggestions-Bkzz4Mv3.js → VariableSuggestions-CbizvAkz.js} +1 -1
- package/dist/interface/assets/{VersionsHandler-DjNSpSYy.js → VersionsHandler-CePyEUVO.js} +2 -2
- package/dist/interface/assets/{VirtualSensorCreate-soGT6h2c.js → VirtualSensorCreate-D_GVoeL7.js} +1 -1
- package/dist/interface/assets/Workers-7yiebNkl.js +2 -0
- package/dist/interface/assets/api-DK2Bav9D.js +4 -0
- package/dist/interface/assets/api-DTCqDA-h.css +2 -0
- package/dist/interface/assets/{api-CK2tonlH.js → api-DW2niHRN.js} +1 -1
- package/dist/interface/assets/{assistant-BEe1ExZL.js → assistant-BJ6xKcw_.js} +1 -1
- package/dist/interface/assets/{auth-QEpUGkWd.js → auth-Dc8bUpc-.js} +1 -1
- package/dist/interface/assets/{automations-BBIBV4Uu.js → automations-DXrjbArj.js} +1 -1
- package/dist/interface/assets/{cameraSources-Cm18cW9L.js → cameraSources-QJfUDOQJ.js} +1 -1
- package/dist/interface/assets/cloudHandoff-DtlquYGZ.js +1 -0
- package/dist/interface/assets/{config-vwkU8aqP.js → config-CiQDwB4t.js} +1 -1
- package/dist/interface/assets/{flowSchema-rzBroL0H.js → flowSchema-BRTZHQ1w.js} +1 -1
- package/dist/interface/assets/{intercomService-Du8V_HxF.js → intercomService-BnA-FQ0Q.js} +1 -1
- package/dist/interface/assets/{main-XHFrBKKz.css → main-BoGhBedC.css} +1 -1
- package/dist/interface/assets/main-D74mRIxc.js +3 -0
- package/dist/interface/assets/mqtt-iD9XHYO_.js +1 -0
- package/dist/interface/assets/{notifications-CN6eTJb_.js → notifications-CbAJX7RF.js} +1 -1
- package/dist/interface/assets/{plugins-DKtX7zQp.js → plugins-eIUrXNeM.js} +1 -1
- package/dist/interface/assets/rooms-BqPyo8jc.js +1 -0
- package/dist/interface/assets/{sensorIcons-ztqlMLDc.js → sensorIcons-DQVgryYP.js} +1 -1
- package/dist/interface/assets/{sensorSlots-D-uxjuv3.js → sensorSlots-BZCXtnb6.js} +1 -1
- package/dist/interface/assets/{sensors-DV2Z0IJt.js → sensors-DttBNEEt.js} +1 -1
- package/dist/interface/assets/{server-CfZnIVzn.js → server-DUFhf2c_.js} +1 -1
- package/dist/interface/assets/{theme-Bi7qdjBK.js → theme-BMmjtQ4w.js} +1 -1
- package/dist/interface/assets/{types-CNLAvgyw.js → types-5rE8Tz0_.js} +1 -1
- package/dist/interface/assets/{types-DwbeYXvn.js → types-CXw7CEzu.js} +1 -1
- package/dist/interface/assets/{types-DuwD8xp5.js → types-DWTSNJ79.js} +1 -1
- package/dist/interface/assets/ungrouped-D56FGIrg.js +1 -0
- package/dist/interface/assets/ungrouped-DHMJ9Rg1.css +1 -0
- package/dist/interface/assets/{updates-BqCH6Vr8.js → updates-TIPWXKzL.js} +1 -1
- package/dist/interface/assets/{useAppVersion-B-rmq3Bb.js → useAppVersion-BIz44Bg4.js} +1 -1
- package/dist/interface/assets/{useAssistantActions-Kf-5ijVf.js → useAssistantActions-CLkkw9kB.js} +1 -1
- package/dist/interface/assets/useBackupRestore-Crfd592q.js +1 -0
- package/dist/interface/assets/{useCameraOptions-Dt2J8sP_.js → useCameraOptions-A97teAIr.js} +1 -1
- package/dist/interface/assets/{useKeyboardInset-DtD3I2WC.js → useKeyboardInset-DXVi1dLG.js} +1 -1
- package/dist/interface/assets/{useLogsSocket-CEhUQdiY.js → useLogsSocket-BlFxVXjF.js} +1 -1
- package/dist/interface/assets/{useNavLayout-CtpYjS5W.js → useNavLayout-C5obaCNv.js} +1 -1
- package/dist/interface/assets/{usePermissions-CJzuagwD.js → usePermissions-C8hB_pG1.js} +1 -1
- package/dist/interface/assets/{usePluginUpdates-BwoWN5yb.js → usePluginUpdates-DO0-Gk4Q.js} +1 -1
- package/dist/interface/assets/{usePushRegistration-ANx4BS6_.js → usePushRegistration-BUttCraQ.js} +1 -1
- package/dist/interface/assets/{useServerRestart-7edyD8M0.js → useServerRestart-Cz9eVHUE.js} +1 -1
- package/dist/interface/assets/{useStreamStatus-DCSWHdbW.js → useStreamStatus-BhS_MCCB.js} +1 -1
- package/dist/interface/assets/{useTabSwipe-DfS3R3uP.js → useTabSwipe-D4k8lm1M.js} +1 -1
- package/dist/interface/assets/{useUpdateChannel-Cr9mSIRC.js → useUpdateChannel-D9lhfW0y.js} +1 -1
- package/dist/interface/assets/{useUpdatesSocket-B5Rm9syb.js → useUpdatesSocket-DnH9sON5.js} +1 -1
- package/dist/interface/assets/{useUserOptions-CJjImz8V.js → useUserOptions-BTRBUuE2.js} +1 -1
- package/dist/interface/assets/{vendor-cameraui-BbGOMenD.js → vendor-cameraui-QXD8jkcj.js} +26 -26
- package/dist/interface/assets/{vendor-core-tgH2YubJ.js → vendor-core-CnhnyKDl.js} +1 -1
- package/dist/interface/assets/{vendor-primevue-DNJJiEZl.js → vendor-primevue-CCUqY55W.js} +207 -207
- package/dist/interface/ha/{404-Dl6JtQWv.js → 404-DLhJqxRl.js} +1 -1
- package/dist/interface/ha/{About-wjv4kCO3.js → About-DC0i1iE4.js} +3 -3
- package/dist/interface/ha/{Assistant-Dpb4IsDC.js → Assistant-BmazMPIg.js} +821 -825
- package/dist/interface/ha/{Automation-CqTPjCUh.js → Automation-gabF9YzQ.js} +336 -336
- package/dist/interface/ha/{AutomationImport-CvdeneoU.js → AutomationImport-DaqZNs9s.js} +8 -8
- package/dist/interface/ha/{AutomationStore-bVPE68io.js → AutomationStore-DzM4huo5.js} +54 -54
- package/dist/interface/ha/{AutomationStoreDetail-BYaNUjoH.js → AutomationStoreDetail-CpzQMt_D.js} +7 -7
- package/dist/interface/ha/{Automations-BfsYh2A_.js → Automations-Dcm4Us50.js} +81 -81
- package/dist/interface/ha/{Camera-C70onr_O.js → Camera-CNK3QR7l.js} +198 -198
- package/dist/interface/ha/{CameraConsole-Dg3lV-wq.js → CameraConsole-CpcF0411.js} +5 -5
- package/dist/interface/ha/{Cameras-DpM6gt3G.js → Cameras-Cf9rwRyf.js} +293 -294
- package/dist/interface/ha/{Camview-CO_bHntH.js → Camview-BFKR2t6C.js} +87 -87
- package/dist/interface/ha/{Config-D-cpocuH.js → Config-1XH3zfr2.js} +11 -11
- package/dist/interface/ha/{ConfigActionAssistant-DVVVfVvT.js → ConfigActionAssistant-C0-NFoTB.js} +5 -5
- package/dist/interface/ha/{ConfigActionCameraControl-BPpzE9-F.js → ConfigActionCameraControl-DNSKZPSZ.js} +5 -5
- package/dist/interface/ha/{ConfigActionDelay-zU6H75hY.js → ConfigActionDelay-iZ3lPGzw.js} +1 -1
- package/dist/interface/ha/{ConfigActionHttp-BsNy03j4.js → ConfigActionHttp-DVJAcGkl.js} +3 -3
- package/dist/interface/ha/{ConfigActionImageInput-JUvNYn0w.js → ConfigActionImageInput-VVbHHHZs.js} +3 -3
- package/dist/interface/ha/{ConfigActionMqtt-PZqAKfTo.js → ConfigActionMqtt-N5OUJDzM.js} +4 -4
- package/dist/interface/ha/{ConfigActionNotification-DIL7abEm.js → ConfigActionNotification-s142tQoU.js} +6 -6
- package/dist/interface/ha/{ConfigActionNotificationControl-BQ2w5yeg.js → ConfigActionNotificationControl-Dh7kaKVP.js} +3 -3
- package/dist/interface/ha/{ConfigActionOutput-DVilKhPV.js → ConfigActionOutput-B4HHTg5C.js} +1 -1
- package/dist/interface/ha/{ConfigActionPlugin-BUfTEJQ_.js → ConfigActionPlugin-D20G2Dqf.js} +5 -5
- package/dist/interface/ha/{ConfigActionSensor-Dzp16VyX.js → ConfigActionSensor-BS3jrFaG.js} +6 -6
- package/dist/interface/ha/{ConfigActionSnapshot-CRjD5AMC.js → ConfigActionSnapshot-CInLAcwK.js} +3 -3
- package/dist/interface/ha/{ConfigActionVariable-CR8g7gEh.js → ConfigActionVariable-C5vADGNF.js} +2 -2
- package/dist/interface/ha/{ConfigConditionIfElse-CHoSgzXF.js → ConfigConditionIfElse-CPeWDD31.js} +4 -4
- package/dist/interface/ha/{ConfigConditionSensorState-Dn8_OhQe.js → ConfigConditionSensorState-BM5GmpN6.js} +6 -6
- package/dist/interface/ha/{ConfigConditionSwitch-Ds-nqWeU.js → ConfigConditionSwitch-Dmz9FduJ.js} +4 -4
- package/dist/interface/ha/{ConfigConditionTime-DWNfEluj.js → ConfigConditionTime-DF6llIJq.js} +2 -2
- package/dist/interface/ha/{ConfigSensorValueInput-DwXM9wP1.js → ConfigSensorValueInput-Ch5njvtv.js} +7 -7
- package/dist/interface/ha/{ConfigTriggerDetection-D37OkR_u.js → ConfigTriggerDetection-BR2QWNyO.js} +5 -5
- package/dist/interface/ha/{ConfigTriggerGeofence-EbXy_y3Q.js → ConfigTriggerGeofence-CaImOjyW.js} +9 -9
- package/dist/interface/ha/{ConfigTriggerMqtt-BX6uNEZy.js → ConfigTriggerMqtt-DWz1XwZQ.js} +2 -2
- package/dist/interface/ha/{ConfigTriggerSensor-BFGEtBVF.js → ConfigTriggerSensor-lfnhz0im.js} +3 -3
- package/dist/interface/ha/{ConfigTriggerSystem-fRnAgUGR.js → ConfigTriggerSystem-CwUhyFAj.js} +3 -3
- package/dist/interface/ha/{ConfigTriggerWebhook-DegifRdj.js → ConfigTriggerWebhook-J6Xts7GQ.js} +2 -2
- package/dist/interface/ha/{Console-Bo6S5psN.js → Console-BSdKFm6Y.js} +8 -8
- package/dist/interface/ha/{CuiAutomationRunsDialog-DXpNJqDE.js → CuiAutomationRunsDialog-BU8sympp.js} +3 -3
- package/dist/interface/ha/{CuiBottomSheet-DLkC2OmT.js → CuiBottomSheet-Bnp7ta7V.js} +1 -1
- package/dist/interface/ha/{CuiCameraRecordings-9tdkxXiT.js → CuiCameraRecordings-E-mMqKSs.js} +18 -19
- package/dist/interface/ha/{CuiCameraShares-BbqY_2b7.js → CuiCameraShares-DcNwd2OC.js} +8 -8
- package/dist/interface/ha/{CuiCameraTable-BmH1yAgl.js → CuiCameraTable-DNW9Vm_A.js} +6 -6
- package/dist/interface/ha/{CuiChartTable-BjBBI7Fo.js → CuiChartTable-muC7jL2H.js} +6 -6
- package/dist/interface/ha/{CuiConsole-By3m4UbE.js → CuiConsole-ND8bcuTg.js} +2 -2
- package/dist/interface/ha/{CuiDataTable-C_ndu5My.js → CuiDataTable-CN4T8DgP.js} +13 -13
- package/dist/interface/ha/{CuiPluginCard-BLQ1galy.js → CuiPluginCard-nIQiyQvH.js} +31 -31
- package/dist/interface/ha/{CuiPluginOAuthButton-BDghklSy.js → CuiPluginOAuthButton-FJ49NfUh.js} +3 -3
- package/dist/interface/ha/{CuiPluginTrustBadge-DolANNao.js → CuiPluginTrustBadge-D6eanMyI.js} +2 -2
- package/dist/interface/ha/{CuiQRCode-CcjPngXI.js → CuiQRCode-BdJzeeoE.js} +2 -2
- package/dist/interface/ha/{CuiSchema-D9JFf0dp.js → CuiSchema-DY0V-8xP.js} +67 -67
- package/dist/interface/ha/{CuiTopNavbarItem-DcUEq-4e.js → CuiTopNavbarItem-DT5pAKHp.js} +7 -8
- package/dist/interface/ha/{Faces-DjXHzr77.js → Faces-C_svyTrr.js} +92 -92
- package/dist/interface/ha/{FirstSteps-CQAP9Siw.js → FirstSteps-yS2M2cor.js} +9 -9
- package/dist/interface/ha/{Floorplan-DyaPzlQO.js → Floorplan-DSOeScjI.js} +194 -194
- package/dist/interface/ha/{Instances-DWjaU5gj.js → Instances-B4h5EKpF.js} +20 -20
- package/dist/interface/ha/{Logs-Dlx-X1NS.js → Logs-BH0Lxvs6.js} +12 -12
- package/dist/interface/ha/{Menu-iqEe01qO.js → Menu-COH7QXuE.js} +13 -13
- package/dist/interface/ha/{Metrics-Br2Dyvzh.js → Metrics-BtnRqL_I.js} +136 -136
- package/dist/interface/ha/{OAuthDeviceFlow-CIGk92FD.js → OAuthDeviceFlow-D2QJ9MnP.js} +8 -8
- package/dist/interface/ha/{Plugin-DklIr7j2.js → Plugin-EfUSqwyh.js} +85 -85
- package/dist/interface/ha/{PluginConsole-DCfxPtGU.js → PluginConsole-hh_o15f7.js} +4 -4
- package/dist/interface/ha/PluginDetail-DFiXGkrY.js +805 -0
- package/dist/interface/ha/{PluginSearch-BTKBnjxb.js → PluginSearch-Cdrfubrj.js} +54 -54
- package/dist/interface/ha/{PluginUpdateProgress-Dej5AcCt.js → PluginUpdateProgress-BD2g2kVj.js} +3 -3
- package/dist/interface/ha/{Plugins-C2fONspm.js → Plugins-qFiHW-Nk.js} +45 -45
- package/dist/interface/ha/{RecentEventsFilter-ylgjiDo8.js → RecentEventsFilter-UWrXnvfq.js} +1 -1
- package/dist/interface/ha/{Recordings-w39I43cc.js → Recordings-BzeC6tOz.js} +437 -419
- package/dist/interface/ha/{SensorEdit-BkKi1l-A.js → SensorEdit-BSgy7lkZ.js} +360 -360
- package/dist/interface/ha/{SensorHistory-BGJjMlc3.js → SensorHistory-IDvP8LKH.js} +2 -2
- package/dist/interface/ha/{Sensors-D_Wi9XPa.js → Sensors-Diqp4oZ0.js} +96 -97
- package/dist/interface/ha/{Settings-Bn7WLWf0.js → Settings-BgDsxAlx.js} +11 -11
- package/dist/interface/ha/{SettingsAccount-CRTex-1j.js → SettingsAccount-DBXMQPYk.js} +159 -159
- package/dist/interface/ha/{SettingsAppearance-B1qmJnYk.js → SettingsAppearance-VmbjnT3o.js} +6 -6
- package/dist/interface/ha/{SettingsAssistant-DDd1X0BC.js → SettingsAssistant-C2R4ZetE.js} +133 -133
- package/dist/interface/ha/{SettingsBackup-DZbhSB13.js → SettingsBackup-BqY9TwYn.js} +20 -20
- package/dist/interface/ha/{SettingsList-BQdyPe0H.js → SettingsList-CzHcfo2N.js} +4 -4
- package/dist/interface/ha/{SettingsMqtt-CSZcY6ht.js → SettingsMqtt-DqV3h3Ow.js} +149 -149
- package/dist/interface/ha/{SettingsNotifications-CfEhl0-y.js → SettingsNotifications-yn5fIR_7.js} +6 -6
- package/dist/interface/ha/{SettingsRecordings-BnAGDvcH.js → SettingsRecordings-DDs1lyfY.js} +8 -8
- package/dist/interface/ha/{SettingsRemote-w86TQVUA.js → SettingsRemote-jBw3l5E0.js} +172 -172
- package/dist/interface/ha/{SettingsSystem-CENjHL3k.js → SettingsSystem-BOv9hNlk.js} +9 -9
- package/dist/interface/ha/{SettingsUsers-CqSHRklV.js → SettingsUsers-Biv-2F4C.js} +90 -90
- package/dist/interface/ha/{Terminal-WsuxG3k-.js → Terminal-CmcrGEV0.js} +4 -4
- package/dist/interface/ha/Training-BEzPiXZg.js +1512 -0
- package/dist/interface/ha/{Updates-Dl_lLLR2.js → Updates-DJAcmDQJ.js} +12 -12
- package/dist/interface/ha/{VariableInput-C8Q81GUt.js → VariableInput-DlYg7t0m.js} +2 -2
- package/dist/interface/ha/{VersionsHandler-BOvjesvp.js → VersionsHandler-UnrAWn-b.js} +11 -11
- package/dist/interface/ha/{VirtualSensorCreate-sgwATaky.js → VirtualSensorCreate-CssxeaCC.js} +2 -2
- package/dist/interface/ha/{Workers-CkDuQ9NG.js → Workers-CLpqLugC.js} +14 -14
- package/dist/interface/ha/{accordion-Xem2SzgR.js → accordion-BylV-jUK.js} +2 -2
- package/dist/interface/ha/{api-BmYisoxj.js → api-BP7mlzjP.js} +11181 -11736
- package/dist/interface/ha/{api-oqpIZTkx.js → api-B_tDa73J.js} +1 -1
- package/dist/interface/ha/{assistant-0jE4C19U.js → assistant-Cb6ACguQ.js} +1 -1
- package/dist/interface/ha/{auth-B4Msg7R-.js → auth-DOYDRgFm.js} +1 -1
- package/dist/interface/ha/{autocomplete-B94Amei3.js → autocomplete-Cp3u2Ywa.js} +4 -4
- package/dist/interface/ha/{automationBlueprint-C-12Yjl7.js → automationBlueprint-CbbG_ku4.js} +1 -1
- package/dist/interface/ha/cameraui-cards.js +1 -1
- package/dist/interface/ha/{cards-BrOcoiQJ.js → cards-BpBP1zVW.js} +1206 -1198
- package/dist/interface/ha/{config-IG56wp6m.js → config-DroY1HBs.js} +1 -1
- package/dist/interface/ha/{datepicker-B4Azs5zr.js → datepicker-DXk97lTw.js} +4 -4
- package/dist/interface/ha/{mqtt-pl13wSmG.js → mqtt-NJTVdd53.js} +1 -1
- package/dist/interface/ha/{multiselect-Dp4XDBRR.js → multiselect-BOb4ScAZ.js} +4 -4
- package/dist/interface/ha/{notifications-B6wxSmou.js → notifications-BPTvvgvv.js} +1 -1
- package/dist/interface/ha/{plugins-BwwaWxye.js → plugins-B29K3nQP.js} +1 -1
- package/dist/interface/ha/{rooms-NIzjFYAd.js → rooms-DLw0WUy_.js} +1 -1
- package/dist/interface/ha/{select-UR3ZRDew.js → select-DV7p2EDj.js} +4 -4
- package/dist/interface/ha/{server-YOLwDVAW.js → server-B4b5_Ecu.js} +1 -1
- package/dist/interface/ha/{speeddial-LCbl5g8p.js → speeddial-B5p0fuqL.js} +1 -1
- package/dist/interface/ha/{tooltip-Z7VN-E1u.js → tooltip-BDrlgLof.js} +1 -1
- package/dist/interface/ha/{types-B8B9MqK0.js → types-DJHHL7nn.js} +1 -1
- package/dist/interface/ha/{ungrouped-DttNEB62.js → ungrouped-xyK1QrsM.js} +344 -376
- package/dist/interface/ha/{updates-DVhiQhMM.js → updates-XFSu9Tfm.js} +5 -5
- package/dist/interface/ha/{useAppVersion-CG4D44Aa.js → useAppVersion-BH3rU1zz.js} +1 -1
- package/dist/interface/ha/{useLogsSocket-PKsRDttg.js → useLogsSocket-CaTRzvgU.js} +1 -1
- package/dist/interface/ha/{useNavLayout-DoEcPx9Z.js → useNavLayout-DV0_OQx0.js} +1 -1
- package/dist/interface/ha/{useServerRestart-CMl589qX.js → useServerRestart-C8tynLUf.js} +1 -1
- package/dist/interface/ha/{useTabSwipe-Cmqdn0J5.js → useTabSwipe-CFoLDp3j.js} +1 -1
- package/dist/interface/ha/{useUpdateChannel-BBW2EX7N.js → useUpdateChannel-DSG2RTPe.js} +2 -2
- package/dist/interface/ha/{useUpdatesSocket-B6ICpKKC.js → useUpdatesSocket-CSQ0g7-6.js} +1 -1
- package/dist/interface/ha/{useUserOptions-CzclRfar.js → useUserOptions-CFaCy6L1.js} +1 -1
- package/dist/interface/ha/{virtualscroller-C5j7FXj4.js → virtualscroller-B-UQZDMJ.js} +88 -88
- package/dist/interface/index.html +34 -34
- package/dist/interface/sw.js +1 -1
- package/dist/server/package.json +22 -20
- package/dist/server/requirements.txt +1 -1
- package/dist/server/src/api/controllers/auth.controller.js +5 -6
- package/dist/server/src/api/controllers/auth.controller.js.map +1 -1
- package/dist/server/src/api/controllers/plugins.controller.js +5 -5
- package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
- package/dist/server/src/api/database/checks.js +20 -8
- package/dist/server/src/api/database/checks.js.map +1 -1
- package/dist/server/src/api/database/selfcheck.js +2 -2
- package/dist/server/src/api/database/selfcheck.js.map +1 -1
- package/dist/server/src/api/index.js +8 -6
- package/dist/server/src/api/index.js.map +1 -1
- package/dist/server/src/api/plugins/logger.plugin.js +11 -11
- package/dist/server/src/api/plugins/logger.plugin.js.map +1 -1
- package/dist/server/src/api/services/twoFactor.service.d.ts +4 -5
- package/dist/server/src/api/services/twoFactor.service.js +16 -17
- package/dist/server/src/api/services/twoFactor.service.js.map +1 -1
- package/dist/server/src/api/types/index.d.ts +0 -1
- package/dist/server/src/api/utils/cert.js +128 -135
- package/dist/server/src/api/utils/cert.js.map +1 -1
- package/dist/server/src/api/utils/form-body.d.ts +2 -0
- package/dist/server/src/api/utils/form-body.js +22 -0
- package/dist/server/src/api/utils/form-body.js.map +1 -0
- package/dist/server/src/api/utils/install-logger.js +12 -12
- package/dist/server/src/api/utils/install-logger.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/logs.d.ts +7 -3
- package/dist/server/src/api/websocket/nsp/logs.js +79 -65
- package/dist/server/src/api/websocket/nsp/logs.js.map +1 -1
- package/dist/server/src/assistant/history.d.ts +2 -0
- package/dist/server/src/assistant/history.js +46 -0
- package/dist/server/src/assistant/history.js.map +1 -0
- package/dist/server/src/assistant/manager.js +2 -1
- package/dist/server/src/assistant/manager.js.map +1 -1
- package/dist/server/src/camera/controller.d.ts +1 -0
- package/dist/server/src/camera/controller.js +23 -18
- package/dist/server/src/camera/controller.js.map +1 -1
- package/dist/server/src/camera/decoder/worker.d.ts +3 -0
- package/dist/server/src/camera/decoder/worker.js +42 -5
- package/dist/server/src/camera/decoder/worker.js.map +1 -1
- package/dist/server/src/go2rtc/index.js +2 -2
- package/dist/server/src/go2rtc/index.js.map +1 -1
- package/dist/server/src/main.js +5 -5
- package/dist/server/src/main.js.map +1 -1
- package/dist/server/src/manager/discoveryManager.js +2 -2
- package/dist/server/src/manager/discoveryManager.js.map +1 -1
- package/dist/server/src/remote/services/cloudflare-managed.js +6 -3
- package/dist/server/src/remote/services/cloudflare-managed.js.map +1 -1
- package/dist/server/src/remote/services/cloudflare.d.ts +0 -1
- package/dist/server/src/remote/services/cloudflare.js +9 -20
- package/dist/server/src/remote/services/cloudflare.js.map +1 -1
- package/dist/server/src/remote/services/cloudflaredBinary.d.ts +3 -2
- package/dist/server/src/remote/services/cloudflaredBinary.js +9 -16
- package/dist/server/src/remote/services/cloudflaredBinary.js.map +1 -1
- package/dist/server/src/rpc/server.js +2 -2
- package/dist/server/src/rpc/server.js.map +1 -1
- package/dist/server/src/utils/automation-registry/index.js +3 -3
- package/dist/server/src/utils/automation-registry/index.js.map +1 -1
- package/dist/server/src/utils/colors.d.ts +2 -0
- package/dist/server/src/utils/colors.js +8 -0
- package/dist/server/src/utils/colors.js.map +1 -0
- package/dist/server/src/utils/npm/auth.d.ts +3 -2
- package/dist/server/src/utils/npm/auth.js +1 -1
- package/dist/server/src/utils/npm/auth.js.map +1 -1
- package/dist/server/src/utils/npm/index.d.ts +3 -15
- package/dist/server/src/utils/npm/index.js +26 -17
- package/dist/server/src/utils/npm/index.js.map +1 -1
- package/dist/server/src/utils/npm/registry.d.ts +69 -0
- package/dist/server/src/utils/npm/registry.js +240 -0
- package/dist/server/src/utils/npm/registry.js.map +1 -0
- package/dist/server/src/utils/plugin-registry/index.js +3 -3
- package/dist/server/src/utils/plugin-registry/index.js.map +1 -1
- package/dist/server/src/utils/process.d.ts +10 -0
- package/dist/server/src/utils/process.js +112 -0
- package/dist/server/src/utils/process.js.map +1 -0
- package/dist/server/src/utils/totp.d.ts +12 -0
- package/dist/server/src/utils/totp.js +71 -0
- package/dist/server/src/utils/totp.js.map +1 -0
- package/dist/server/src/utils/ttl-cache.d.ts +20 -0
- package/dist/server/src/utils/ttl-cache.js +63 -0
- package/dist/server/src/utils/ttl-cache.js.map +1 -0
- package/npm-shrinkwrap.json +6427 -0
- package/package.json +22 -20
- package/dist/interface/assets/Assistant-BKxssfw-.js +0 -1
- package/dist/interface/assets/Automation-CP59cgP7.js +0 -3
- package/dist/interface/assets/AutomationStore-BZGR_5Xl.js +0 -2
- package/dist/interface/assets/Automations-BpXorYAS.js +0 -2
- package/dist/interface/assets/Camera-UBUfaR5a.js +0 -2
- package/dist/interface/assets/Cameras-B21Y8MdQ.js +0 -651
- package/dist/interface/assets/Camview-BySyPtU5.js +0 -1
- package/dist/interface/assets/Config-BGyGmukb.js +0 -2
- package/dist/interface/assets/ConfigTriggerGeofence-CkzTFEZn.js +0 -1
- package/dist/interface/assets/Console-HXmKYaK_.js +0 -1
- package/dist/interface/assets/CuiAssistantConversation-2qrRCsgw.js +0 -5
- package/dist/interface/assets/CuiAssistantConversation-DmSdiv1b.css +0 -1
- package/dist/interface/assets/CuiBottomSheet-CTr-KHC8.js +0 -1
- package/dist/interface/assets/CuiCameraPipCard-BZCayhy_.js +0 -1
- package/dist/interface/assets/CuiCameraRecordings-BbaEL2ST.js +0 -1
- package/dist/interface/assets/CuiCameraTable-C5tQHs63.js +0 -1
- package/dist/interface/assets/CuiLightControl-v6k9hVGl.js +0 -1
- package/dist/interface/assets/CuiPluginCard-5MRYJcF2.js +0 -2
- package/dist/interface/assets/CuiSchema-BDXeXora.js +0 -1
- package/dist/interface/assets/CuiTopNavbarItem-BVknLbRO.js +0 -1
- package/dist/interface/assets/Faces-BEpYvbB0.js +0 -1
- package/dist/interface/assets/FirstSteps-U93RDOcP.js +0 -1
- package/dist/interface/assets/Floorplan-D8XoCNOB.js +0 -1
- package/dist/interface/assets/Instances-CFwZotvU.js +0 -1
- package/dist/interface/assets/Metrics-Ca_d5CbP.js +0 -12
- package/dist/interface/assets/Plugin-BjLw46Sw.js +0 -1
- package/dist/interface/assets/PluginDetail-BuLW4lkN.js +0 -2
- package/dist/interface/assets/PluginSearch--LLMEeyx.js +0 -2
- package/dist/interface/assets/PluginSearch-0akjE0ef.js +0 -1
- package/dist/interface/assets/Plugins-26O511gf.js +0 -1
- package/dist/interface/assets/Recordings-DQOGeSFm.js +0 -1
- package/dist/interface/assets/SensorEdit-DEW5D80x.js +0 -1
- package/dist/interface/assets/Sensors-C8yOyAwo.js +0 -2
- package/dist/interface/assets/Settings-B-RgMeVm.js +0 -1
- package/dist/interface/assets/SettingsAccount-B6aXFx3F.js +0 -1
- package/dist/interface/assets/SettingsAccount-_0ccrXYU.js +0 -1
- package/dist/interface/assets/SettingsAppearance-CkDwzx6f.js +0 -1
- package/dist/interface/assets/SettingsAppearance-DBFE3uVH.js +0 -1
- package/dist/interface/assets/SettingsAssistant-DN5OUJqt.js +0 -1
- package/dist/interface/assets/SettingsMqtt-hsKZkU-o.js +0 -1
- package/dist/interface/assets/SettingsNotifications-DIeiUEAk.js +0 -1
- package/dist/interface/assets/SettingsRemote-Doa0aBMC.js +0 -2
- package/dist/interface/assets/Training-DYlefOX1.js +0 -1
- package/dist/interface/assets/Workers-CUVvTuts.js +0 -2
- package/dist/interface/assets/api-B0wYDGQj.css +0 -2
- package/dist/interface/assets/api-BNrZVfeD.js +0 -4
- package/dist/interface/assets/cloudHandoff-Dnndt2el.js +0 -1
- package/dist/interface/assets/main-CRlC4FBY.js +0 -3
- package/dist/interface/assets/mqtt-BY6-Hrbv.js +0 -1
- package/dist/interface/assets/ring-resize-DyqCo2UN.js +0 -1
- package/dist/interface/assets/rooms-BHP4q6yf.js +0 -1
- package/dist/interface/assets/ungrouped-DBRZ-Ori.css +0 -1
- package/dist/interface/assets/ungrouped-DHLAmt__.js +0 -1
- package/dist/interface/assets/useBackupRestore-Dj-ZXODq.js +0 -1
- package/dist/interface/ha/PluginDetail-BFfRnkdG.js +0 -230
- package/dist/interface/ha/Training-hu_XOYBk.js +0 -1505
- package/dist/interface/ha/ring-resize-Dr2PxWIg.js +0 -16
|
@@ -1,71 +1,70 @@
|
|
|
1
1
|
import { c as e, m as t } from "./ripple-ZDATPc2w.js";
|
|
2
2
|
import { B as n, D as r, Dt as i, G as a, H as o, Jt as s, K as c, M as l, Wt as u, _t as d, bt as f, d as p, f as m, ft as h, gt as g, kt as _, l as v, lt as y, ot as b, p as x, qt as S, r as C, rt as w, u as T, ut as E, v as D, x as O, xt as k, y as A, yt as j, z as M } from "./runtime-core.esm-bundler-_TfE0DWz.js";
|
|
3
|
-
import { t as ee } from "./tooltip-
|
|
4
|
-
import { t as
|
|
5
|
-
import { A as
|
|
6
|
-
import { M as
|
|
7
|
-
import { i as
|
|
8
|
-
import { $ as
|
|
9
|
-
import { n as
|
|
10
|
-
import { n as
|
|
11
|
-
import { t as
|
|
12
|
-
import { t as
|
|
13
|
-
import { t as
|
|
14
|
-
import { i as
|
|
15
|
-
import { t as
|
|
16
|
-
import { i as
|
|
17
|
-
import { n as
|
|
18
|
-
import { t as
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { t as
|
|
22
|
-
import { t as ze } from "./
|
|
23
|
-
import {
|
|
24
|
-
import { t as He } from "./rooms-NIzjFYAd.js";
|
|
3
|
+
import { t as ee } from "./tooltip-BDrlgLof.js";
|
|
4
|
+
import { t as N } from "./message-D6dIy_hz.js";
|
|
5
|
+
import { A as P, D as F, F as I, I as L, L as R, O as te, Or as ne, Ot as re, Sr as ie, St as ae, Tr as oe, Yt as z, _t as B, a as V, ai as se, bi as H, jn as U, k as W, kt as ce, m as le, mr as G, tt as ue, ui as de, wr as fe } from "./api-BP7mlzjP.js";
|
|
6
|
+
import { M as pe } from "./protocol-BB4jdtUC-DW3jl2tV.js";
|
|
7
|
+
import { i as me, o as he } from "./intercomService-B7HkLs6z.js";
|
|
8
|
+
import { $ as ge, et as _e, nt as ve, rt as ye, tt as be } from "./pinia-C6gt7A_Q.js";
|
|
9
|
+
import { n as K } from "./vue-i18n-D5EAy78K.js";
|
|
10
|
+
import { n as xe, t as q } from "./button-BouAFgf5.js";
|
|
11
|
+
import { t as J } from "./inputtext-C_ygnPrC.js";
|
|
12
|
+
import { t as Se } from "./close-CxFbonhd.js";
|
|
13
|
+
import { t as Ce } from "./select-DV7p2EDj.js";
|
|
14
|
+
import { i as we, n as Te, r as Ee, t as De } from "./accordion-BylV-jUK.js";
|
|
15
|
+
import { t as Oe } from "./chip-BTHURsTF.js";
|
|
16
|
+
import { i as ke, t as Ae } from "./CuiDataTable-CN4T8DgP.js";
|
|
17
|
+
import { n as je, r as Me, t as Ne } from "./CuiSchema-DY0V-8xP.js";
|
|
18
|
+
import { t as Pe } from "./CuiCameraTable-DNW9Vm_A.js";
|
|
19
|
+
import { u as Fe } from "./cards-BpBP1zVW.js";
|
|
20
|
+
import { t as Ie } from "./plus-CgxY7W0L.js";
|
|
21
|
+
import { t as Le } from "./radar-BG-Tcwg_.js";
|
|
22
|
+
import { n as Re, t as ze } from "./eye-off-UG_p9nl8.js";
|
|
23
|
+
import { t as Be } from "./rooms-DLw0WUy_.js";
|
|
25
24
|
//#region ~icons/material-symbols/camera-rounded
|
|
26
|
-
var
|
|
25
|
+
var Ve = {
|
|
27
26
|
viewBox: "0 0 24 24",
|
|
28
27
|
width: "1.2em",
|
|
29
28
|
height: "1.2em"
|
|
30
29
|
};
|
|
31
|
-
function
|
|
32
|
-
return o(), x("svg",
|
|
30
|
+
function He(e, t) {
|
|
31
|
+
return o(), x("svg", Ve, [...t[0] ||= [T("path", {
|
|
33
32
|
fill: "currentColor",
|
|
34
33
|
d: "M12.5 9q-.275 0-.425-.25t0-.5L15 3.175q.2-.325.5-.387t.65.112q1.725.775 3.05 2.162T21.25 8.2q.125.325-.038.563T20.7 9zm-3.575 1.225l-3-5.2q-.2-.325-.1-.65t.4-.525Q7.425 3 8.888 2.5T12 2q.375 0 .825.038t.75.087q.35.05.463.3t-.063.55L9.8 10.225q-.15.25-.437.25t-.438-.25M2.85 14q-.275 0-.5-.187t-.275-.463t-.062-.6T2 12q0-1.575.513-3.137T4.1 5.9q.275-.35.638-.35t.562.375l4.2 7.325q.15.25-.012.5T9.05 14zm5 7.1q-1.65-.8-3.025-2.175T2.75 15.8q-.125-.325.05-.562T3.325 15h8.15q.275 0 .425.25t0 .5l-2.875 5.025q-.2.325-.5.425t-.675-.1M12 22q-.35 0-.788-.038t-.762-.087q-.35-.05-.475-.3t.05-.55l4.125-7.2q.15-.25.5-.25t.5.25l2.95 5.125q.175.275.113.6t-.413.6q-1.15.85-2.687 1.35T12 22m6.775-3.875l-4.25-7.375q-.15-.25.013-.5t.437-.25h6.175q.275 0 .5.188t.275.462t.062.6T22 12q0 1.575-.513 3.163T19.9 18.125q-.2.275-.575.288t-.55-.288"
|
|
35
34
|
}, null, -1)]]);
|
|
36
35
|
}
|
|
37
|
-
var
|
|
36
|
+
var Ue = d({
|
|
38
37
|
name: "material-symbols-camera-rounded",
|
|
39
|
-
render:
|
|
40
|
-
}), Ke = "#### Source: Bubble\n\nOther names: [ESeeCloud](http://www.eseecloud.com/), [dvr163](http://help.dvr163.com/).\n\n- you can skip `username`, `password`, `port`, `ch` and `stream` if they are default\n- setup separate streams for different channels and streams\n\n```yaml\nstreams:\n camera1: bubble://username:password@192.168.1.123:34567/bubble/live?ch=0&stream=0\n```\n\n_Source: [Go2Rtc Bubble](https://github.com/seydx/go2rtc#source-bubble)_\n", qe = "#### Source: CUI\n\nThis source can be used to stream dynamically generated, go2rtc compatible, URLs. The source is just a placeholder for a `https://` URL.\n\n```yaml\nstreams:\n camera1: cui://192.168.1.123:34567/some-identifier-if-you-want\n```\n\nThe URL will be changed to `https://192.168.1.123:34567/some-identifier-if-you-want` and the response must be like this:\n\n```json\n{\n {\n \"streamUrl\": \"rtsp://192.168.1.1:554/stream\",\n }\n}\n```\n\nGo2rtc will then use the `streamUrl` to stream the video. The `streamUrl` can be any URL that is compatible with go2rtc. The response must be a valid JSON object with the `streamUrl` key.\n", Je = "#### Source: Doorbird\n\n[Doorbird](https://www.doorbird.com/) proprietary camera protocol with **two way audio** support.\n\n```yaml\nstreams:\n video-audio:\n - rtsp://user:pass@123.123.123.123:554/mpeg/media.amp\n - doorbird://user:pass@123.123.123.123?media=audio\n two-way:\n - rtsp://user:pass@123.123.123.123:554/mpeg/media.amp\n - doorbird://user:pass@123.123.123.123?media=audio\n - doorbird://user:pass@123.123.123.123\n mjpeg-video:\n - doorbird://user:pass@123.123.123.123?media=video\n```\n\n_Source: [Go2Rtc Tuya](https://github.com/seydx/go2rtc#source-doorbird)_\n", Ye = "#### Source: DVRIP\n\nOther names: DVR-IP, NetSurveillance, Sofia protocol (NETsurveillance ActiveX plugin XMeye SDK).\n\n- you can skip `username`, `password`, `port`, `channel` and `subtype` if they are default\n- setup separate streams for different channels\n- use `subtype=0` for Main stream, and `subtype=1` for Extra1 stream\n- only the TCP protocol is supported\n\n```yaml\nstreams:\n only_stream: dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0\n only_tts: dvrip://username:password@192.168.1.123:34567?backchannel=1\n two_way_audio:\n - dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0\n - dvrip://username:password@192.168.1.123:34567?backchannel=1\n```\n\n_Source: [Go2Rtc DVRIP](https://github.com/seydx/go2rtc#source-dvrip)_\n", Xe = "#### Source: Echo\n\nSome sources may have a dynamic link. And you will need to get it using a bash or python script. Your script should echo a link to the source. RTSP, FFmpeg or any of the [supported sources](https://github.com/seydx/go2rtc#module-streams).\n\n**Docker** and **Hass Add-on** users has preinstalled `python3`, `curl`, `jq`.\nCheck examples in [wiki](https://github.com/seydx/go2rtc/wiki/Source-Echo-examples).\n\n```yaml\nstreams:\n apple_hls: echo:python3 hls.py https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html\n```\n\n_Source: [Go2Rtc Echo](https://github.com/seydx/go2rtc#source-echo)_\n", Ze = "#### Source: Exec\n\nExec source can run any external application and expect data from it. Two transports are supported - **pipe** and **RTSP**.\n\nIf you want to use **RTSP** transport - the command must contain the `{output}` argument in any place. On launch, it will be replaced by the local address of the RTSP server.\n\n**pipe** reads data from app stdout in different formats: **MJPEG**, **H.264/H.265 bitstream**, **MPEG-TS**. Also pipe can write data to app stdin in two formats: **PCMA** and **PCM/48000**.\n\nThe source can be used with:\n\n- [FFmpeg](https://ffmpeg.org/) - go2rtc ffmpeg source just a shortcut to exec source\n- [FFplay](https://ffmpeg.org/ffplay.html) - play audio on your server\n- [GStreamer](https://gstreamer.freedesktop.org/)\n- [Raspberry Pi Cameras](https://www.raspberrypi.com/documentation/computers/camera_software.html)\n- any your own software\n\n```yaml\nstreams:\n stream: exec:ffmpeg -re -i /media/BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp {output}\n picam_h264: exec:libcamera-vid -t 0 --inline -o -\n picam_mjpeg: exec:libcamera-vid -t 0 --codec mjpeg -o -\n pi5cam_h264: exec:libcamera-vid -t 0 --libav-format h264 -o -\n canon: exec:gphoto2 --capture-movie --stdout#killsignal=2#killtimeout=5\n play_pcma: exec:ffplay -fflags nobuffer -f alaw -ar 8000 -i -#backchannel=1\n play_pcm48k: exec:ffplay -fflags nobuffer -f s16be -ar 48000 -i -#backchannel=1\n```\n\n_Source: [Go2Rtc Exec](https://github.com/seydx/go2rtc#source-exec)_\n", Qe = "#### Source: Expr\n\n[Expr](https://github.com/antonmedv/expr) - expression language and expression evaluation for Go.\n\n- [language definition](https://expr.medv.io/docs/Language-Definition) - takes best from JS, Python, Jinja2 syntax\n- your expression should return a link of any supported source\n- expression supports multiple operation, but:\n - all operations must be separated by a semicolon\n - all operations, except the last one, must declare a new variable (`let s = \"abc\";`)\n - the last operation should return a string\n- go2rtc supports additional functions:\n - `fetch` - JS-like HTTP requests\n - `match` - JS-like RegExp queries\n\n## Examples\n\n**Two way audio for Dahua VTO**\n\n```yaml\nstreams:\n dahua_vto: |\n expr: let host = \"admin:password@192.168.1.123\";\n fetch(\"http://\"+host+\"/cgi-bin/configManager.cgi?action=setConfig&Encode[0].MainFormat[0].Audio.Compression=G.711A&Encode[0].MainFormat[0].Audio.Frequency=8000\").ok\n ? \"rtsp://\"+host+\"/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif\" : \"\"\n```\n\n**dom.ru**\n\nYou can get credentials via:\n\n- https://github.com/alexmorbo/domru (file `/share/domru/accounts`)\n- https://github.com/ad/domru\n\n```yaml\nstreams:\n dom_ru: |\n expr: let camera = \"99999999\"; let token = \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"; let operator = 99;\n fetch(\"https://myhome.novotelecom.ru/rest/v1/forpost/cameras/\"+camera+\"/video\", {\n headers: {Authorization: \"Bearer \"+token, Operator: operator}\n }).json().data.URL\n```\n\n**Parse HLS files from Apple**\n\nSame example in two languages - python and expr.\n\n```yaml\nstreams:\n example_python: |\n echo:python -c 'from urllib.request import urlopen; import re\n\n # url1 = \"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8\"\n html1 = urlopen(\"https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html\").read().decode(\"utf-8\")\n url1 = re.search(r\"https.+?m3u8\", html1)[0]\n\n # url2 = \"gear1/prog_index.m3u8\"\n html2 = urlopen(url1).read().decode(\"utf-8\")\n url2 = re.search(r\"^[a-z0-1/_]+\\.m3u8$\", html2, flags=re.MULTILINE)[0]\n\n # url3 = \"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear1/prog_index.m3u8\"\n url3 = url1[:url1.rindex(\"/\")+1] + url2\n\n print(\"ffmpeg:\" + url3 + \"#video=copy\")'\n\n example_expr: |\n expr:\n\n let html1 = fetch(\"https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html\").text;\n let url1 = match(html1, \"https.+?m3u8\")[0];\n\n let html2 = fetch(url1).text;\n let url2 = match(html2, \"^[a-z0-1/_]+\\\\.m3u8$\", \"m\")[0];\n\n let url3 = url1[:lastIndexOf(url1, \"/\")+1] + url2;\n\n \"ffmpeg:\" + url3 + \"#video=copy\"\n```\n\n## Comparsion\n\n| expr | python | js |\n| ---------------------------- | -------------------------- | ------------------------------ |\n| let x = 1; | x = 1 | let x = 1 |\n| {a: 1, b: 2} | {\"a\": 1, \"b\": 2} | {a: 1, b: 2} |\n| let r = fetch(url, {method}) | r = request(method, url) | r = await fetch(url, {method}) |\n| r.ok | r.ok | r.ok |\n| r.status | r.status_code | r.status |\n| r.text | r.text | await r.text() |\n| r.json() | r.json() | await r.json() |\n| r.headers | r.headers | r.headers |\n| let m = match(text, \"abc\") | m = re.search(\"abc\", text) | let m = text.match(/abc/) |\n\n_Source: [Go2Rtc Expr](https://github.com/seydx/go2rtc#source-expr)_\n", $e = "#### Source: FFmpeg\n\nYou can get any stream or file or device via FFmpeg and push it to go2rtc. The app will automatically start FFmpeg with the proper arguments when someone starts watching the stream.\n\n- FFmpeg preistalled for **Docker** and **Hass Add-on** users\n- **Hass Add-on** users can target files from [/media](https://www.home-assistant.io/more-info/local-media/setup-media/) folder\n\nFormat: `ffmpeg:{input}#{param1}#{param2}#{param3}`. Examples:\n\n```yaml\nstreams:\n # [FILE] all tracks will be copied without transcoding codecs\n file1: ffmpeg:/media/BigBuckBunny.mp4\n\n # [FILE] video will be transcoded to H264, audio will be skipped\n file2: ffmpeg:/media/BigBuckBunny.mp4#video=h264\n\n # [FILE] video will be copied, audio will be transcoded to pcmu\n file3: ffmpeg:/media/BigBuckBunny.mp4#video=copy#audio=pcmu\n\n # [HLS] video will be copied, audio will be skipped\n hls: ffmpeg:https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear5/prog_index.m3u8#video=copy\n\n # [MJPEG] video will be transcoded to H264\n mjpeg: ffmpeg:http://185.97.122.128/cgi-bin/faststream.jpg#video=h264\n\n # [RTSP] video with rotation, should be transcoded, so select H264\n rotate: ffmpeg:rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0#video=h264#rotate=90\n```\n\nAll trascoding formats has [built-in templates](https://github.com/seydx/go2rtc/blob/master/internal/ffmpeg/ffmpeg.go): `h264`, `h265`, `opus`, `pcmu`, `pcmu/16000`, `pcmu/48000`, `pcma`, `pcma/16000`, `pcma/48000`, `aac`, `aac/16000`.\n\nBut you can override them via YAML config. You can also add your own formats to config and use them with source params.\n\n```yaml\nffmpeg:\n bin: ffmpeg # path to ffmpeg binary\n h264: '-codec:v libx264 -g:v 30 -preset:v superfast -tune:v zerolatency -profile:v main -level:v 4.1'\n mycodec: '-any args that supported by ffmpeg...'\n myinput: '-fflags nobuffer -flags low_delay -timeout 5000000 -i {input}'\n myraw: '-ss 00:00:20'\n```\n\n- You can use go2rtc stream name as ffmpeg input (ex. `ffmpeg:camera1#video=h264`)\n- You can use `video` and `audio` params multiple times (ex. `#video=copy#audio=copy#audio=pcmu`)\n- You can use `rotate` param with `90`, `180`, `270` or `-90` values, important with transcoding (ex. `#video=h264#rotate=90`)\n- You can use `width` and/or `height` params, important with transcoding (ex. `#video=h264#width=1280`)\n- You can use `drawtext` to add a timestamp (ex. `drawtext=x=2:y=2:fontsize=12:fontcolor=white:box=1:boxcolor=black`)\n - This will greatly increase the CPU of the server, even with hardware acceleration\n- You can use `raw` param for any additional FFmpeg arguments (ex. `#raw=-vf transpose=1`)\n- You can use `input` param to override default input template (ex. `#input=rtsp/udp` will change RTSP transport from TCP to UDP+TCP)\n - You can use raw input value (ex. `#input=-timeout 5000000 -i {input}`)\n - You can add your own input templates\n\nRead more about [hardware acceleration](https://github.com/seydx/go2rtc/wiki/Hardware-acceleration).\n\n**PS.** It is recommended to check the available hardware in the WebUI add page.\n\n<hr>\n\n#### Source: FFmpeg Device\n\nYou can get video from any USB-camera or Webcam as RTSP or WebRTC stream. This is part of FFmpeg integration.\n\n- check available devices in Web interface\n- `video_size` and `framerate` must be supported by your camera!\n- for Linux supported only video for now\n- for macOS you can stream Facetime camera or whole Desktop!\n- for macOS important to set right framerate\n\nFormat: `ffmpeg:device?{input-params}#{param1}#{param2}#{param3}`\n\n```yaml\nstreams:\n linux_usbcam: ffmpeg:device?video=0&video_size=1280x720#video=h264\n windows_webcam: ffmpeg:device?video=0#video=h264\n macos_facetime: ffmpeg:device?video=0&audio=1&video_size=1280x720&framerate=30#video=h264#audio=pcma\n```\n\n**PS.** It is recommended to check the available devices in the WebUI add page.\n\n_Source: [Go2Rtc FFmpeg](https://github.com/seydx/go2rtc#source-ffmpeg) & [Go2Rtc FFmpeg Device](https://github.com/seydx/go2rtc#source-ffmpeg-device)_\n", et = "#### Source: GoPro\n\nSupported models: HERO9, HERO10, HERO11, HERO12. \nSupported OS: Linux, Mac, Windows, [HassOS](https://www.home-assistant.io/installation/)\n\nThe other camera models have different APIs. I will try to add them in the next versions.\n\n## Config\n\n- USB-connected cameras create a new network interface in the system\n- Linux users do not need to install anything\n- Windows users should install the [network driver](https://community.gopro.com/s/article/GoPro-Webcam)\n- if the camera is detected but the stream does not start - you need to disable firewall\n\n1. Discover camera address: WebUI > Add > GoPro\n2. Add camera to config\n\n```yaml\nstreams:\n hero12: gopro://172.20.100.51\n```\n\n## Useful links\n\n- https://gopro.github.io/OpenGoPro/\n\n_Source: [Go2Rtc Hass](https://github.com/seydx/go2rtc#source-hass)_\n", tt = "#### Source: Hass\n\nSupport import camera links from [Home Assistant](https://www.home-assistant.io/) config files:\n\n- [Generic Camera](https://www.home-assistant.io/integrations/generic/), setup via GUI\n- [HomeKit Camera](https://www.home-assistant.io/integrations/homekit_controller/)\n- [ONVIF](https://www.home-assistant.io/integrations/onvif/)\n- [Roborock](https://github.com/humbertogontijo/homeassistant-roborock) vacuums with camera\n\n```yaml\nhass:\n config: '/config' # skip this setting if you Hass Add-on user\n\nstreams:\n generic_camera: hass:Camera1 # Settings > Integrations > Integration Name\n aqara_g3: hass:Camera-Hub-G3-AB12\n```\n\n**WebRTC Cameras**\n\nAny cameras in WebRTC format are supported. But at the moment Home Assistant only supports some [Nest](https://www.home-assistant.io/integrations/nest/) cameras in this fomat.\n\nThe Nest API only allows you to get a link to a stream for 5 minutes. So every 5 minutes the stream will be reconnected.\n\n```yaml\nstreams:\n # link to Home Assistant Supervised\n hass-webrtc1: hass://supervisor?entity_id=camera.nest_doorbell\n # link to external Hass with Long-Lived Access Tokens\n hass-webrtc2: hass://192.168.1.123:8123?entity_id=camera.nest_doorbell&token=eyXYZ...\n```\n\n_Source: [Go2Rtc Hass](https://github.com/seydx/go2rtc#source-hass)_\n", nt = "#### Source: HomeKit\n\n**Important:**\n\n- You can use HomeKit Cameras **without Apple devices** (iPhone, iPad, etc.), it's just a yet another protocol\n- HomeKit device can be paired with only one ecosystem. So, if you have paired it to an iPhone (Apple Home) - you can't pair it with Home Assistant or go2rtc. Or if you have paired it to go2rtc - you can't pair it with iPhone\n- HomeKit device should be in same network with working [mDNS](https://en.wikipedia.org/wiki/Multicast_DNS) between device and go2rtc\n\ngo2rtc support import paired HomeKit devices from [Home Assistant](#source-hass). So you can use HomeKit camera with Hass and go2rtc simultaneously. If you using Hass, I recommend pairing devices with it, it will give you more options.\n\nYou can pair device with go2rtc on the HomeKit page. If you can't see your devices - reload the page. Also try reboot your HomeKit device (power off). If you still can't see it - you have a problems with mDNS.\n\nIf you see a device but it does not have a pair button - it is paired to some ecosystem (Apple Home, Home Assistant etc). You need to delete device from that ecosystem, and it will be available for pairing. If you cannot unpair device, you will have to reset it.\n\n**Important:**\n\n- HomeKit audio uses very non-standard **AAC-ELD** codec with very non-standard params and specification violation\n- Audio can't be played in `VLC` and probably any other player\n- Audio should be transcoded for using with MSE, WebRTC, etc.\n\nRecommended settings for using HomeKit Camera with WebRTC, MSE, MP4, RTSP:\n\n```\nstreams:\n aqara_g3:\n - hass:Camera-Hub-G3-AB12\n - ffmpeg:aqara_g3#audio=aac#audio=opus\n```\n\nRTSP link with \"normal\" audio for any player: `rtsp://192.168.1.123:8554/aqara_g3?video&audio=aac`\n\n**This source is in active development!** Tested only with [Aqara Camera Hub G3](https://www.aqara.com/eu/product/camera-hub-g3) (both EU and CN versions).\n\n_Source: [Go2Rtc HomeKit](https://github.com/seydx/go2rtc#source-homekit)_\n", rt = "#### Source: HTTP\n\nSupport Content-Type:\n\n- **HTTP-FLV** (`video/x-flv`) - same as RTMP, but over HTTP\n- **HTTP-JPEG** (`image/jpeg`) - camera snapshot link, can be converted by go2rtc to MJPEG stream\n- **HTTP-MJPEG** (`multipart/x`) - simple MJPEG stream over HTTP\n- **MPEG-TS** (`video/mpeg`) - legacy [streaming format](https://en.wikipedia.org/wiki/MPEG_transport_stream)\n\nSource also support HTTP and TCP streams with autodetection for different formats: **MJPEG**, **H.264/H.265 bitstream**, **MPEG-TS**.\n\n```yaml\nstreams:\n # [HTTP-FLV] stream in video/x-flv format\n http_flv: http://192.168.1.123:20880/api/camera/stream/780900131155/657617\n\n # [JPEG] snapshots from Dahua camera, will be converted to MJPEG stream\n dahua_snap: http://admin:password@192.168.1.123/cgi-bin/snapshot.cgi?channel=1\n\n # [MJPEG] stream will be proxied without modification\n http_mjpeg: https://mjpeg.sanford.io/count.mjpeg\n\n # [MJPEG or H.264/H.265 bitstream or MPEG-TS]\n tcp_magic: tcp://192.168.1.123:12345\n\n # Add custom header\n custom_header: 'https://mjpeg.sanford.io/count.mjpeg#header=Authorization: Bearer XXX'\n```\n\n**PS.** Dahua camera has bug: if you select MJPEG codec for RTSP second stream - snapshot won't work.\n\n_Source: [Go2Rtc Http](https://github.com/seydx/go2rtc#source-http)_\n", it = "#### Source: ISAPI\n\nThis source type support only backchannel audio for Hikvision ISAPI protocol. So it should be used as second source in addition to the RTSP protocol.\n\n```yaml\nstreams:\n hikvision1:\n - rtsp://admin:password@192.168.1.123:554/Streaming/Channels/101\n - isapi://admin:password@192.168.1.123:80/\n```\n\n_Source: [Go2Rtc Isapi](https://github.com/seydx/go2rtc#source-isapi)_\n", at = "#### Source: Ivideon\n\nSupport public cameras from service [Ivideon](https://tv.ivideon.com/).\n\n```yaml\nstreams:\n quailcam: ivideon:100-tu5dkUPct39cTp9oNEN2B6/0\n```\n\n_Source: [Go2Rtc Ivideon](https://github.com/seydx/go2rtc#source-ivideon)_\n", ot = "#### Source: Kasa\n\n[TP-Link Kasa](https://www.kasasmart.com/) non-standard protocol [more info](https://medium.com/@hu3vjeen/reverse-engineering-tp-link-kc100-bac4641bf1cd).\n\n- `username` - urlsafe email, `alex@gmail.com` -> `alex%40gmail.com`\n- `password` - base64password, `secret1` -> `c2VjcmV0MQ==`\n\n```yaml\nstreams:\n kc401: kasa://username:password@192.168.1.123:19443/https/stream/mixed\n```\n\nTested: KD110, KC200, KC401, KC420WS, EC71.\n\n_Source: [Go2Rtc Kasa](https://github.com/seydx/go2rtc#source-kasa)_\n", st = "#### Source: Nest\n\nCurrently only WebRTC cameras are supported.\n\nFor simplicity, it is recommended to connect the Nest/WebRTC camera to the [Home Assistant](#source-hass). But if you can somehow get the below parameters - Nest/WebRTC source will work without Hass.\n\n```yaml\nstreams:\n nest-doorbell: nest:?client_id=***&client_secret=***&refresh_token=***&project_id=***&device_id=***\n```\n\n_Source: [Go2Rtc Nest](https://github.com/seydx/go2rtc#source-nest)_\n", ct = "#### Source: ONVIF\n\nThe source is not very useful if you already know RTSP and snapshot links for your camera. But it can be useful if you don't.\n\n**WebUI > Add** webpage support ONVIF autodiscovery. Your server must be on the same subnet as the camera. If you use docker, you must use \"network host\".\n\n```yaml\nstreams:\n dahua1: onvif://admin:password@192.168.1.123\n reolink1: onvif://admin:password@192.168.1.123:8000\n tapo1: onvif://admin:password@192.168.1.123:2020\n```\n\n_Source: [Go2Rtc Onvif](https://github.com/seydx/go2rtc#source-onvif)_\n", lt = "#### Source: Ring\n\nThis source type support Ring cameras with [two way audio](#two-way-audio) support. If you have a `refresh_token` and `device_id` - you can use it in `go2rtc.yaml` config file. Otherwise, you can use the go2rtc interface and add your ring account (WebUI > Add > Ring). Once added, it will list all your Ring cameras.\n\n```yaml\nstreams:\n ring: ring:?device_id=XXX&refresh_token=XXX\n ring_snapshot: ring:?device_id=XXX&refresh_token=XXX&snapshot\n```\n\n_Source: [Go2Rtc Ring](https://github.com/seydx/go2rtc#source-ring)_\n", ut = "#### Source: Roborock\n\nThis source type support Roborock vacuums with cameras. Known working models:\n\n- Roborock S6 MaxV - only video (the vacuum has no microphone)\n- Roborock S7 MaxV - video and two way audio\n- Roborock Qrevo MaxV - video and two way audio\n\nSource support load Roborock credentials from Home Assistant [custom integration](https://github.com/humbertogontijo/homeassistant-roborock) or the [core integration](https://www.home-assistant.io/integrations/roborock). Otherwise, you need to log in to your Roborock account (MiHome account is not supported). Go to: go2rtc WebUI > Add webpage. Copy `roborock://...` source for your vacuum and paste it to `go2rtc.yaml` config.\n\nIf you have graphic pin for your vacuum - add it as numeric pin (lines: 123, 456, 789) to the end of the roborock-link.\n\n_Source: [Go2Rtc Roborock](https://github.com/seydx/go2rtc#source-roborock)_\n", dt = "#### Source: RTMP\n\nYou can get stream from RTMP server, for example [Nginx with nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module).\n\n```yaml\nstreams:\n rtmp_stream: rtmp://192.168.1.123/live/camera1\n```\n\n_Source: [Go2Rtc RTMP](https://github.com/seydx/go2rtc#source-rtmp)_\n", ft = "#### Source: RTSP\n\n```yaml\nstreams:\n sonoff_camera: rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0\n dahua_camera:\n - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif\n - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=1\n amcrest_doorbell:\n - rtsp://username:password@192.168.1.123:554/cam/realmonitor?channel=1&subtype=0#backchannel=0\n unifi_camera: rtspx://192.168.1.123:7441/fD6ouM72bWoFijxK\n glichy_camera: ffmpeg:rtsp://username:password@192.168.1.123/live/ch00_1\n```\n\n**Recommendations**\n\n- **Amcrest Doorbell** users may want to disable two way audio, because with an active stream you won't have a call button working. You need to add `#backchannel=0` to the end of your RTSP link in YAML config file\n- **Dahua Doorbell** users may want to change backchannel [audio codec](https://github.com/AlexxIT/go2rtc/issues/52)\n- **Reolink** users may want NOT to use RTSP protocol at all, some camera models have a very awful unusable stream implementation\n- **Ubiquiti UniFi** users may want to disable HTTPS verification. Use `rtspx://` prefix instead of `rtsps://`. And don't use `?enableSrtp` [suffix](https://github.com/AlexxIT/go2rtc/issues/81)\n- **TP-Link Tapo** users may skip login and password, because go2rtc support login [without them](https://drmnsamoliu.github.io/video.html)\n- If your camera has two RTSP links - you can add both of them as sources. This is useful when streams has different codecs, as example AAC audio with main stream and PCMU/PCMA audio with second stream\n- If the stream from your camera is glitchy, try using [ffmpeg source](#source-ffmpeg). It will not add CPU load if you won't use transcoding\n- If the stream from your camera is very glitchy, try to use transcoding with [ffmpeg source](#source-ffmpeg)\n\n**Other options**\n\nFormat: `rtsp...#{param1}#{param2}#{param3}`\n\n- Ignore audio - `#media=video` or ignore video - `#media=audio`\n- Ignore two way audio API `#backchannel=0` - important for some glitchy cameras\n- Use WebSocket transport `#transport=ws...`\n\n**RTSP over WebSocket**\n\n```yaml\nstreams:\n # WebSocket with authorization, RTSP - without\n axis-rtsp-ws: rtsp://192.168.1.123:4567/axis-media/media.amp?overview=0&camera=1&resolution=1280x720&videoframeskipmode=empty&Axis-Orig-Sw=true#transport=ws://user:pass@192.168.1.123:4567/rtsp-over-websocket\n # WebSocket without authorization, RTSP - with\n dahua-rtsp-ws: rtsp://user:pass@192.168.1.123/cam/realmonitor?channel=1&subtype=1&proto=Private3#transport=ws://192.168.1.123/rtspoverwebsocket\n```\n\n_Source: [Go2Rtc RTSP](https://github.com/seydx/go2rtc#source-rtsp)_\n", pt = "#### Source: Tapo\n\n[TP-Link Tapo](https://www.tapo.com/) proprietary camera protocol with **two way audio** support.\n\n- stream quality is the same as [RTSP protocol](https://www.tapo.com/en/faq/34/)\n- use the **cloud password**, this is not the RTSP password! you do not need to add a login!\n- you can also use UPPERCASE MD5 hash from your cloud password with `admin` username\n- some new camera firmwares requires SHA256 instead of MD5\n\n```yaml\nstreams:\n # cloud password without username\n camera1: tapo://cloud-password@192.168.1.123\n # admin username and UPPERCASE MD5 cloud-password hash\n camera2: tapo://admin:UPPERCASE-MD5@192.168.1.123\n # admin username and UPPERCASE SHA256 cloud-password hash\n camera3: tapo://admin:UPPERCASE-SHA256@192.168.1.123\n```\n\n```bash\necho -n \"cloud password\" | md5 | awk '{print toupper($0)}'\necho -n \"cloud password\" | shasum -a 256 | awk '{print toupper($0)}'\n```\n\n_Source: [Go2Rtc Tapo](https://github.com/seydx/go2rtc#source-tapo)_\n", mt = "#### Source: Tuya\n\n[Tuya](https://www.tuya.com/) proprietary camera protocol with **two way audio** support. Go2rtc supports `Tuya Smart API` and `Tuya Cloud API`.\n\n**Tuya Smart API (recommended)**:\n\n- Cameras can be discovered through the go2rtc web interface via Tuya Smart account (Add > Tuya > Select region and fill in email and password > Login).\n- **Smart Life accounts are not supported**, you need to create a Tuya Smart account. If the cameras are already added to the Smart Life app, you need to remove them and add them again to the Tuya Smart app.\n\n**Tuya Cloud API**:\n\n- Requires setting up a cloud project in the Tuya Developer Platform.\n- Obtain `device_id`, `client_id`, `client_secret`, and `uid` from [Tuya IoT Platform](https://iot.tuya.com/). [Here's a guide](https://xzetsubou.github.io/hass-localtuya/cloud_api/).\n- Please ensure that you have subscribed to the `IoT Video Live Stream` service (Free Trial) in the Tuya Developer Platform, otherwise the stream will not work (Tuya Developer Platform > Service API > Authorize > IoT Video Live Stream).\n\n**Configuring the stream:**\n\n- Use `resolution` parameter to select the stream (not all cameras support `hd` stream through WebRTC even if the camera has it):\n - `hd` - HD stream (default)\n - `sd` - SD stream\n\n```yaml\nstreams:\n # Tuya Smart API: WebRTC main stream (use Add > Tuya to discover the URL)\n tuya_main:\n - tuya://protect-us.ismartlife.me?device_id=XXX&email=XXX&password=XXX\n\n # Tuya Smart API: WebRTC sub stream (use Add > Tuya to discover the URL)\n tuya_sub:\n - tuya://protect-us.ismartlife.me?device_id=XXX&email=XXX&password=XXX&resolution=sd\n\n # Tuya Cloud API: WebRTC main stream\n tuya_webrtc:\n - tuya://openapi.tuyaus.com?device_id=XXX&uid=XXX&client_id=XXX&client_secret=XXX\n\n # Tuya Cloud API: WebRTC sub stream\n tuya_webrtc_sd:\n - tuya://openapi.tuyaus.com?device_id=XXX&uid=XXX&client_id=XXX&client_secret=XXX&resolution=sd\n```\n\n_Source: [Go2Rtc Tuya](https://github.com/seydx/go2rtc#source-tuya)_\n", ht = "#### Source: WebRTC\n\nThis source type support four connection formats.\n\n**whep**\n\n[WebRTC/WHEP](https://datatracker.ietf.org/doc/draft-murillo-whep/) - is replaced by [WebRTC/WISH](https://datatracker.ietf.org/doc/charter-ietf-wish/02/) standard for WebRTC video/audio viewers. But it may already be supported in some third-party software. It is supported in go2rtc.\n\n**go2rtc**\n\nThis format is only supported in go2rtc. Unlike WHEP it supports asynchronous WebRTC connection and two way audio.\n\n**openipc**\n\nSupport connection to [OpenIPC](https://openipc.org/) cameras.\n\n**wyze**\n\nSupports connection to [Wyze](https://www.wyze.com/) cameras, using WebRTC protocol. You can use [docker-wyze-bridge](https://github.com/mrlt8/docker-wyze-bridge) project to get connection credentials.\n\n**kinesis**\n\nSupports [Amazon Kinesis Video Streams](https://aws.amazon.com/kinesis/video-streams/), using WebRTC protocol. You need to specify signalling WebSocket URL with all credentials in query params, `client_id` and `ice_servers` list in [JSON format](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer).\n\n```yaml\nstreams:\n webrtc-whep: webrtc:http://192.168.1.123:1984/api/webrtc?src=camera1\n webrtc-go2rtc: webrtc:ws://192.168.1.123:1984/api/ws?src=camera1\n webrtc-openipc: webrtc:ws://192.168.1.123/webrtc_ws#format=openipc#ice_servers=[{\"urls\":\"stun:stun.kinesisvideo.eu-north-1.amazonaws.com:443\"}]\n webrtc-wyze: webrtc:http://192.168.1.123:5000/signaling/camera1?kvs#format=wyze\n webrtc-kinesis: webrtc:wss://...amazonaws.com/?...#format=kinesis#client_id=...#ice_servers=[{...},{...}]\n```\n\n**PS.** For `kinesis` sources you can use [echo](#source-echo) to get connection params using `bash`/`python` or any other script language.\n\n_Source: [Go2Rtc WebRTC](https://github.com/seydx/go2rtc#source-webrtc)_\n", gt = "#### Source: WebTorrent\n\nThis source can get a stream from another go2rtc via [WebTorrent](#module-webtorrent) protocol.\n\n```yaml\nstreams:\n webtorrent1: webtorrent:?share=huofssuxaty00izc&pwd=k3l2j9djeg8v8r7e\n```\n\n_Source: [Go2Rtc Webtorrent](https://github.com/seydx/go2rtc#source-webtorrent)_\n", _t = "#### Source: Wyze\n\nThis source allows you to stream from [Wyze](https://wyze.com/) cameras using native P2P protocol without the Wyze app or SDK.\n\n**Important:**\n\n1. **Requires Wyze account**. You need to login once via the WebUI to load your cameras.\n2. **Requires firmware with DTLS**. Only cameras with DTLS-enabled firmware are supported.\n3. Internet access is only needed when loading cameras from your account. After that, all streaming is local P2P.\n4. Connection to the camera is local only (direct P2P to camera IP).\n\n**Features:**\n\n- H.264 and H.265 video codec support\n- AAC, G.711, PCM, and Opus audio codec support\n- Two-way audio (intercom) support\n- Resolution switching (HD/SD)\n\n## Setup\n\n1. Get your API Key from [Wyze Developer Portal](https://support.wyze.com/hc/en-us/articles/16129834216731)\n2. Go to go2rtc WebUI > Add > Wyze\n3. Enter your API ID, API Key, email, and password\n4. Select cameras to add - stream URLs are generated automatically\n\n**Example Config**\n\n```yaml\nwyze:\n user@email.com:\n api_id: 'your-api-id'\n api_key: 'your-api-key'\n password: 'yourpassword' # or MD5 triple-hash with \"md5:\" prefix\n\nstreams:\n wyze_cam: wyze://192.168.1.123?uid=WYZEUID1234567890AB&enr=xxx&mac=AABBCCDDEEFF&model=HL_CAM4&dtls=true\n```\n\n## Stream URL Format\n\nThe stream URL is automatically generated when you add cameras via the WebUI:\n\n```\nwyze://[IP]?uid=[P2P_ID]&enr=[ENR]&mac=[MAC]&model=[MODEL]&subtype=[hd|sd]&dtls=true\n```\n\n| Parameter | Description |\n| --------- | ----------------------------------------------- |\n| `IP` | Camera's local IP address |\n| `uid` | P2P identifier (20 chars) |\n| `enr` | Encryption key for DTLS |\n| `mac` | Device MAC address |\n| `model` | Camera model (e.g., HL_CAM4) |\n| `dtls` | Enable DTLS encryption (default: true) |\n| `subtype` | Camera resolution: `hd` or `sd` (default: `hd`) |\n\n## Configuration\n\n### Resolution\n\nYou can change the camera's resolution using the `subtype` parameter:\n\n```yaml\nstreams:\n wyze_hd: wyze://...&subtype=hd\n wyze_sd: wyze://...&subtype=sd\n```\n\n### Two-Way Audio\n\nTwo-way audio (intercom) is supported automatically. When a consumer sends audio to the stream, it will be transmitted to the camera's speaker.\n", vt = "#### Source: Xiaomi\n\nThis source allows you to view cameras from the [Xiaomi Mi Home](https://home.mi.com/) ecosystem.\n\n**Important:**\n\n1. **Not all cameras are supported**. There are several P2P protocol vendors in the Xiaomi ecosystem.\n Currently, the **CS2** vendor is supported. However, the **TUTK** vendor is not supported.\n2. Each time you connect to the camera, you need internet access to obtain encryption keys.\n3. Connection to the camera is local only.\n\n**Features:**\n\n- Multiple Xiaomi accounts supported\n- Cameras from multiple regions are supported for a single account\n- Two-way audio is supported\n- Cameras with multiple lenses are supported\n\n## Setup\n\n1. Goto go2rtc WebUI > Add > Xiaomi > Login with username and password\n2. Receive verification code by email or phone if required.\n3. Complete the captcha if required.\n4. If everything is OK, your account will be added and you can load cameras from it.\n\n**Example**\n\n```yaml\nxiaomi:\n 1234567890: V1:***\n\nstreams:\n xiaomi1: xiaomi://1234567890:cn@192.168.1.123?did=9876543210&model=isa.camera.hlc7\n```\n\n## Configuration\n\nYou can change camera's quality: `subtype=hd/sd/auto`\n\n```yaml\nstreams:\n xiaomi1: xiaomi://***&subtype=sd\n```\n\nYou can use second channel for Dual cameras: `channel=1`\n\n```yaml\nstreams:\n xiaomi1: xiaomi://***&channel=1\n```\n", yt = "# Yandex\n\nSource for receiving stream from new [Yandex IP camera](https://alice.yandex.ru/smart-home/security/ipcamera).\n\n## Get Yandex token\n\n1. Install HomeAssistant integration [YandexStation](https://github.com/AlexxIT/YandexStation).\n2. Copy token from HomeAssistant config folder: `/config/.storage/core.config_entries`, key: `\"x_token\"`.\n\n## Get device ID\n\n1. Open this link in any browser: https://iot.quasar.yandex.ru/m/v3/user/devices\n2. Copy ID of your camera, key: `\"id\"`.\n\n## Config examples\n\n```yaml\nstreams:\n yandex_stream: yandex:?x_token=XXXX&device_id=XXXX\n yandex_snapshot: yandex:?x_token=XXXX&device_id=XXXX&snapshot\n yandex_snapshot_custom_size: yandex:?x_token=XXXX&device_id=XXXX&snapshot=h=540\n```\n\n_Source: [Go2Rtc Yandex](https://github.com/AlexxIT/go2rtc/tree/master/internal/yandex)_\n", bt = [
|
|
38
|
+
render: He
|
|
39
|
+
}), We = "#### Source: Bubble\n\nOther names: [ESeeCloud](http://www.eseecloud.com/), [dvr163](http://help.dvr163.com/).\n\n- you can skip `username`, `password`, `port`, `ch` and `stream` if they are default\n- setup separate streams for different channels and streams\n\n```yaml\nstreams:\n camera1: bubble://username:password@192.168.1.123:34567/bubble/live?ch=0&stream=0\n```\n\n_Source: [Go2Rtc Bubble](https://github.com/seydx/go2rtc#source-bubble)_\n", Ge = "#### Source: CUI\n\nThis source can be used to stream dynamically generated, go2rtc compatible, URLs. The source is just a placeholder for a `https://` URL.\n\n```yaml\nstreams:\n camera1: cui://192.168.1.123:34567/some-identifier-if-you-want\n```\n\nThe URL will be changed to `https://192.168.1.123:34567/some-identifier-if-you-want` and the response must be like this:\n\n```json\n{\n {\n \"streamUrl\": \"rtsp://192.168.1.1:554/stream\",\n }\n}\n```\n\nGo2rtc will then use the `streamUrl` to stream the video. The `streamUrl` can be any URL that is compatible with go2rtc. The response must be a valid JSON object with the `streamUrl` key.\n", Ke = "#### Source: Doorbird\n\n[Doorbird](https://www.doorbird.com/) proprietary camera protocol with **two way audio** support.\n\n```yaml\nstreams:\n video-audio:\n - rtsp://user:pass@123.123.123.123:554/mpeg/media.amp\n - doorbird://user:pass@123.123.123.123?media=audio\n two-way:\n - rtsp://user:pass@123.123.123.123:554/mpeg/media.amp\n - doorbird://user:pass@123.123.123.123?media=audio\n - doorbird://user:pass@123.123.123.123\n mjpeg-video:\n - doorbird://user:pass@123.123.123.123?media=video\n```\n\n_Source: [Go2Rtc Tuya](https://github.com/seydx/go2rtc#source-doorbird)_\n", qe = "#### Source: DVRIP\n\nOther names: DVR-IP, NetSurveillance, Sofia protocol (NETsurveillance ActiveX plugin XMeye SDK).\n\n- you can skip `username`, `password`, `port`, `channel` and `subtype` if they are default\n- setup separate streams for different channels\n- use `subtype=0` for Main stream, and `subtype=1` for Extra1 stream\n- only the TCP protocol is supported\n\n```yaml\nstreams:\n only_stream: dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0\n only_tts: dvrip://username:password@192.168.1.123:34567?backchannel=1\n two_way_audio:\n - dvrip://username:password@192.168.1.123:34567?channel=0&subtype=0\n - dvrip://username:password@192.168.1.123:34567?backchannel=1\n```\n\n_Source: [Go2Rtc DVRIP](https://github.com/seydx/go2rtc#source-dvrip)_\n", Je = "#### Source: Echo\n\nSome sources may have a dynamic link. And you will need to get it using a bash or python script. Your script should echo a link to the source. RTSP, FFmpeg or any of the [supported sources](https://github.com/seydx/go2rtc#module-streams).\n\n**Docker** and **Hass Add-on** users has preinstalled `python3`, `curl`, `jq`.\nCheck examples in [wiki](https://github.com/seydx/go2rtc/wiki/Source-Echo-examples).\n\n```yaml\nstreams:\n apple_hls: echo:python3 hls.py https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html\n```\n\n_Source: [Go2Rtc Echo](https://github.com/seydx/go2rtc#source-echo)_\n", Ye = "#### Source: Exec\n\nExec source can run any external application and expect data from it. Two transports are supported - **pipe** and **RTSP**.\n\nIf you want to use **RTSP** transport - the command must contain the `{output}` argument in any place. On launch, it will be replaced by the local address of the RTSP server.\n\n**pipe** reads data from app stdout in different formats: **MJPEG**, **H.264/H.265 bitstream**, **MPEG-TS**. Also pipe can write data to app stdin in two formats: **PCMA** and **PCM/48000**.\n\nThe source can be used with:\n\n- [FFmpeg](https://ffmpeg.org/) - go2rtc ffmpeg source just a shortcut to exec source\n- [FFplay](https://ffmpeg.org/ffplay.html) - play audio on your server\n- [GStreamer](https://gstreamer.freedesktop.org/)\n- [Raspberry Pi Cameras](https://www.raspberrypi.com/documentation/computers/camera_software.html)\n- any your own software\n\n```yaml\nstreams:\n stream: exec:ffmpeg -re -i /media/BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp {output}\n picam_h264: exec:libcamera-vid -t 0 --inline -o -\n picam_mjpeg: exec:libcamera-vid -t 0 --codec mjpeg -o -\n pi5cam_h264: exec:libcamera-vid -t 0 --libav-format h264 -o -\n canon: exec:gphoto2 --capture-movie --stdout#killsignal=2#killtimeout=5\n play_pcma: exec:ffplay -fflags nobuffer -f alaw -ar 8000 -i -#backchannel=1\n play_pcm48k: exec:ffplay -fflags nobuffer -f s16be -ar 48000 -i -#backchannel=1\n```\n\n_Source: [Go2Rtc Exec](https://github.com/seydx/go2rtc#source-exec)_\n", Xe = "#### Source: Expr\n\n[Expr](https://github.com/antonmedv/expr) - expression language and expression evaluation for Go.\n\n- [language definition](https://expr.medv.io/docs/Language-Definition) - takes best from JS, Python, Jinja2 syntax\n- your expression should return a link of any supported source\n- expression supports multiple operation, but:\n - all operations must be separated by a semicolon\n - all operations, except the last one, must declare a new variable (`let s = \"abc\";`)\n - the last operation should return a string\n- go2rtc supports additional functions:\n - `fetch` - JS-like HTTP requests\n - `match` - JS-like RegExp queries\n\n## Examples\n\n**Two way audio for Dahua VTO**\n\n```yaml\nstreams:\n dahua_vto: |\n expr: let host = \"admin:password@192.168.1.123\";\n fetch(\"http://\"+host+\"/cgi-bin/configManager.cgi?action=setConfig&Encode[0].MainFormat[0].Audio.Compression=G.711A&Encode[0].MainFormat[0].Audio.Frequency=8000\").ok\n ? \"rtsp://\"+host+\"/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif\" : \"\"\n```\n\n**dom.ru**\n\nYou can get credentials via:\n\n- https://github.com/alexmorbo/domru (file `/share/domru/accounts`)\n- https://github.com/ad/domru\n\n```yaml\nstreams:\n dom_ru: |\n expr: let camera = \"99999999\"; let token = \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"; let operator = 99;\n fetch(\"https://myhome.novotelecom.ru/rest/v1/forpost/cameras/\"+camera+\"/video\", {\n headers: {Authorization: \"Bearer \"+token, Operator: operator}\n }).json().data.URL\n```\n\n**Parse HLS files from Apple**\n\nSame example in two languages - python and expr.\n\n```yaml\nstreams:\n example_python: |\n echo:python -c 'from urllib.request import urlopen; import re\n\n # url1 = \"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8\"\n html1 = urlopen(\"https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html\").read().decode(\"utf-8\")\n url1 = re.search(r\"https.+?m3u8\", html1)[0]\n\n # url2 = \"gear1/prog_index.m3u8\"\n html2 = urlopen(url1).read().decode(\"utf-8\")\n url2 = re.search(r\"^[a-z0-1/_]+\\.m3u8$\", html2, flags=re.MULTILINE)[0]\n\n # url3 = \"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear1/prog_index.m3u8\"\n url3 = url1[:url1.rindex(\"/\")+1] + url2\n\n print(\"ffmpeg:\" + url3 + \"#video=copy\")'\n\n example_expr: |\n expr:\n\n let html1 = fetch(\"https://developer.apple.com/streaming/examples/basic-stream-osx-ios5.html\").text;\n let url1 = match(html1, \"https.+?m3u8\")[0];\n\n let html2 = fetch(url1).text;\n let url2 = match(html2, \"^[a-z0-1/_]+\\\\.m3u8$\", \"m\")[0];\n\n let url3 = url1[:lastIndexOf(url1, \"/\")+1] + url2;\n\n \"ffmpeg:\" + url3 + \"#video=copy\"\n```\n\n## Comparsion\n\n| expr | python | js |\n| ---------------------------- | -------------------------- | ------------------------------ |\n| let x = 1; | x = 1 | let x = 1 |\n| {a: 1, b: 2} | {\"a\": 1, \"b\": 2} | {a: 1, b: 2} |\n| let r = fetch(url, {method}) | r = request(method, url) | r = await fetch(url, {method}) |\n| r.ok | r.ok | r.ok |\n| r.status | r.status_code | r.status |\n| r.text | r.text | await r.text() |\n| r.json() | r.json() | await r.json() |\n| r.headers | r.headers | r.headers |\n| let m = match(text, \"abc\") | m = re.search(\"abc\", text) | let m = text.match(/abc/) |\n\n_Source: [Go2Rtc Expr](https://github.com/seydx/go2rtc#source-expr)_\n", Ze = "#### Source: FFmpeg\n\nYou can get any stream or file or device via FFmpeg and push it to go2rtc. The app will automatically start FFmpeg with the proper arguments when someone starts watching the stream.\n\n- FFmpeg preistalled for **Docker** and **Hass Add-on** users\n- **Hass Add-on** users can target files from [/media](https://www.home-assistant.io/more-info/local-media/setup-media/) folder\n\nFormat: `ffmpeg:{input}#{param1}#{param2}#{param3}`. Examples:\n\n```yaml\nstreams:\n # [FILE] all tracks will be copied without transcoding codecs\n file1: ffmpeg:/media/BigBuckBunny.mp4\n\n # [FILE] video will be transcoded to H264, audio will be skipped\n file2: ffmpeg:/media/BigBuckBunny.mp4#video=h264\n\n # [FILE] video will be copied, audio will be transcoded to pcmu\n file3: ffmpeg:/media/BigBuckBunny.mp4#video=copy#audio=pcmu\n\n # [HLS] video will be copied, audio will be skipped\n hls: ffmpeg:https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/gear5/prog_index.m3u8#video=copy\n\n # [MJPEG] video will be transcoded to H264\n mjpeg: ffmpeg:http://185.97.122.128/cgi-bin/faststream.jpg#video=h264\n\n # [RTSP] video with rotation, should be transcoded, so select H264\n rotate: ffmpeg:rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0#video=h264#rotate=90\n```\n\nAll trascoding formats has [built-in templates](https://github.com/seydx/go2rtc/blob/master/internal/ffmpeg/ffmpeg.go): `h264`, `h265`, `opus`, `pcmu`, `pcmu/16000`, `pcmu/48000`, `pcma`, `pcma/16000`, `pcma/48000`, `aac`, `aac/16000`.\n\nBut you can override them via YAML config. You can also add your own formats to config and use them with source params.\n\n```yaml\nffmpeg:\n bin: ffmpeg # path to ffmpeg binary\n h264: '-codec:v libx264 -g:v 30 -preset:v superfast -tune:v zerolatency -profile:v main -level:v 4.1'\n mycodec: '-any args that supported by ffmpeg...'\n myinput: '-fflags nobuffer -flags low_delay -timeout 5000000 -i {input}'\n myraw: '-ss 00:00:20'\n```\n\n- You can use go2rtc stream name as ffmpeg input (ex. `ffmpeg:camera1#video=h264`)\n- You can use `video` and `audio` params multiple times (ex. `#video=copy#audio=copy#audio=pcmu`)\n- You can use `rotate` param with `90`, `180`, `270` or `-90` values, important with transcoding (ex. `#video=h264#rotate=90`)\n- You can use `width` and/or `height` params, important with transcoding (ex. `#video=h264#width=1280`)\n- You can use `drawtext` to add a timestamp (ex. `drawtext=x=2:y=2:fontsize=12:fontcolor=white:box=1:boxcolor=black`)\n - This will greatly increase the CPU of the server, even with hardware acceleration\n- You can use `raw` param for any additional FFmpeg arguments (ex. `#raw=-vf transpose=1`)\n- You can use `input` param to override default input template (ex. `#input=rtsp/udp` will change RTSP transport from TCP to UDP+TCP)\n - You can use raw input value (ex. `#input=-timeout 5000000 -i {input}`)\n - You can add your own input templates\n\nRead more about [hardware acceleration](https://github.com/seydx/go2rtc/wiki/Hardware-acceleration).\n\n**PS.** It is recommended to check the available hardware in the WebUI add page.\n\n<hr>\n\n#### Source: FFmpeg Device\n\nYou can get video from any USB-camera or Webcam as RTSP or WebRTC stream. This is part of FFmpeg integration.\n\n- check available devices in Web interface\n- `video_size` and `framerate` must be supported by your camera!\n- for Linux supported only video for now\n- for macOS you can stream Facetime camera or whole Desktop!\n- for macOS important to set right framerate\n\nFormat: `ffmpeg:device?{input-params}#{param1}#{param2}#{param3}`\n\n```yaml\nstreams:\n linux_usbcam: ffmpeg:device?video=0&video_size=1280x720#video=h264\n windows_webcam: ffmpeg:device?video=0#video=h264\n macos_facetime: ffmpeg:device?video=0&audio=1&video_size=1280x720&framerate=30#video=h264#audio=pcma\n```\n\n**PS.** It is recommended to check the available devices in the WebUI add page.\n\n_Source: [Go2Rtc FFmpeg](https://github.com/seydx/go2rtc#source-ffmpeg) & [Go2Rtc FFmpeg Device](https://github.com/seydx/go2rtc#source-ffmpeg-device)_\n", Qe = "#### Source: GoPro\n\nSupported models: HERO9, HERO10, HERO11, HERO12. \nSupported OS: Linux, Mac, Windows, [HassOS](https://www.home-assistant.io/installation/)\n\nThe other camera models have different APIs. I will try to add them in the next versions.\n\n## Config\n\n- USB-connected cameras create a new network interface in the system\n- Linux users do not need to install anything\n- Windows users should install the [network driver](https://community.gopro.com/s/article/GoPro-Webcam)\n- if the camera is detected but the stream does not start - you need to disable firewall\n\n1. Discover camera address: WebUI > Add > GoPro\n2. Add camera to config\n\n```yaml\nstreams:\n hero12: gopro://172.20.100.51\n```\n\n## Useful links\n\n- https://gopro.github.io/OpenGoPro/\n\n_Source: [Go2Rtc Hass](https://github.com/seydx/go2rtc#source-hass)_\n", $e = "#### Source: Hass\n\nSupport import camera links from [Home Assistant](https://www.home-assistant.io/) config files:\n\n- [Generic Camera](https://www.home-assistant.io/integrations/generic/), setup via GUI\n- [HomeKit Camera](https://www.home-assistant.io/integrations/homekit_controller/)\n- [ONVIF](https://www.home-assistant.io/integrations/onvif/)\n- [Roborock](https://github.com/humbertogontijo/homeassistant-roborock) vacuums with camera\n\n```yaml\nhass:\n config: '/config' # skip this setting if you Hass Add-on user\n\nstreams:\n generic_camera: hass:Camera1 # Settings > Integrations > Integration Name\n aqara_g3: hass:Camera-Hub-G3-AB12\n```\n\n**WebRTC Cameras**\n\nAny cameras in WebRTC format are supported. But at the moment Home Assistant only supports some [Nest](https://www.home-assistant.io/integrations/nest/) cameras in this fomat.\n\nThe Nest API only allows you to get a link to a stream for 5 minutes. So every 5 minutes the stream will be reconnected.\n\n```yaml\nstreams:\n # link to Home Assistant Supervised\n hass-webrtc1: hass://supervisor?entity_id=camera.nest_doorbell\n # link to external Hass with Long-Lived Access Tokens\n hass-webrtc2: hass://192.168.1.123:8123?entity_id=camera.nest_doorbell&token=eyXYZ...\n```\n\n_Source: [Go2Rtc Hass](https://github.com/seydx/go2rtc#source-hass)_\n", et = "#### Source: HomeKit\n\n**Important:**\n\n- You can use HomeKit Cameras **without Apple devices** (iPhone, iPad, etc.), it's just a yet another protocol\n- HomeKit device can be paired with only one ecosystem. So, if you have paired it to an iPhone (Apple Home) - you can't pair it with Home Assistant or go2rtc. Or if you have paired it to go2rtc - you can't pair it with iPhone\n- HomeKit device should be in same network with working [mDNS](https://en.wikipedia.org/wiki/Multicast_DNS) between device and go2rtc\n\ngo2rtc support import paired HomeKit devices from [Home Assistant](#source-hass). So you can use HomeKit camera with Hass and go2rtc simultaneously. If you using Hass, I recommend pairing devices with it, it will give you more options.\n\nYou can pair device with go2rtc on the HomeKit page. If you can't see your devices - reload the page. Also try reboot your HomeKit device (power off). If you still can't see it - you have a problems with mDNS.\n\nIf you see a device but it does not have a pair button - it is paired to some ecosystem (Apple Home, Home Assistant etc). You need to delete device from that ecosystem, and it will be available for pairing. If you cannot unpair device, you will have to reset it.\n\n**Important:**\n\n- HomeKit audio uses very non-standard **AAC-ELD** codec with very non-standard params and specification violation\n- Audio can't be played in `VLC` and probably any other player\n- Audio should be transcoded for using with MSE, WebRTC, etc.\n\nRecommended settings for using HomeKit Camera with WebRTC, MSE, MP4, RTSP:\n\n```\nstreams:\n aqara_g3:\n - hass:Camera-Hub-G3-AB12\n - ffmpeg:aqara_g3#audio=aac#audio=opus\n```\n\nRTSP link with \"normal\" audio for any player: `rtsp://192.168.1.123:8554/aqara_g3?video&audio=aac`\n\n**This source is in active development!** Tested only with [Aqara Camera Hub G3](https://www.aqara.com/eu/product/camera-hub-g3) (both EU and CN versions).\n\n_Source: [Go2Rtc HomeKit](https://github.com/seydx/go2rtc#source-homekit)_\n", tt = "#### Source: HTTP\n\nSupport Content-Type:\n\n- **HTTP-FLV** (`video/x-flv`) - same as RTMP, but over HTTP\n- **HTTP-JPEG** (`image/jpeg`) - camera snapshot link, can be converted by go2rtc to MJPEG stream\n- **HTTP-MJPEG** (`multipart/x`) - simple MJPEG stream over HTTP\n- **MPEG-TS** (`video/mpeg`) - legacy [streaming format](https://en.wikipedia.org/wiki/MPEG_transport_stream)\n\nSource also support HTTP and TCP streams with autodetection for different formats: **MJPEG**, **H.264/H.265 bitstream**, **MPEG-TS**.\n\n```yaml\nstreams:\n # [HTTP-FLV] stream in video/x-flv format\n http_flv: http://192.168.1.123:20880/api/camera/stream/780900131155/657617\n\n # [JPEG] snapshots from Dahua camera, will be converted to MJPEG stream\n dahua_snap: http://admin:password@192.168.1.123/cgi-bin/snapshot.cgi?channel=1\n\n # [MJPEG] stream will be proxied without modification\n http_mjpeg: https://mjpeg.sanford.io/count.mjpeg\n\n # [MJPEG or H.264/H.265 bitstream or MPEG-TS]\n tcp_magic: tcp://192.168.1.123:12345\n\n # Add custom header\n custom_header: 'https://mjpeg.sanford.io/count.mjpeg#header=Authorization: Bearer XXX'\n```\n\n**PS.** Dahua camera has bug: if you select MJPEG codec for RTSP second stream - snapshot won't work.\n\n_Source: [Go2Rtc Http](https://github.com/seydx/go2rtc#source-http)_\n", nt = "#### Source: ISAPI\n\nThis source type support only backchannel audio for Hikvision ISAPI protocol. So it should be used as second source in addition to the RTSP protocol.\n\n```yaml\nstreams:\n hikvision1:\n - rtsp://admin:password@192.168.1.123:554/Streaming/Channels/101\n - isapi://admin:password@192.168.1.123:80/\n```\n\n_Source: [Go2Rtc Isapi](https://github.com/seydx/go2rtc#source-isapi)_\n", rt = "#### Source: Ivideon\n\nSupport public cameras from service [Ivideon](https://tv.ivideon.com/).\n\n```yaml\nstreams:\n quailcam: ivideon:100-tu5dkUPct39cTp9oNEN2B6/0\n```\n\n_Source: [Go2Rtc Ivideon](https://github.com/seydx/go2rtc#source-ivideon)_\n", it = "#### Source: Kasa\n\n[TP-Link Kasa](https://www.kasasmart.com/) non-standard protocol [more info](https://medium.com/@hu3vjeen/reverse-engineering-tp-link-kc100-bac4641bf1cd).\n\n- `username` - urlsafe email, `alex@gmail.com` -> `alex%40gmail.com`\n- `password` - base64password, `secret1` -> `c2VjcmV0MQ==`\n\n```yaml\nstreams:\n kc401: kasa://username:password@192.168.1.123:19443/https/stream/mixed\n```\n\nTested: KD110, KC200, KC401, KC420WS, EC71.\n\n_Source: [Go2Rtc Kasa](https://github.com/seydx/go2rtc#source-kasa)_\n", at = "#### Source: Nest\n\nCurrently only WebRTC cameras are supported.\n\nFor simplicity, it is recommended to connect the Nest/WebRTC camera to the [Home Assistant](#source-hass). But if you can somehow get the below parameters - Nest/WebRTC source will work without Hass.\n\n```yaml\nstreams:\n nest-doorbell: nest:?client_id=***&client_secret=***&refresh_token=***&project_id=***&device_id=***\n```\n\n_Source: [Go2Rtc Nest](https://github.com/seydx/go2rtc#source-nest)_\n", ot = "#### Source: ONVIF\n\nThe source is not very useful if you already know RTSP and snapshot links for your camera. But it can be useful if you don't.\n\n**WebUI > Add** webpage support ONVIF autodiscovery. Your server must be on the same subnet as the camera. If you use docker, you must use \"network host\".\n\n```yaml\nstreams:\n dahua1: onvif://admin:password@192.168.1.123\n reolink1: onvif://admin:password@192.168.1.123:8000\n tapo1: onvif://admin:password@192.168.1.123:2020\n```\n\n_Source: [Go2Rtc Onvif](https://github.com/seydx/go2rtc#source-onvif)_\n", st = "#### Source: Ring\n\nThis source type support Ring cameras with [two way audio](#two-way-audio) support. If you have a `refresh_token` and `device_id` - you can use it in `go2rtc.yaml` config file. Otherwise, you can use the go2rtc interface and add your ring account (WebUI > Add > Ring). Once added, it will list all your Ring cameras.\n\n```yaml\nstreams:\n ring: ring:?device_id=XXX&refresh_token=XXX\n ring_snapshot: ring:?device_id=XXX&refresh_token=XXX&snapshot\n```\n\n_Source: [Go2Rtc Ring](https://github.com/seydx/go2rtc#source-ring)_\n", ct = "#### Source: Roborock\n\nThis source type support Roborock vacuums with cameras. Known working models:\n\n- Roborock S6 MaxV - only video (the vacuum has no microphone)\n- Roborock S7 MaxV - video and two way audio\n- Roborock Qrevo MaxV - video and two way audio\n\nSource support load Roborock credentials from Home Assistant [custom integration](https://github.com/humbertogontijo/homeassistant-roborock) or the [core integration](https://www.home-assistant.io/integrations/roborock). Otherwise, you need to log in to your Roborock account (MiHome account is not supported). Go to: go2rtc WebUI > Add webpage. Copy `roborock://...` source for your vacuum and paste it to `go2rtc.yaml` config.\n\nIf you have graphic pin for your vacuum - add it as numeric pin (lines: 123, 456, 789) to the end of the roborock-link.\n\n_Source: [Go2Rtc Roborock](https://github.com/seydx/go2rtc#source-roborock)_\n", lt = "#### Source: RTMP\n\nYou can get stream from RTMP server, for example [Nginx with nginx-rtmp-module](https://github.com/arut/nginx-rtmp-module).\n\n```yaml\nstreams:\n rtmp_stream: rtmp://192.168.1.123/live/camera1\n```\n\n_Source: [Go2Rtc RTMP](https://github.com/seydx/go2rtc#source-rtmp)_\n", ut = "#### Source: RTSP\n\n```yaml\nstreams:\n sonoff_camera: rtsp://rtsp:12345678@192.168.1.123/av_stream/ch0\n dahua_camera:\n - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif\n - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=1\n amcrest_doorbell:\n - rtsp://username:password@192.168.1.123:554/cam/realmonitor?channel=1&subtype=0#backchannel=0\n unifi_camera: rtspx://192.168.1.123:7441/fD6ouM72bWoFijxK\n glichy_camera: ffmpeg:rtsp://username:password@192.168.1.123/live/ch00_1\n```\n\n**Recommendations**\n\n- **Amcrest Doorbell** users may want to disable two way audio, because with an active stream you won't have a call button working. You need to add `#backchannel=0` to the end of your RTSP link in YAML config file\n- **Dahua Doorbell** users may want to change backchannel [audio codec](https://github.com/AlexxIT/go2rtc/issues/52)\n- **Reolink** users may want NOT to use RTSP protocol at all, some camera models have a very awful unusable stream implementation\n- **Ubiquiti UniFi** users may want to disable HTTPS verification. Use `rtspx://` prefix instead of `rtsps://`. And don't use `?enableSrtp` [suffix](https://github.com/AlexxIT/go2rtc/issues/81)\n- **TP-Link Tapo** users may skip login and password, because go2rtc support login [without them](https://drmnsamoliu.github.io/video.html)\n- If your camera has two RTSP links - you can add both of them as sources. This is useful when streams has different codecs, as example AAC audio with main stream and PCMU/PCMA audio with second stream\n- If the stream from your camera is glitchy, try using [ffmpeg source](#source-ffmpeg). It will not add CPU load if you won't use transcoding\n- If the stream from your camera is very glitchy, try to use transcoding with [ffmpeg source](#source-ffmpeg)\n\n**Other options**\n\nFormat: `rtsp...#{param1}#{param2}#{param3}`\n\n- Ignore audio - `#media=video` or ignore video - `#media=audio`\n- Ignore two way audio API `#backchannel=0` - important for some glitchy cameras\n- Use WebSocket transport `#transport=ws...`\n\n**RTSP over WebSocket**\n\n```yaml\nstreams:\n # WebSocket with authorization, RTSP - without\n axis-rtsp-ws: rtsp://192.168.1.123:4567/axis-media/media.amp?overview=0&camera=1&resolution=1280x720&videoframeskipmode=empty&Axis-Orig-Sw=true#transport=ws://user:pass@192.168.1.123:4567/rtsp-over-websocket\n # WebSocket without authorization, RTSP - with\n dahua-rtsp-ws: rtsp://user:pass@192.168.1.123/cam/realmonitor?channel=1&subtype=1&proto=Private3#transport=ws://192.168.1.123/rtspoverwebsocket\n```\n\n_Source: [Go2Rtc RTSP](https://github.com/seydx/go2rtc#source-rtsp)_\n", dt = "#### Source: Tapo\n\n[TP-Link Tapo](https://www.tapo.com/) proprietary camera protocol with **two way audio** support.\n\n- stream quality is the same as [RTSP protocol](https://www.tapo.com/en/faq/34/)\n- use the **cloud password**, this is not the RTSP password! you do not need to add a login!\n- you can also use UPPERCASE MD5 hash from your cloud password with `admin` username\n- some new camera firmwares requires SHA256 instead of MD5\n\n```yaml\nstreams:\n # cloud password without username\n camera1: tapo://cloud-password@192.168.1.123\n # admin username and UPPERCASE MD5 cloud-password hash\n camera2: tapo://admin:UPPERCASE-MD5@192.168.1.123\n # admin username and UPPERCASE SHA256 cloud-password hash\n camera3: tapo://admin:UPPERCASE-SHA256@192.168.1.123\n```\n\n```bash\necho -n \"cloud password\" | md5 | awk '{print toupper($0)}'\necho -n \"cloud password\" | shasum -a 256 | awk '{print toupper($0)}'\n```\n\n_Source: [Go2Rtc Tapo](https://github.com/seydx/go2rtc#source-tapo)_\n", ft = "#### Source: Tuya\n\n[Tuya](https://www.tuya.com/) proprietary camera protocol with **two way audio** support. Go2rtc supports `Tuya Smart API` and `Tuya Cloud API`.\n\n**Tuya Smart API (recommended)**:\n\n- Cameras can be discovered through the go2rtc web interface via Tuya Smart account (Add > Tuya > Select region and fill in email and password > Login).\n- **Smart Life accounts are not supported**, you need to create a Tuya Smart account. If the cameras are already added to the Smart Life app, you need to remove them and add them again to the Tuya Smart app.\n\n**Tuya Cloud API**:\n\n- Requires setting up a cloud project in the Tuya Developer Platform.\n- Obtain `device_id`, `client_id`, `client_secret`, and `uid` from [Tuya IoT Platform](https://iot.tuya.com/). [Here's a guide](https://xzetsubou.github.io/hass-localtuya/cloud_api/).\n- Please ensure that you have subscribed to the `IoT Video Live Stream` service (Free Trial) in the Tuya Developer Platform, otherwise the stream will not work (Tuya Developer Platform > Service API > Authorize > IoT Video Live Stream).\n\n**Configuring the stream:**\n\n- Use `resolution` parameter to select the stream (not all cameras support `hd` stream through WebRTC even if the camera has it):\n - `hd` - HD stream (default)\n - `sd` - SD stream\n\n```yaml\nstreams:\n # Tuya Smart API: WebRTC main stream (use Add > Tuya to discover the URL)\n tuya_main:\n - tuya://protect-us.ismartlife.me?device_id=XXX&email=XXX&password=XXX\n\n # Tuya Smart API: WebRTC sub stream (use Add > Tuya to discover the URL)\n tuya_sub:\n - tuya://protect-us.ismartlife.me?device_id=XXX&email=XXX&password=XXX&resolution=sd\n\n # Tuya Cloud API: WebRTC main stream\n tuya_webrtc:\n - tuya://openapi.tuyaus.com?device_id=XXX&uid=XXX&client_id=XXX&client_secret=XXX\n\n # Tuya Cloud API: WebRTC sub stream\n tuya_webrtc_sd:\n - tuya://openapi.tuyaus.com?device_id=XXX&uid=XXX&client_id=XXX&client_secret=XXX&resolution=sd\n```\n\n_Source: [Go2Rtc Tuya](https://github.com/seydx/go2rtc#source-tuya)_\n", pt = "#### Source: WebRTC\n\nThis source type support four connection formats.\n\n**whep**\n\n[WebRTC/WHEP](https://datatracker.ietf.org/doc/draft-murillo-whep/) - is replaced by [WebRTC/WISH](https://datatracker.ietf.org/doc/charter-ietf-wish/02/) standard for WebRTC video/audio viewers. But it may already be supported in some third-party software. It is supported in go2rtc.\n\n**go2rtc**\n\nThis format is only supported in go2rtc. Unlike WHEP it supports asynchronous WebRTC connection and two way audio.\n\n**openipc**\n\nSupport connection to [OpenIPC](https://openipc.org/) cameras.\n\n**wyze**\n\nSupports connection to [Wyze](https://www.wyze.com/) cameras, using WebRTC protocol. You can use [docker-wyze-bridge](https://github.com/mrlt8/docker-wyze-bridge) project to get connection credentials.\n\n**kinesis**\n\nSupports [Amazon Kinesis Video Streams](https://aws.amazon.com/kinesis/video-streams/), using WebRTC protocol. You need to specify signalling WebSocket URL with all credentials in query params, `client_id` and `ice_servers` list in [JSON format](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer).\n\n```yaml\nstreams:\n webrtc-whep: webrtc:http://192.168.1.123:1984/api/webrtc?src=camera1\n webrtc-go2rtc: webrtc:ws://192.168.1.123:1984/api/ws?src=camera1\n webrtc-openipc: webrtc:ws://192.168.1.123/webrtc_ws#format=openipc#ice_servers=[{\"urls\":\"stun:stun.kinesisvideo.eu-north-1.amazonaws.com:443\"}]\n webrtc-wyze: webrtc:http://192.168.1.123:5000/signaling/camera1?kvs#format=wyze\n webrtc-kinesis: webrtc:wss://...amazonaws.com/?...#format=kinesis#client_id=...#ice_servers=[{...},{...}]\n```\n\n**PS.** For `kinesis` sources you can use [echo](#source-echo) to get connection params using `bash`/`python` or any other script language.\n\n_Source: [Go2Rtc WebRTC](https://github.com/seydx/go2rtc#source-webrtc)_\n", mt = "#### Source: WebTorrent\n\nThis source can get a stream from another go2rtc via [WebTorrent](#module-webtorrent) protocol.\n\n```yaml\nstreams:\n webtorrent1: webtorrent:?share=huofssuxaty00izc&pwd=k3l2j9djeg8v8r7e\n```\n\n_Source: [Go2Rtc Webtorrent](https://github.com/seydx/go2rtc#source-webtorrent)_\n", ht = "#### Source: Wyze\n\nThis source allows you to stream from [Wyze](https://wyze.com/) cameras using native P2P protocol without the Wyze app or SDK.\n\n**Important:**\n\n1. **Requires Wyze account**. You need to login once via the WebUI to load your cameras.\n2. **Requires firmware with DTLS**. Only cameras with DTLS-enabled firmware are supported.\n3. Internet access is only needed when loading cameras from your account. After that, all streaming is local P2P.\n4. Connection to the camera is local only (direct P2P to camera IP).\n\n**Features:**\n\n- H.264 and H.265 video codec support\n- AAC, G.711, PCM, and Opus audio codec support\n- Two-way audio (intercom) support\n- Resolution switching (HD/SD)\n\n## Setup\n\n1. Get your API Key from [Wyze Developer Portal](https://support.wyze.com/hc/en-us/articles/16129834216731)\n2. Go to go2rtc WebUI > Add > Wyze\n3. Enter your API ID, API Key, email, and password\n4. Select cameras to add - stream URLs are generated automatically\n\n**Example Config**\n\n```yaml\nwyze:\n user@email.com:\n api_id: 'your-api-id'\n api_key: 'your-api-key'\n password: 'yourpassword' # or MD5 triple-hash with \"md5:\" prefix\n\nstreams:\n wyze_cam: wyze://192.168.1.123?uid=WYZEUID1234567890AB&enr=xxx&mac=AABBCCDDEEFF&model=HL_CAM4&dtls=true\n```\n\n## Stream URL Format\n\nThe stream URL is automatically generated when you add cameras via the WebUI:\n\n```\nwyze://[IP]?uid=[P2P_ID]&enr=[ENR]&mac=[MAC]&model=[MODEL]&subtype=[hd|sd]&dtls=true\n```\n\n| Parameter | Description |\n| --------- | ----------------------------------------------- |\n| `IP` | Camera's local IP address |\n| `uid` | P2P identifier (20 chars) |\n| `enr` | Encryption key for DTLS |\n| `mac` | Device MAC address |\n| `model` | Camera model (e.g., HL_CAM4) |\n| `dtls` | Enable DTLS encryption (default: true) |\n| `subtype` | Camera resolution: `hd` or `sd` (default: `hd`) |\n\n## Configuration\n\n### Resolution\n\nYou can change the camera's resolution using the `subtype` parameter:\n\n```yaml\nstreams:\n wyze_hd: wyze://...&subtype=hd\n wyze_sd: wyze://...&subtype=sd\n```\n\n### Two-Way Audio\n\nTwo-way audio (intercom) is supported automatically. When a consumer sends audio to the stream, it will be transmitted to the camera's speaker.\n", gt = "#### Source: Xiaomi\n\nThis source allows you to view cameras from the [Xiaomi Mi Home](https://home.mi.com/) ecosystem.\n\n**Important:**\n\n1. **Not all cameras are supported**. There are several P2P protocol vendors in the Xiaomi ecosystem.\n Currently, the **CS2** vendor is supported. However, the **TUTK** vendor is not supported.\n2. Each time you connect to the camera, you need internet access to obtain encryption keys.\n3. Connection to the camera is local only.\n\n**Features:**\n\n- Multiple Xiaomi accounts supported\n- Cameras from multiple regions are supported for a single account\n- Two-way audio is supported\n- Cameras with multiple lenses are supported\n\n## Setup\n\n1. Goto go2rtc WebUI > Add > Xiaomi > Login with username and password\n2. Receive verification code by email or phone if required.\n3. Complete the captcha if required.\n4. If everything is OK, your account will be added and you can load cameras from it.\n\n**Example**\n\n```yaml\nxiaomi:\n 1234567890: V1:***\n\nstreams:\n xiaomi1: xiaomi://1234567890:cn@192.168.1.123?did=9876543210&model=isa.camera.hlc7\n```\n\n## Configuration\n\nYou can change camera's quality: `subtype=hd/sd/auto`\n\n```yaml\nstreams:\n xiaomi1: xiaomi://***&subtype=sd\n```\n\nYou can use second channel for Dual cameras: `channel=1`\n\n```yaml\nstreams:\n xiaomi1: xiaomi://***&channel=1\n```\n", _t = "# Yandex\n\nSource for receiving stream from new [Yandex IP camera](https://alice.yandex.ru/smart-home/security/ipcamera).\n\n## Get Yandex token\n\n1. Install HomeAssistant integration [YandexStation](https://github.com/AlexxIT/YandexStation).\n2. Copy token from HomeAssistant config folder: `/config/.storage/core.config_entries`, key: `\"x_token\"`.\n\n## Get device ID\n\n1. Open this link in any browser: https://iot.quasar.yandex.ru/m/v3/user/devices\n2. Copy ID of your camera, key: `\"id\"`.\n\n## Config examples\n\n```yaml\nstreams:\n yandex_stream: yandex:?x_token=XXXX&device_id=XXXX\n yandex_snapshot: yandex:?x_token=XXXX&device_id=XXXX&snapshot\n yandex_snapshot_custom_size: yandex:?x_token=XXXX&device_id=XXXX&snapshot=h=540\n```\n\n_Source: [Go2Rtc Yandex](https://github.com/AlexxIT/go2rtc/tree/master/internal/yandex)_\n", vt = [
|
|
41
40
|
"nest:",
|
|
42
41
|
"ring:",
|
|
43
42
|
"yandex:",
|
|
44
43
|
"webtorrent:"
|
|
45
44
|
];
|
|
46
|
-
function
|
|
45
|
+
function Y(e) {
|
|
47
46
|
let t = e.trim(), n;
|
|
48
|
-
for (let e of
|
|
47
|
+
for (let e of ge) t.startsWith(e) && (!n || e.length > n.length) && (n = e);
|
|
49
48
|
return n;
|
|
50
49
|
}
|
|
51
|
-
function
|
|
50
|
+
function yt(e) {
|
|
52
51
|
let t = e.trim();
|
|
53
52
|
if (!t) return "";
|
|
54
|
-
for (let e of
|
|
53
|
+
for (let e of vt) if (t.startsWith(e)) {
|
|
55
54
|
let n = t.slice(e.length);
|
|
56
55
|
return n && !n.startsWith("?") ? `${e}?${n}` : t;
|
|
57
56
|
}
|
|
58
57
|
return t;
|
|
59
58
|
}
|
|
60
|
-
function
|
|
59
|
+
function bt(e) {
|
|
61
60
|
return e.startsWith("cui://") && e.includes("/api/cameras/streams/");
|
|
62
61
|
}
|
|
63
62
|
//#endregion
|
|
64
63
|
//#region src/components/CuiCameraSources/CuiCameraSources.vue?vue&type=script&setup=true&lang.ts
|
|
65
|
-
var
|
|
64
|
+
var xt = { class: "flex flex-col gap-6" }, St = { class: "flex gap-2 items-center w-full" }, Ct = { class: "flex gap-2 items-center w-full" }, wt = { class: "text-color text-sm" }, Tt = { class: "flex flex-col gap-6" }, Et = ["for"], Dt = ["for"], Ot = { class: "w-full flex flex-col gap-2" }, kt = { class: "flex items-center gap-4" }, At = { class: "flex flex-col field-switch-gap" }, jt = ["for"], Mt = { class: "flex items-center gap-4" }, Nt = { class: "flex flex-col field-switch-gap" }, Pt = ["for"], Ft = { class: "flex items-center gap-4" }, It = { class: "flex flex-col field-switch-gap" }, Lt = ["for"], Rt = { class: "flex items-center gap-4" }, zt = { class: "flex flex-col field-switch-gap" }, Bt = ["for"], Vt = { class: "flex flex-col gap-6" }, Ht = { class: "flex flex-col field-gap" }, Ut = ["for"], Wt = {
|
|
66
65
|
key: 0,
|
|
67
66
|
class: "w-full flex flex-row gap-2"
|
|
68
|
-
},
|
|
67
|
+
}, Gt = "rtsp://user:pass@192.168.1.50:554/stream", Kt = /* @__PURE__ */ O({
|
|
69
68
|
__name: "CuiCameraSources",
|
|
70
69
|
props: {
|
|
71
70
|
sources: {},
|
|
@@ -76,35 +75,35 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
76
75
|
}
|
|
77
76
|
},
|
|
78
77
|
setup(n, { expose: r }) {
|
|
79
|
-
let i = new
|
|
80
|
-
"../../markdowns/bubble.md":
|
|
81
|
-
"../../markdowns/cui.md":
|
|
82
|
-
"../../markdowns/doorbird.md":
|
|
83
|
-
"../../markdowns/dvrip.md":
|
|
84
|
-
"../../markdowns/echo.md":
|
|
85
|
-
"../../markdowns/exec.md":
|
|
86
|
-
"../../markdowns/expr.md":
|
|
87
|
-
"../../markdowns/ffmpeg.md":
|
|
88
|
-
"../../markdowns/gopro.md":
|
|
89
|
-
"../../markdowns/hass.md":
|
|
90
|
-
"../../markdowns/homekit.md":
|
|
91
|
-
"../../markdowns/http.md":
|
|
92
|
-
"../../markdowns/isapi.md":
|
|
93
|
-
"../../markdowns/ivideon.md":
|
|
94
|
-
"../../markdowns/kasa.md":
|
|
95
|
-
"../../markdowns/nest.md":
|
|
96
|
-
"../../markdowns/onvif.md":
|
|
97
|
-
"../../markdowns/ring.md":
|
|
98
|
-
"../../markdowns/roborock.md":
|
|
99
|
-
"../../markdowns/rtmp.md":
|
|
100
|
-
"../../markdowns/rtsp.md":
|
|
101
|
-
"../../markdowns/tapo.md":
|
|
102
|
-
"../../markdowns/tuya.md":
|
|
103
|
-
"../../markdowns/webrtc.md":
|
|
104
|
-
"../../markdowns/webtorrent.md":
|
|
105
|
-
"../../markdowns/wyze.md":
|
|
106
|
-
"../../markdowns/xiaomi.md":
|
|
107
|
-
"../../markdowns/yandex.md":
|
|
78
|
+
let i = new z(), c = n, d = B(), { t: f } = K(), { mutateAsync: h, isPending: b } = i.previewCameraQuery(), S = /* #__PURE__ */ Object.assign({
|
|
79
|
+
"../../markdowns/bubble.md": We,
|
|
80
|
+
"../../markdowns/cui.md": Ge,
|
|
81
|
+
"../../markdowns/doorbird.md": Ke,
|
|
82
|
+
"../../markdowns/dvrip.md": qe,
|
|
83
|
+
"../../markdowns/echo.md": Je,
|
|
84
|
+
"../../markdowns/exec.md": Ye,
|
|
85
|
+
"../../markdowns/expr.md": Xe,
|
|
86
|
+
"../../markdowns/ffmpeg.md": Ze,
|
|
87
|
+
"../../markdowns/gopro.md": Qe,
|
|
88
|
+
"../../markdowns/hass.md": $e,
|
|
89
|
+
"../../markdowns/homekit.md": et,
|
|
90
|
+
"../../markdowns/http.md": tt,
|
|
91
|
+
"../../markdowns/isapi.md": nt,
|
|
92
|
+
"../../markdowns/ivideon.md": rt,
|
|
93
|
+
"../../markdowns/kasa.md": it,
|
|
94
|
+
"../../markdowns/nest.md": at,
|
|
95
|
+
"../../markdowns/onvif.md": ot,
|
|
96
|
+
"../../markdowns/ring.md": st,
|
|
97
|
+
"../../markdowns/roborock.md": ct,
|
|
98
|
+
"../../markdowns/rtmp.md": lt,
|
|
99
|
+
"../../markdowns/rtsp.md": ut,
|
|
100
|
+
"../../markdowns/tapo.md": dt,
|
|
101
|
+
"../../markdowns/tuya.md": ft,
|
|
102
|
+
"../../markdowns/webrtc.md": pt,
|
|
103
|
+
"../../markdowns/webtorrent.md": mt,
|
|
104
|
+
"../../markdowns/wyze.md": ht,
|
|
105
|
+
"../../markdowns/xiaomi.md": gt,
|
|
106
|
+
"../../markdowns/yandex.md": _t
|
|
108
107
|
}), w = k([
|
|
109
108
|
"high-resolution",
|
|
110
109
|
"mid-resolution",
|
|
@@ -112,30 +111,30 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
112
111
|
"snapshot"
|
|
113
112
|
]), O = k(c.sources.map((e, t) => t)), j = v(() => c.isLoading || b.value);
|
|
114
113
|
function M(e) {
|
|
115
|
-
return e.urls.some(
|
|
114
|
+
return e.urls.some(bt);
|
|
116
115
|
}
|
|
117
|
-
function
|
|
118
|
-
let t =
|
|
116
|
+
function P(e) {
|
|
117
|
+
let t = Y(e);
|
|
119
118
|
if (!t) return;
|
|
120
119
|
let n = t.replace(/[:/]+$/, "");
|
|
121
120
|
return S[`../../markdowns/${n}.md`];
|
|
122
121
|
}
|
|
123
|
-
function
|
|
124
|
-
return !!
|
|
122
|
+
function F(e) {
|
|
123
|
+
return !!P(e);
|
|
125
124
|
}
|
|
126
125
|
function R(e) {
|
|
127
126
|
c.sources[e].urls.push("");
|
|
128
127
|
}
|
|
129
|
-
function
|
|
128
|
+
function te(e, t) {
|
|
130
129
|
c.sources[e].urls.splice(t, 1);
|
|
131
130
|
}
|
|
132
|
-
function
|
|
131
|
+
function ne(e, t, n) {
|
|
133
132
|
c.sources[e].urls[t] = n;
|
|
134
133
|
}
|
|
135
|
-
function
|
|
134
|
+
function ie(e, t) {
|
|
136
135
|
e.role = t, t === "snapshot" && (e.useForSnapshot = !1, e.hotMode = !1, e.preload = !1);
|
|
137
136
|
}
|
|
138
|
-
function
|
|
137
|
+
function ae() {
|
|
139
138
|
c.sources.push({
|
|
140
139
|
_id: le(8),
|
|
141
140
|
name: "",
|
|
@@ -151,7 +150,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
151
150
|
c.sources.splice(e, 1);
|
|
152
151
|
}
|
|
153
152
|
function V(e) {
|
|
154
|
-
let t =
|
|
153
|
+
let t = P(e);
|
|
155
154
|
t && d.openTextDialog({ data: {
|
|
156
155
|
title: f("components.dialog.title.information"),
|
|
157
156
|
hideConfirmButton: !0,
|
|
@@ -160,7 +159,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
160
159
|
} });
|
|
161
160
|
}
|
|
162
161
|
async function se(e) {
|
|
163
|
-
let t =
|
|
162
|
+
let t = yt(e);
|
|
164
163
|
if (t) try {
|
|
165
164
|
let e = await h({ cameraData: { url: t } });
|
|
166
165
|
d.openImageDialog({ data: {
|
|
@@ -170,14 +169,14 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
170
169
|
} });
|
|
171
170
|
} catch {}
|
|
172
171
|
}
|
|
173
|
-
return r({ newSource:
|
|
174
|
-
let c =
|
|
175
|
-
return o(), x("div",
|
|
172
|
+
return r({ newSource: ae }), (r, i) => {
|
|
173
|
+
let c = Oe, d = Se, f = q, h = Ee, v = J, b = ce, S = N, k = Ce, P = U, ae = je, z = Ue, B = re, H = we, W = Te, le = De, G = ee;
|
|
174
|
+
return o(), x("div", xt, [A(le, {
|
|
176
175
|
value: _(O),
|
|
177
176
|
"onUpdate:value": i[0] ||= (e) => g(O) ? O.value = e : null,
|
|
178
177
|
multiple: ""
|
|
179
178
|
}, {
|
|
180
|
-
default: y(() => [(o(!0), x(C, null, a(n.sources, (i, g) => (o(), p(
|
|
179
|
+
default: y(() => [(o(!0), x(C, null, a(n.sources, (i, g) => (o(), p(W, {
|
|
181
180
|
key: i._id,
|
|
182
181
|
value: g,
|
|
183
182
|
class: u({ "border-b-0": g === n.sources.length - 1 })
|
|
@@ -187,7 +186,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
187
186
|
"px-0": g !== 0,
|
|
188
187
|
"pb-5": g === n.sources.length - 1
|
|
189
188
|
}) }, {
|
|
190
|
-
default: y(() => [T("div",
|
|
189
|
+
default: y(() => [T("div", St, [T("div", Ct, [T("span", wt, s(r.$t("components.dialog.components.new_camera.source") + ": "), 1), A(c, {
|
|
191
190
|
class: "text-color text-xs border-[1px] bg-primary-500/20 border-primary-500/30 py-2 px-3 rounded-full overflow-hidden",
|
|
192
191
|
label: i.name === "" ? r.$t("components.dialog.components.new_camera.unknown") : i.name
|
|
193
192
|
}, null, 8, ["label"])]), n.allowAddRemoveSources && n.sources.length > 1 ? (o(), p(f, {
|
|
@@ -206,11 +205,11 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
206
205
|
_: 1
|
|
207
206
|
}, 8, ["loading", "onClick"])) : m("", !0)])]),
|
|
208
207
|
_: 2
|
|
209
|
-
}, 1032, ["class"]), A(
|
|
208
|
+
}, 1032, ["class"]), A(H, { pt: { content: { class: {
|
|
210
209
|
"px-0": !0,
|
|
211
210
|
"pb-5": g === n.sources.length - 1
|
|
212
211
|
} } } }, {
|
|
213
|
-
default: y(() => [T("div",
|
|
212
|
+
default: y(() => [T("div", Tt, [
|
|
214
213
|
A(_(L), {
|
|
215
214
|
modelValue: i.name,
|
|
216
215
|
"onUpdate:modelValue": (e) => i.name = e,
|
|
@@ -223,7 +222,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
223
222
|
T("label", {
|
|
224
223
|
for: `sources[${g}].name`,
|
|
225
224
|
class: "cui-label"
|
|
226
|
-
}, s(r.$t("components.form.label.source_name")), 9,
|
|
225
|
+
}, s(r.$t("components.form.label.source_name")), 9, Et),
|
|
227
226
|
A(b, null, {
|
|
228
227
|
default: y(() => [A(v, l({ ref_for: !0 }, t, {
|
|
229
228
|
invalid: n.length > 0,
|
|
@@ -266,14 +265,14 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
266
265
|
T("label", {
|
|
267
266
|
for: `sources[${g}].role`,
|
|
268
267
|
class: "cui-label"
|
|
269
|
-
}, s(r.$t("components.form.label.source_role")), 9,
|
|
268
|
+
}, s(r.$t("components.form.label.source_role")), 9, Dt),
|
|
270
269
|
A(b, null, {
|
|
271
270
|
default: y(() => [A(k, {
|
|
272
271
|
"model-value": i.role,
|
|
273
272
|
options: _(w).filter((e) => !n.sources.some((t) => t.role === e && t._id !== i._id)),
|
|
274
273
|
invalid: t.length > 0,
|
|
275
274
|
loading: _(j),
|
|
276
|
-
onValueChange: (e) =>
|
|
275
|
+
onValueChange: (e) => ie(i, e)
|
|
277
276
|
}, null, 8, [
|
|
278
277
|
"model-value",
|
|
279
278
|
"options",
|
|
@@ -303,7 +302,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
303
302
|
]),
|
|
304
303
|
_: 2
|
|
305
304
|
}, 1032, ["model-value", "name"]),
|
|
306
|
-
T("div",
|
|
305
|
+
T("div", Ot, [
|
|
307
306
|
i.role !== "snapshot" && n.sources.length > 1 ? (o(), p(_(L), {
|
|
308
307
|
key: 0,
|
|
309
308
|
"model-value": i.useForSnapshot,
|
|
@@ -314,11 +313,11 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
314
313
|
as: "div",
|
|
315
314
|
class: "flex flex-col field-gap cui-toggle-switch"
|
|
316
315
|
}, {
|
|
317
|
-
default: y(({ field: t, errors: a }) => [T("div",
|
|
316
|
+
default: y(({ field: t, errors: a }) => [T("div", kt, [T("div", At, [
|
|
318
317
|
T("label", {
|
|
319
318
|
for: `sources[${g}].useForSnapshot`,
|
|
320
319
|
class: "cui-label-switch"
|
|
321
|
-
}, s(r.$t("components.form.label.use_for_snapshot")), 9,
|
|
320
|
+
}, s(r.$t("components.form.label.use_for_snapshot")), 9, jt),
|
|
322
321
|
A(S, {
|
|
323
322
|
severity: "secondary",
|
|
324
323
|
variant: "simple",
|
|
@@ -335,7 +334,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
335
334
|
}, null, 8, ["name"])]),
|
|
336
335
|
_: 2
|
|
337
336
|
}, 1024)
|
|
338
|
-
]), A(
|
|
337
|
+
]), A(P, l({ "model-value": i.useForSnapshot }, { ref_for: !0 }, t, {
|
|
339
338
|
invalid: a.length > 0,
|
|
340
339
|
loading: _(j),
|
|
341
340
|
disabled: n.sources.some((e) => (e.useForSnapshot || e.role === "snapshot") && e._id !== i._id),
|
|
@@ -360,11 +359,11 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
360
359
|
as: "div",
|
|
361
360
|
class: "flex flex-col field-gap cui-toggle-switch"
|
|
362
361
|
}, {
|
|
363
|
-
default: y(({ field: t, errors: n }) => [T("div",
|
|
362
|
+
default: y(({ field: t, errors: n }) => [T("div", Mt, [T("div", Nt, [
|
|
364
363
|
T("label", {
|
|
365
364
|
for: `sources[${g}].hotMode`,
|
|
366
365
|
class: "cui-label-switch"
|
|
367
|
-
}, s(r.$t("components.form.label.hot_mode")), 9,
|
|
366
|
+
}, s(r.$t("components.form.label.hot_mode")), 9, Pt),
|
|
368
367
|
A(S, {
|
|
369
368
|
severity: "secondary",
|
|
370
369
|
variant: "simple",
|
|
@@ -381,7 +380,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
381
380
|
}, null, 8, ["name"])]),
|
|
382
381
|
_: 2
|
|
383
382
|
}, 1024)
|
|
384
|
-
]), A(
|
|
383
|
+
]), A(P, l({ "model-value": i.hotMode }, { ref_for: !0 }, t, {
|
|
385
384
|
invalid: n.length > 0,
|
|
386
385
|
loading: _(j),
|
|
387
386
|
class: "ml-auto shrink-0",
|
|
@@ -404,11 +403,11 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
404
403
|
as: "div",
|
|
405
404
|
class: "flex flex-col field-gap cui-toggle-switch"
|
|
406
405
|
}, {
|
|
407
|
-
default: y(({ field: t, errors: n }) => [T("div",
|
|
406
|
+
default: y(({ field: t, errors: n }) => [T("div", Ft, [T("div", It, [
|
|
408
407
|
T("label", {
|
|
409
408
|
for: `sources[${g}].preload`,
|
|
410
409
|
class: "cui-label-switch"
|
|
411
|
-
}, s(r.$t("components.form.label.preload")), 9,
|
|
410
|
+
}, s(r.$t("components.form.label.preload")), 9, Lt),
|
|
412
411
|
A(S, {
|
|
413
412
|
severity: "secondary",
|
|
414
413
|
variant: "simple",
|
|
@@ -425,7 +424,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
425
424
|
}, null, 8, ["name"])]),
|
|
426
425
|
_: 2
|
|
427
426
|
}, 1024)
|
|
428
|
-
]), A(
|
|
427
|
+
]), A(P, l({ "model-value": i.preload }, { ref_for: !0 }, t, {
|
|
429
428
|
invalid: n.length > 0,
|
|
430
429
|
loading: _(j),
|
|
431
430
|
class: "ml-auto shrink-0",
|
|
@@ -448,11 +447,11 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
448
447
|
as: "div",
|
|
449
448
|
class: "flex flex-col field-gap cui-toggle-switch"
|
|
450
449
|
}, {
|
|
451
|
-
default: y(({ field: t, errors: n }) => [T("div",
|
|
450
|
+
default: y(({ field: t, errors: n }) => [T("div", Rt, [T("div", zt, [
|
|
452
451
|
T("label", {
|
|
453
452
|
for: `sources[${g}].muted`,
|
|
454
453
|
class: "cui-label-switch"
|
|
455
|
-
}, s(r.$t("components.form.label.muted")), 9,
|
|
454
|
+
}, s(r.$t("components.form.label.muted")), 9, Bt),
|
|
456
455
|
A(S, {
|
|
457
456
|
severity: "secondary",
|
|
458
457
|
variant: "simple",
|
|
@@ -469,7 +468,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
469
468
|
}, null, 8, ["name"])]),
|
|
470
469
|
_: 2
|
|
471
470
|
}, 1024)
|
|
472
|
-
]), A(
|
|
471
|
+
]), A(P, l({ "model-value": i.muted }, { ref_for: !0 }, t, {
|
|
473
472
|
invalid: n.length > 0,
|
|
474
473
|
loading: _(j),
|
|
475
474
|
class: "ml-auto shrink-0",
|
|
@@ -483,11 +482,11 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
483
482
|
_: 2
|
|
484
483
|
}, 1032, ["model-value", "name"]))
|
|
485
484
|
]),
|
|
486
|
-
T("div",
|
|
487
|
-
T("div",
|
|
485
|
+
T("div", Vt, [
|
|
486
|
+
T("div", Ht, [T("label", {
|
|
488
487
|
for: `sources[${g}].urls[]`,
|
|
489
488
|
class: "cui-label"
|
|
490
|
-
}, s(r.$t("components.form.label.sources")), 9,
|
|
489
|
+
}, s(r.$t("components.form.label.sources")), 9, Ut), A(S, {
|
|
491
490
|
severity: "secondary",
|
|
492
491
|
variant: "simple",
|
|
493
492
|
size: "small",
|
|
@@ -496,7 +495,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
496
495
|
default: y(() => [D(s(M(i) ? r.$t("views.devices.managed_source_hint") : r.$t("components.form.hint.source_urls")), 1)]),
|
|
497
496
|
_: 2
|
|
498
497
|
}, 1024)]),
|
|
499
|
-
(o(!0), x(C, null, a(i.urls, (n, a) => (o(), x(C, { key: a }, [_(
|
|
498
|
+
(o(!0), x(C, null, a(i.urls, (n, a) => (o(), x(C, { key: a }, [_(bt)(n) ? (o(), x("div", Wt, [A(b, null, {
|
|
500
499
|
default: y(() => [A(v, {
|
|
501
500
|
"model-value": n,
|
|
502
501
|
readonly: "",
|
|
@@ -518,30 +517,30 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
518
517
|
invalid: c.length > 0,
|
|
519
518
|
loading: _(j),
|
|
520
519
|
type: "text",
|
|
521
|
-
placeholder:
|
|
522
|
-
"onUpdate:modelValue": (e) =>
|
|
520
|
+
placeholder: Gt,
|
|
521
|
+
"onUpdate:modelValue": (e) => ne(g, a, e ?? "")
|
|
523
522
|
}, null, 8, [
|
|
524
523
|
"model-value",
|
|
525
524
|
"invalid",
|
|
526
525
|
"loading",
|
|
527
526
|
"onUpdate:modelValue"
|
|
528
|
-
]), A(
|
|
527
|
+
]), A(B, null, {
|
|
529
528
|
default: y(() => [
|
|
530
529
|
E((o(), p(f, {
|
|
531
530
|
text: "",
|
|
532
531
|
rounded: "",
|
|
533
532
|
severity: "secondary",
|
|
534
|
-
disabled: _(j) || !
|
|
533
|
+
disabled: _(j) || !F(n),
|
|
535
534
|
class: "border-right-color",
|
|
536
535
|
onClick: (e) => V(n)
|
|
537
536
|
}, {
|
|
538
|
-
icon: y(() => [A(
|
|
537
|
+
icon: y(() => [A(ae, {
|
|
539
538
|
width: "100%",
|
|
540
539
|
height: "100%"
|
|
541
540
|
})]),
|
|
542
541
|
_: 1
|
|
543
542
|
}, 8, ["disabled", "onClick"])), [[
|
|
544
|
-
|
|
543
|
+
G,
|
|
545
544
|
{ value: r.$t("components.dialog.components.new_camera.protocol_info") },
|
|
546
545
|
void 0,
|
|
547
546
|
{ top: !0 }
|
|
@@ -550,17 +549,17 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
550
549
|
text: "",
|
|
551
550
|
rounded: "",
|
|
552
551
|
severity: "secondary",
|
|
553
|
-
disabled: _(j) || !_(
|
|
552
|
+
disabled: _(j) || !_(Y)(n),
|
|
554
553
|
class: "border-right-color",
|
|
555
554
|
onClick: (e) => se(n)
|
|
556
555
|
}, {
|
|
557
|
-
icon: y(() => [A(
|
|
556
|
+
icon: y(() => [A(z, {
|
|
558
557
|
width: "100%",
|
|
559
558
|
height: "100%"
|
|
560
559
|
})]),
|
|
561
560
|
_: 1
|
|
562
561
|
}, 8, ["disabled", "onClick"])), [[
|
|
563
|
-
|
|
562
|
+
G,
|
|
564
563
|
{ value: r.$t("components.dialog.components.new_camera.test_source") },
|
|
565
564
|
void 0,
|
|
566
565
|
{ top: !0 }
|
|
@@ -571,7 +570,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
571
570
|
rounded: "",
|
|
572
571
|
severity: "danger",
|
|
573
572
|
disabled: _(j),
|
|
574
|
-
onClick: t((e) =>
|
|
573
|
+
onClick: t((e) => te(g, a), ["prevent"])
|
|
575
574
|
}, {
|
|
576
575
|
icon: y(() => [A(d, {
|
|
577
576
|
width: "100%",
|
|
@@ -597,7 +596,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
597
596
|
size: "small",
|
|
598
597
|
class: "cui-input-hint"
|
|
599
598
|
}, {
|
|
600
|
-
default: y(() => [D(s(_(
|
|
599
|
+
default: y(() => [D(s(_(Y)(n) ? r.$t("components.form.hint.source_detected_protocol", { protocol: _(Y)(n) }) : r.$t("components.form.hint.source_url")), 1)]),
|
|
601
600
|
_: 2
|
|
602
601
|
}, 1024)
|
|
603
602
|
]),
|
|
@@ -624,16 +623,16 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
624
623
|
}, 8, ["value"])]);
|
|
625
624
|
};
|
|
626
625
|
}
|
|
627
|
-
}),
|
|
626
|
+
}), qt = { class: "flex flex-col gap-2 w-full" }, Jt = {
|
|
628
627
|
for: "roomName",
|
|
629
628
|
class: "cui-label"
|
|
630
|
-
},
|
|
629
|
+
}, Yt = /* @__PURE__ */ O({
|
|
631
630
|
__name: "CreateRoom",
|
|
632
631
|
setup(e, { expose: t }) {
|
|
633
632
|
let n = k("");
|
|
634
633
|
return t({ onConfirm: async () => n.value.trim() || null }), (e, t) => {
|
|
635
|
-
let r =
|
|
636
|
-
return o(), x("div",
|
|
634
|
+
let r = J;
|
|
635
|
+
return o(), x("div", qt, [T("label", Jt, s(e.$t("components.form.label.name")), 1), A(r, {
|
|
637
636
|
id: "roomName",
|
|
638
637
|
modelValue: _(n),
|
|
639
638
|
"onUpdate:modelValue": t[0] ||= (e) => g(n) ? n.value = e : null,
|
|
@@ -646,7 +645,7 @@ var Ct = { class: "flex flex-col gap-6" }, wt = { class: "flex gap-2 items-cente
|
|
|
646
645
|
});
|
|
647
646
|
//#endregion
|
|
648
647
|
//#region src/components/CuiCameraDetailsFields/rooms.ts
|
|
649
|
-
function
|
|
648
|
+
function Xt(e, t) {
|
|
650
649
|
let n = e?.rooms ?? [], r = [...e?.levels ?? []].sort((e, t) => e.order - t.order), i = (e) => ({
|
|
651
650
|
label: e.name === "Default" ? t("components.form.label.room_default") : e.name,
|
|
652
651
|
value: e.id
|
|
@@ -668,46 +667,46 @@ function Qt(e, t) {
|
|
|
668
667
|
}
|
|
669
668
|
//#endregion
|
|
670
669
|
//#region src/components/CuiCameraDetailsFields/CuiCameraDetailsFields.vue?vue&type=script&setup=true&lang.ts
|
|
671
|
-
var
|
|
670
|
+
var Zt = { class: "flex flex-col gap-6" }, Qt = {
|
|
672
671
|
for: "name",
|
|
673
672
|
class: "cui-label"
|
|
674
|
-
},
|
|
673
|
+
}, $t = { class: "flex flex-col field-gap" }, en = {
|
|
675
674
|
for: "type",
|
|
676
675
|
class: "cui-label"
|
|
677
|
-
},
|
|
676
|
+
}, tn = { class: "flex flex-col field-gap" }, nn = {
|
|
678
677
|
for: "room",
|
|
679
678
|
class: "cui-label"
|
|
680
|
-
},
|
|
679
|
+
}, rn = { class: "flex gap-2" }, an = { class: "text-color font-normal" }, on = { class: "flex flex-col gap-6" }, sn = {
|
|
681
680
|
for: "info.manufacturer",
|
|
682
681
|
class: "cui-label"
|
|
683
|
-
},
|
|
682
|
+
}, cn = {
|
|
684
683
|
for: "info.model",
|
|
685
684
|
class: "cui-label"
|
|
686
|
-
},
|
|
685
|
+
}, ln = {
|
|
687
686
|
for: "info.hardware",
|
|
688
687
|
class: "cui-label"
|
|
689
|
-
},
|
|
688
|
+
}, un = {
|
|
690
689
|
for: "info.serialNumber",
|
|
691
690
|
class: "cui-label"
|
|
692
|
-
},
|
|
691
|
+
}, dn = {
|
|
693
692
|
for: "info.firmwareVersion",
|
|
694
693
|
class: "cui-label"
|
|
695
|
-
},
|
|
694
|
+
}, fn = {
|
|
696
695
|
for: "info.supportUrl",
|
|
697
696
|
class: "cui-label"
|
|
698
|
-
},
|
|
697
|
+
}, pn = /* @__PURE__ */ O({
|
|
699
698
|
__name: "CuiCameraDetailsFields",
|
|
700
699
|
props: {
|
|
701
700
|
form: {},
|
|
702
701
|
isLoading: { type: Boolean }
|
|
703
702
|
},
|
|
704
703
|
setup(t) {
|
|
705
|
-
let n = new
|
|
704
|
+
let n = new Be(), r = t, i = B(), { t: a } = K(), { data: u, isBusy: d } = n.getRoomsQuery(), { mutateAsync: f } = n.createRoomMutation(), h = k(["camera", "doorbell"]), g = v(() => (u.value?.levels.length ?? 0) > 0), b = v(() => Xt(u.value, a));
|
|
706
705
|
function S(e) {
|
|
707
706
|
r.form.roomId = e;
|
|
708
707
|
}
|
|
709
708
|
function C() {
|
|
710
|
-
i.openComponentDialog(
|
|
709
|
+
i.openComponentDialog(Yt, {
|
|
711
710
|
data: {
|
|
712
711
|
title: a("components.dialog.title.create_room"),
|
|
713
712
|
confirmText: a("components.form.button.add"),
|
|
@@ -725,8 +724,8 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
725
724
|
});
|
|
726
725
|
}
|
|
727
726
|
return (n, r) => {
|
|
728
|
-
let i =
|
|
729
|
-
return o(), x("div",
|
|
727
|
+
let i = J, a = ce, u = N, f = Ce, v = Fe, w = q, O = Ee, k = we, j = Te, M = De, P = ee;
|
|
728
|
+
return o(), x("div", Zt, [
|
|
730
729
|
A(_(L), {
|
|
731
730
|
modelValue: t.form.name,
|
|
732
731
|
"onUpdate:modelValue": r[0] ||= (e) => t.form.name = e,
|
|
@@ -736,7 +735,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
736
735
|
class: "flex flex-col field-gap"
|
|
737
736
|
}, {
|
|
738
737
|
default: y(({ field: r, errors: c }) => [
|
|
739
|
-
T("label",
|
|
738
|
+
T("label", Qt, s(n.$t("components.form.label.name")), 1),
|
|
740
739
|
A(a, null, {
|
|
741
740
|
default: y(() => [A(i, l(r, {
|
|
742
741
|
invalid: c.length > 0,
|
|
@@ -765,7 +764,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
765
764
|
]),
|
|
766
765
|
_: 1
|
|
767
766
|
}, 8, ["modelValue"]),
|
|
768
|
-
T("div",
|
|
767
|
+
T("div", $t, [T("label", en, s(n.$t("components.form.label.type")), 1), A(a, null, {
|
|
769
768
|
default: y(() => [A(f, {
|
|
770
769
|
"model-value": t.form.type,
|
|
771
770
|
options: _(h),
|
|
@@ -779,9 +778,9 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
779
778
|
])]),
|
|
780
779
|
_: 1
|
|
781
780
|
})]),
|
|
782
|
-
T("div",
|
|
783
|
-
T("label",
|
|
784
|
-
T("div",
|
|
781
|
+
T("div", tn, [
|
|
782
|
+
T("label", nn, s(n.$t("components.form.label.room")), 1),
|
|
783
|
+
T("div", rn, [A(f, {
|
|
785
784
|
"model-value": t.form.roomId,
|
|
786
785
|
options: _(b),
|
|
787
786
|
"option-label": "label",
|
|
@@ -806,7 +805,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
806
805
|
icon: y(() => [A(v, { class: "w-4 h-4" })]),
|
|
807
806
|
_: 1
|
|
808
807
|
})), [[
|
|
809
|
-
|
|
808
|
+
P,
|
|
810
809
|
n.$t("components.form.button.create_room"),
|
|
811
810
|
void 0,
|
|
812
811
|
{ top: !0 }
|
|
@@ -825,10 +824,10 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
825
824
|
A(M, null, {
|
|
826
825
|
default: y(() => [A(j, { value: "branding" }, {
|
|
827
826
|
default: y(() => [A(O, { class: "px-0 pt-0" }, {
|
|
828
|
-
default: y(() => [T("span",
|
|
827
|
+
default: y(() => [T("span", an, s(n.$t("components.camera_options.branding")), 1)]),
|
|
829
828
|
_: 1
|
|
830
829
|
}), A(k, { pt: { content: { class: "px-0" } } }, {
|
|
831
|
-
default: y(() => [T("div",
|
|
830
|
+
default: y(() => [T("div", on, [
|
|
832
831
|
A(_(L), {
|
|
833
832
|
modelValue: t.form.info.manufacturer,
|
|
834
833
|
"onUpdate:modelValue": r[3] ||= (e) => t.form.info.manufacturer = e,
|
|
@@ -838,7 +837,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
838
837
|
class: "flex flex-col field-gap"
|
|
839
838
|
}, {
|
|
840
839
|
default: y(({ field: r, errors: o }) => [
|
|
841
|
-
T("label",
|
|
840
|
+
T("label", sn, s(n.$t("components.form.label.manufacturer")), 1),
|
|
842
841
|
A(a, null, {
|
|
843
842
|
default: y(() => [A(i, l(r, {
|
|
844
843
|
invalid: o.length > 0,
|
|
@@ -866,7 +865,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
866
865
|
class: "flex flex-col field-gap"
|
|
867
866
|
}, {
|
|
868
867
|
default: y(({ field: r, errors: o }) => [
|
|
869
|
-
T("label",
|
|
868
|
+
T("label", cn, s(n.$t("components.form.label.model")), 1),
|
|
870
869
|
A(a, null, {
|
|
871
870
|
default: y(() => [A(i, l(r, {
|
|
872
871
|
invalid: o.length > 0,
|
|
@@ -894,7 +893,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
894
893
|
class: "flex flex-col field-gap"
|
|
895
894
|
}, {
|
|
896
895
|
default: y(({ field: r, errors: o }) => [
|
|
897
|
-
T("label",
|
|
896
|
+
T("label", ln, s(n.$t("components.form.label.hardware_version")), 1),
|
|
898
897
|
A(a, null, {
|
|
899
898
|
default: y(() => [A(i, l(r, {
|
|
900
899
|
invalid: o.length > 0,
|
|
@@ -922,7 +921,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
922
921
|
class: "flex flex-col field-gap"
|
|
923
922
|
}, {
|
|
924
923
|
default: y(({ field: r, errors: o }) => [
|
|
925
|
-
T("label",
|
|
924
|
+
T("label", un, s(n.$t("components.form.label.serial_number")), 1),
|
|
926
925
|
A(a, null, {
|
|
927
926
|
default: y(() => [A(i, l(r, {
|
|
928
927
|
invalid: o.length > 0,
|
|
@@ -950,7 +949,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
950
949
|
class: "flex flex-col field-gap"
|
|
951
950
|
}, {
|
|
952
951
|
default: y(({ field: r, errors: o }) => [
|
|
953
|
-
T("label",
|
|
952
|
+
T("label", dn, s(n.$t("components.form.label.firmware_version")), 1),
|
|
954
953
|
A(a, null, {
|
|
955
954
|
default: y(() => [A(i, l(r, {
|
|
956
955
|
invalid: o.length > 0,
|
|
@@ -978,7 +977,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
978
977
|
class: "flex flex-col field-gap"
|
|
979
978
|
}, {
|
|
980
979
|
default: y(({ field: r, errors: o }) => [
|
|
981
|
-
T("label",
|
|
980
|
+
T("label", fn, s(n.$t("components.form.label.support_url")), 1),
|
|
982
981
|
A(a, null, {
|
|
983
982
|
default: y(() => [A(i, l(r, {
|
|
984
983
|
invalid: o.length > 0,
|
|
@@ -1007,26 +1006,26 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1007
1006
|
]);
|
|
1008
1007
|
};
|
|
1009
1008
|
}
|
|
1010
|
-
}),
|
|
1011
|
-
name:
|
|
1012
|
-
urls:
|
|
1013
|
-
role:
|
|
1014
|
-
useForSnapshot:
|
|
1015
|
-
hotMode:
|
|
1016
|
-
preload:
|
|
1017
|
-
muted:
|
|
1018
|
-
backchannelDisabled:
|
|
1019
|
-
timeout:
|
|
1020
|
-
handshakeTimeout:
|
|
1021
|
-
childSourceId:
|
|
1009
|
+
}), mn = RegExp(`^(${ge.join("|")})`), hn = P().trim().min(1, "Camera Source is required").regex(mn, "Unsupported protocol — start the URL with a supported one (e.g. rtsp://)"), gn = W({
|
|
1010
|
+
name: P().trim().min(1, "Camera Source Name is required"),
|
|
1011
|
+
urls: hn.array(),
|
|
1012
|
+
role: ve,
|
|
1013
|
+
useForSnapshot: F().default(!1),
|
|
1014
|
+
hotMode: F().default(!0),
|
|
1015
|
+
preload: F().default(!0),
|
|
1016
|
+
muted: F().default(!1),
|
|
1017
|
+
backchannelDisabled: F().default(!1),
|
|
1018
|
+
timeout: te().int().min(5).max(120).nullish(),
|
|
1019
|
+
handshakeTimeout: te().int().min(1).max(60).nullish(),
|
|
1020
|
+
childSourceId: P().trim().nullish()
|
|
1022
1021
|
}).strict().transform((e) => e.role === "snapshot" ? {
|
|
1023
1022
|
...e,
|
|
1024
1023
|
useForSnapshot: !1,
|
|
1025
1024
|
hotMode: !1,
|
|
1026
1025
|
preload: !1
|
|
1027
|
-
} : e),
|
|
1028
|
-
...
|
|
1029
|
-
sources:
|
|
1026
|
+
} : e), _n = W({
|
|
1027
|
+
..._e.shape,
|
|
1028
|
+
sources: gn.array().refine((e) => e.some((e) => e.role === "high-resolution" || e.role === "mid-resolution" || e.role === "low-resolution"), {
|
|
1030
1029
|
path: ["sources[].role"],
|
|
1031
1030
|
message: "One of the roles \"high-resolution\", \"mid-resolution\" or \"low-resolution\" is required"
|
|
1032
1031
|
}).refine((e) => e.filter((e) => e.useForSnapshot).length <= 1, {
|
|
@@ -1038,8 +1037,8 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1038
1037
|
}, {
|
|
1039
1038
|
message: "Each source role can be assigned to only one source",
|
|
1040
1039
|
path: ["sources"]
|
|
1041
|
-
}).superRefine(
|
|
1042
|
-
}).strict(),
|
|
1040
|
+
}).superRefine(ye)
|
|
1041
|
+
}).strict(), vn = {
|
|
1043
1042
|
disabled: !1,
|
|
1044
1043
|
name: "",
|
|
1045
1044
|
type: "camera",
|
|
@@ -1073,25 +1072,25 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1073
1072
|
},
|
|
1074
1073
|
plugins: [],
|
|
1075
1074
|
assignments: {}
|
|
1076
|
-
},
|
|
1075
|
+
}, yn = { class: "card-title" }, bn = { class: "card-title" }, xn = { class: "w-full flex items-center justify-center mt-4" }, Sn = /* @__PURE__ */ O({
|
|
1077
1076
|
__name: "AddCamera",
|
|
1078
|
-
props: { camera: { default: () =>
|
|
1077
|
+
props: { camera: { default: () => vn } },
|
|
1079
1078
|
setup(e, { expose: t }) {
|
|
1080
|
-
let n = new
|
|
1079
|
+
let n = new z(), r = e, a = H(), { t: c } = K(), { mutateAsync: l, isPending: u } = n.createCameraQuery(), { camera: d } = i(r), f = w("formRef"), p = w("sourcesRef"), m = k(V(d.value)), h = v(() => u.value);
|
|
1081
1080
|
async function g() {
|
|
1082
1081
|
if (!(await f.value?.validate())?.valid) return a.add({
|
|
1083
1082
|
severity: "error",
|
|
1084
1083
|
detail: c("components.toast.validation_failed"),
|
|
1085
1084
|
life: 3e3
|
|
1086
1085
|
}), null;
|
|
1087
|
-
let e =
|
|
1088
|
-
...
|
|
1086
|
+
let e = V(m.value), t = {
|
|
1087
|
+
...be(),
|
|
1089
1088
|
...e,
|
|
1090
1089
|
sources: e.sources.map((e) => ({
|
|
1091
1090
|
...e,
|
|
1092
1091
|
muted: e.muted ?? !1,
|
|
1093
1092
|
backchannelDisabled: e.backchannelDisabled ?? !1,
|
|
1094
|
-
urls: e.urls.map(
|
|
1093
|
+
urls: e.urls.map(yt).filter(Boolean)
|
|
1095
1094
|
}))
|
|
1096
1095
|
};
|
|
1097
1096
|
await l({ cameraData: t });
|
|
@@ -1101,21 +1100,21 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1101
1100
|
onSave: g,
|
|
1102
1101
|
onConfirm: g
|
|
1103
1102
|
}), (e, t) => {
|
|
1104
|
-
let n =
|
|
1103
|
+
let n = pn, r = me, i = Kt, a = Me, c = q;
|
|
1105
1104
|
return o(), x("div", null, [A(_(R), {
|
|
1106
1105
|
ref_key: "formRef",
|
|
1107
1106
|
ref: f,
|
|
1108
1107
|
class: "flex flex-col w-full gap-6",
|
|
1109
|
-
"validation-schema": _(
|
|
1108
|
+
"validation-schema": _(_n)
|
|
1110
1109
|
}, {
|
|
1111
|
-
default: y(() => [T("div", null, [T("span",
|
|
1110
|
+
default: y(() => [T("div", null, [T("span", yn, s(e.$t("components.dialog.components.new_camera.camera")), 1), A(r, { class: "cui-card" }, {
|
|
1112
1111
|
content: y(() => [A(n, {
|
|
1113
1112
|
form: _(m),
|
|
1114
1113
|
"is-loading": _(h)
|
|
1115
1114
|
}, null, 8, ["form", "is-loading"])]),
|
|
1116
1115
|
_: 1
|
|
1117
1116
|
})]), T("div", null, [
|
|
1118
|
-
T("span",
|
|
1117
|
+
T("span", bn, s(e.$t("components.form.label.sources")), 1),
|
|
1119
1118
|
A(r, {
|
|
1120
1119
|
class: "cui-card border-color-inner",
|
|
1121
1120
|
pt: { body: { class: "pb-0" } }
|
|
@@ -1129,7 +1128,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1129
1128
|
}, null, 8, ["sources", "is-loading"])]),
|
|
1130
1129
|
_: 1
|
|
1131
1130
|
}),
|
|
1132
|
-
T("div",
|
|
1131
|
+
T("div", xn, [A(c, {
|
|
1133
1132
|
text: "",
|
|
1134
1133
|
rounded: "",
|
|
1135
1134
|
loading: _(h),
|
|
@@ -1147,17 +1146,17 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1147
1146
|
}, 8, ["validation-schema"])]);
|
|
1148
1147
|
};
|
|
1149
1148
|
}
|
|
1150
|
-
}),
|
|
1149
|
+
}), Cn = { class: "card-title" }, wn = {
|
|
1151
1150
|
key: 0,
|
|
1152
1151
|
class: "flex flex-col gap-6"
|
|
1153
|
-
},
|
|
1152
|
+
}, Tn = { class: "cui-label" }, En = { class: "card-title" }, Dn = /* @__PURE__ */ O({
|
|
1154
1153
|
__name: "ConfirmCamera",
|
|
1155
1154
|
props: {
|
|
1156
1155
|
draft: {},
|
|
1157
1156
|
onConfirm: { type: Function }
|
|
1158
1157
|
},
|
|
1159
1158
|
setup(e, { expose: t }) {
|
|
1160
|
-
let n =
|
|
1159
|
+
let n = W({ name: P().trim().min(1) }).passthrough(), r = e, i = H(), { t: c } = K(), l = w("formRef"), u = k(V(r.draft)), d = k({
|
|
1161
1160
|
name: u.value.name,
|
|
1162
1161
|
type: u.value.type,
|
|
1163
1162
|
room: u.value.room,
|
|
@@ -1194,7 +1193,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1194
1193
|
info: d.value.info,
|
|
1195
1194
|
sources: d.value.sources.map((e) => ({
|
|
1196
1195
|
...e,
|
|
1197
|
-
urls: e.urls.map(
|
|
1196
|
+
urls: e.urls.map(yt).filter(Boolean)
|
|
1198
1197
|
}))
|
|
1199
1198
|
};
|
|
1200
1199
|
await r.onConfirm(e);
|
|
@@ -1213,22 +1212,22 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1213
1212
|
isLoading: h,
|
|
1214
1213
|
onConfirm: g
|
|
1215
1214
|
}), (e, t) => {
|
|
1216
|
-
let r =
|
|
1215
|
+
let r = J, i = ce, c = pn, u = me, f = Kt;
|
|
1217
1216
|
return o(), x("div", null, [A(_(R), {
|
|
1218
1217
|
ref_key: "formRef",
|
|
1219
1218
|
ref: l,
|
|
1220
1219
|
class: "flex flex-col w-full gap-6",
|
|
1221
1220
|
"validation-schema": _(n)
|
|
1222
1221
|
}, {
|
|
1223
|
-
default: y(() => [T("div", null, [T("span",
|
|
1222
|
+
default: y(() => [T("div", null, [T("span", Cn, s(e.$t("components.dialog.components.new_camera.camera")), 1), A(u, { class: "cui-card" }, {
|
|
1224
1223
|
content: y(() => [A(c, {
|
|
1225
1224
|
form: _(d),
|
|
1226
1225
|
"is-loading": _(h)
|
|
1227
1226
|
}, {
|
|
1228
|
-
default: y(() => [_(p).length ? (o(), x("div",
|
|
1227
|
+
default: y(() => [_(p).length ? (o(), x("div", wn, [(o(!0), x(C, null, a(_(p), (e) => (o(), x("div", {
|
|
1229
1228
|
key: e.label,
|
|
1230
1229
|
class: "flex flex-col field-gap"
|
|
1231
|
-
}, [T("label",
|
|
1230
|
+
}, [T("label", Tn, s(e.label), 1), A(i, null, {
|
|
1232
1231
|
default: y(() => [A(r, {
|
|
1233
1232
|
"model-value": e.value,
|
|
1234
1233
|
readonly: "",
|
|
@@ -1239,7 +1238,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1239
1238
|
_: 1
|
|
1240
1239
|
}, 8, ["form", "is-loading"])]),
|
|
1241
1240
|
_: 1
|
|
1242
|
-
})]), T("div", null, [T("span",
|
|
1241
|
+
})]), T("div", null, [T("span", En, s(e.$t("components.form.label.sources")), 1), A(u, {
|
|
1243
1242
|
class: "cui-card border-color-inner",
|
|
1244
1243
|
pt: { body: { class: "pb-0" } }
|
|
1245
1244
|
}, {
|
|
@@ -1254,13 +1253,13 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1254
1253
|
}, 8, ["validation-schema"])]);
|
|
1255
1254
|
};
|
|
1256
1255
|
}
|
|
1257
|
-
}),
|
|
1256
|
+
}), On = { class: "flex flex-col gap-6" }, kn = {
|
|
1258
1257
|
key: 0,
|
|
1259
1258
|
class: "flex flex-col field-gap"
|
|
1260
|
-
},
|
|
1259
|
+
}, An = { class: "cui-label" }, jn = {
|
|
1261
1260
|
key: 1,
|
|
1262
1261
|
class: "text-center py-4"
|
|
1263
|
-
},
|
|
1262
|
+
}, Mn = { class: "text-muted" }, Nn = /* @__PURE__ */ O({
|
|
1264
1263
|
__name: "ConnectionSchema",
|
|
1265
1264
|
props: {
|
|
1266
1265
|
camera: {},
|
|
@@ -1268,7 +1267,7 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1268
1267
|
onConnect: { type: Function }
|
|
1269
1268
|
},
|
|
1270
1269
|
setup(e, { expose: t }) {
|
|
1271
|
-
let n = e, a =
|
|
1270
|
+
let n = e, a = he(), c = H(), { t: l } = K(), u = r("dialogRefProps"), { schema: d } = i(n), f = w("schemaFormRef"), h = k(!1), g = v(() => ({
|
|
1272
1271
|
schema: d.value,
|
|
1273
1272
|
config: {}
|
|
1274
1273
|
})), y = v(() => !!(u.loading?.value || h.value));
|
|
@@ -1301,11 +1300,11 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1301
1300
|
isLoading: y,
|
|
1302
1301
|
onConfirm: b
|
|
1303
1302
|
}), (t, n) => {
|
|
1304
|
-
let r =
|
|
1305
|
-
return o(), x("div",
|
|
1303
|
+
let r = J, i = Ne;
|
|
1304
|
+
return o(), x("div", On, [e.camera.address ? (o(), x("div", kn, [T("label", An, s(t.$t("views.devices.address")), 1), A(r, {
|
|
1306
1305
|
"model-value": e.camera.address,
|
|
1307
1306
|
readonly: ""
|
|
1308
|
-
}, null, 8, ["model-value"])])) : m("", !0), _(d).length === 0 ? (o(), x("div",
|
|
1307
|
+
}, null, 8, ["model-value"])])) : m("", !0), _(d).length === 0 ? (o(), x("div", jn, [T("p", Mn, s(t.$t("views.devices.no_settings_required")), 1)])) : (o(), p(i, {
|
|
1309
1308
|
key: 2,
|
|
1310
1309
|
ref_key: "schemaFormRef",
|
|
1311
1310
|
ref: f,
|
|
@@ -1314,98 +1313,98 @@ var $t = { class: "flex flex-col gap-6" }, en = {
|
|
|
1314
1313
|
}, null, 8, ["schema-form", "loading"]))]);
|
|
1315
1314
|
};
|
|
1316
1315
|
}
|
|
1317
|
-
}),
|
|
1316
|
+
}), Pn = 5e3, X = j({
|
|
1318
1317
|
isLoading: !0,
|
|
1319
1318
|
devices: [],
|
|
1320
1319
|
isScanning: !1,
|
|
1321
1320
|
hiddenDevices: [],
|
|
1322
1321
|
showHidden: !1,
|
|
1323
1322
|
error: null
|
|
1324
|
-
}),
|
|
1323
|
+
}), Fn = null, Z = null, Q = !1, $ = 0, In = null;
|
|
1325
1324
|
function Ln() {
|
|
1326
|
-
|
|
1325
|
+
X.isLoading = !0, X.devices = [], X.isScanning = !1, X.hiddenDevices = [], X.showHidden = !1, X.error = null;
|
|
1327
1326
|
}
|
|
1328
1327
|
function Rn() {
|
|
1329
|
-
return
|
|
1328
|
+
return Z || (Fn = h(!0), Fn.run(() => {
|
|
1330
1329
|
let e = de("/cameras");
|
|
1331
|
-
|
|
1330
|
+
Z = e, e.onReady(() => {
|
|
1332
1331
|
zn();
|
|
1333
1332
|
}), b(e.connected, (e, t) => {
|
|
1334
|
-
!e && t && (
|
|
1333
|
+
!e && t && (Q = !1);
|
|
1335
1334
|
}), e.on("cameras:discovered", (e) => {
|
|
1336
1335
|
for (let t of e.devices) {
|
|
1337
|
-
let e =
|
|
1338
|
-
e >= 0 ?
|
|
1336
|
+
let e = X.devices.findIndex((e) => e.id === t.id);
|
|
1337
|
+
e >= 0 ? X.devices[e] = t : X.devices.push(t);
|
|
1339
1338
|
}
|
|
1340
1339
|
}), e.on("cameras:scanning", (e) => {
|
|
1341
|
-
|
|
1340
|
+
X.isScanning = e.isScanning;
|
|
1342
1341
|
}), e.on("cameras:connection-status", (e) => {
|
|
1343
|
-
let t =
|
|
1344
|
-
t && (e.status === "connecting" ? t.status = "adopting" : e.status === "error" ? (t.status = "error", t.errorMessage = e.errorMessage) : e.status === "connected" && (
|
|
1342
|
+
let t = X.devices.find((t) => t.discoveredId === e.discoveredId);
|
|
1343
|
+
t && (e.status === "connecting" ? t.status = "adopting" : e.status === "error" ? (t.status = "error", t.errorMessage = e.errorMessage) : e.status === "connected" && (X.devices = X.devices.filter((t) => t.discoveredId !== e.discoveredId)));
|
|
1345
1344
|
}), e.on("cameras:camera-connected", (e) => {
|
|
1346
|
-
|
|
1345
|
+
X.devices = X.devices.filter((t) => t.discoveredId !== e.discoveredId);
|
|
1347
1346
|
}), e.on("cameras:deleted", (e) => {
|
|
1348
|
-
|
|
1347
|
+
X.devices = X.devices.filter((t) => t.cameraId !== e.cameraId);
|
|
1349
1348
|
});
|
|
1350
|
-
}),
|
|
1349
|
+
}), Z);
|
|
1351
1350
|
}
|
|
1352
1351
|
async function zn() {
|
|
1353
|
-
if (!
|
|
1354
|
-
success:
|
|
1355
|
-
devices:
|
|
1356
|
-
isScanning:
|
|
1357
|
-
hiddenDevices:
|
|
1352
|
+
if (!Z || Q) return {
|
|
1353
|
+
success: Q,
|
|
1354
|
+
devices: X.devices,
|
|
1355
|
+
isScanning: X.isScanning,
|
|
1356
|
+
hiddenDevices: X.hiddenDevices
|
|
1358
1357
|
};
|
|
1359
1358
|
try {
|
|
1360
|
-
let e = await
|
|
1361
|
-
return
|
|
1359
|
+
let e = await Z.request("cameras:subscribe", {});
|
|
1360
|
+
return Q = e.success, e.devices && (X.devices = e.devices), e.isScanning !== void 0 && (X.isScanning = e.isScanning), e.hiddenDevices && (X.hiddenDevices = e.hiddenDevices), X.isLoading = !1, e;
|
|
1362
1361
|
} catch (e) {
|
|
1363
|
-
return
|
|
1362
|
+
return X.isLoading = !1, X.error = e instanceof Error ? e.message : "subscribe failed", { success: !1 };
|
|
1364
1363
|
}
|
|
1365
1364
|
}
|
|
1366
1365
|
async function Bn() {
|
|
1367
|
-
if (!
|
|
1366
|
+
if (!Z || !Q) return { success: !0 };
|
|
1368
1367
|
try {
|
|
1369
|
-
let e = await
|
|
1370
|
-
return
|
|
1368
|
+
let e = await Z.request("cameras:unsubscribe", {});
|
|
1369
|
+
return Q = !e.success, e;
|
|
1371
1370
|
} catch {
|
|
1372
1371
|
return { success: !1 };
|
|
1373
1372
|
}
|
|
1374
1373
|
}
|
|
1375
1374
|
function Vn() {
|
|
1376
|
-
|
|
1375
|
+
Q && Bn(), Fn?.stop(), Fn = null, Z = null, Q = !1, Ln();
|
|
1377
1376
|
}
|
|
1378
1377
|
function Hn() {
|
|
1379
|
-
|
|
1378
|
+
In &&= (clearTimeout(In), null), $++;
|
|
1380
1379
|
function e() {
|
|
1381
|
-
Rn(),
|
|
1380
|
+
Rn(), Z?.connected.value && !Q && zn();
|
|
1382
1381
|
}
|
|
1383
1382
|
function t() {
|
|
1384
|
-
|
|
1383
|
+
Q && Bn();
|
|
1385
1384
|
}
|
|
1386
1385
|
async function n() {
|
|
1387
|
-
if (!
|
|
1386
|
+
if (!Z?.ready.value) return {
|
|
1388
1387
|
success: !1,
|
|
1389
1388
|
error: "Not connected"
|
|
1390
1389
|
};
|
|
1391
|
-
|
|
1390
|
+
X.devices = [], X.isScanning = !0;
|
|
1392
1391
|
try {
|
|
1393
|
-
let e = await
|
|
1394
|
-
return e.success || (
|
|
1392
|
+
let e = await Z.request("cameras:rescan", {});
|
|
1393
|
+
return e.success || (X.isScanning = !1), e;
|
|
1395
1394
|
} catch (e) {
|
|
1396
|
-
return
|
|
1395
|
+
return X.isScanning = !1, {
|
|
1397
1396
|
success: !1,
|
|
1398
1397
|
error: e instanceof Error ? e.message : "rescan failed"
|
|
1399
1398
|
};
|
|
1400
1399
|
}
|
|
1401
1400
|
}
|
|
1402
1401
|
async function r(e) {
|
|
1403
|
-
if (!
|
|
1402
|
+
if (!Z?.ready.value) return {
|
|
1404
1403
|
success: !1,
|
|
1405
1404
|
error: "Not connected"
|
|
1406
1405
|
};
|
|
1407
1406
|
try {
|
|
1408
|
-
return await
|
|
1407
|
+
return await Z.request("cameras:get-schema", { discoveredId: e });
|
|
1409
1408
|
} catch (e) {
|
|
1410
1409
|
return {
|
|
1411
1410
|
success: !1,
|
|
@@ -1414,12 +1413,12 @@ function Hn() {
|
|
|
1414
1413
|
}
|
|
1415
1414
|
}
|
|
1416
1415
|
async function i(e, t) {
|
|
1417
|
-
if (!
|
|
1416
|
+
if (!Z?.ready.value) return {
|
|
1418
1417
|
success: !1,
|
|
1419
1418
|
error: "Not connected"
|
|
1420
1419
|
};
|
|
1421
1420
|
try {
|
|
1422
|
-
return await
|
|
1421
|
+
return await Z.request("cameras:connect", {
|
|
1423
1422
|
discoveredId: e,
|
|
1424
1423
|
credentials: t
|
|
1425
1424
|
});
|
|
@@ -1431,8 +1430,8 @@ function Hn() {
|
|
|
1431
1430
|
}
|
|
1432
1431
|
}
|
|
1433
1432
|
async function a(e, t) {
|
|
1434
|
-
if (!
|
|
1435
|
-
let n = await
|
|
1433
|
+
if (!Z?.ready.value) throw Error("Not connected");
|
|
1434
|
+
let n = await Z.request("cameras:prepare", {
|
|
1436
1435
|
discoveredId: e,
|
|
1437
1436
|
credentials: t
|
|
1438
1437
|
});
|
|
@@ -1440,8 +1439,8 @@ function Hn() {
|
|
|
1440
1439
|
return n.draft;
|
|
1441
1440
|
}
|
|
1442
1441
|
async function o(e, t) {
|
|
1443
|
-
if (!
|
|
1444
|
-
let n = await
|
|
1442
|
+
if (!Z?.ready.value) throw Error("Not connected");
|
|
1443
|
+
let n = await Z.request("cameras:confirm", {
|
|
1445
1444
|
draft: e,
|
|
1446
1445
|
discoveredId: t
|
|
1447
1446
|
});
|
|
@@ -1452,7 +1451,7 @@ function Hn() {
|
|
|
1452
1451
|
};
|
|
1453
1452
|
}
|
|
1454
1453
|
async function s(e) {
|
|
1455
|
-
if (!
|
|
1454
|
+
if (!Z?.ready.value) return {
|
|
1456
1455
|
success: !1,
|
|
1457
1456
|
error: "Not connected"
|
|
1458
1457
|
};
|
|
@@ -1462,8 +1461,8 @@ function Hn() {
|
|
|
1462
1461
|
model: e.model
|
|
1463
1462
|
};
|
|
1464
1463
|
try {
|
|
1465
|
-
let e = await
|
|
1466
|
-
return e.success && e.hiddenDevices && (
|
|
1464
|
+
let e = await Z.request("cameras:hide-device", { device: t });
|
|
1465
|
+
return e.success && e.hiddenDevices && (X.hiddenDevices = e.hiddenDevices), e;
|
|
1467
1466
|
} catch (e) {
|
|
1468
1467
|
return {
|
|
1469
1468
|
success: !1,
|
|
@@ -1472,13 +1471,13 @@ function Hn() {
|
|
|
1472
1471
|
}
|
|
1473
1472
|
}
|
|
1474
1473
|
async function c(e) {
|
|
1475
|
-
if (!
|
|
1474
|
+
if (!Z?.ready.value) return {
|
|
1476
1475
|
success: !1,
|
|
1477
1476
|
error: "Not connected"
|
|
1478
1477
|
};
|
|
1479
1478
|
try {
|
|
1480
|
-
let t = await
|
|
1481
|
-
return t.success && t.hiddenDevices && (
|
|
1479
|
+
let t = await Z.request("cameras:unhide-device", { deviceId: e });
|
|
1480
|
+
return t.success && t.hiddenDevices && (X.hiddenDevices = t.hiddenDevices), t;
|
|
1482
1481
|
} catch (e) {
|
|
1483
1482
|
return {
|
|
1484
1483
|
success: !1,
|
|
@@ -1487,32 +1486,32 @@ function Hn() {
|
|
|
1487
1486
|
}
|
|
1488
1487
|
}
|
|
1489
1488
|
function l() {
|
|
1490
|
-
|
|
1489
|
+
X.showHidden = !X.showHidden;
|
|
1491
1490
|
}
|
|
1492
1491
|
function u(e) {
|
|
1493
|
-
return e.type !== "discovered" || !e.discoveredId ? !1 :
|
|
1492
|
+
return e.type !== "discovered" || !e.discoveredId ? !1 : X.hiddenDevices.some((t) => t.id === e.discoveredId);
|
|
1494
1493
|
}
|
|
1495
1494
|
let d = v(() => {
|
|
1496
|
-
let e = new Set(
|
|
1495
|
+
let e = new Set(X.hiddenDevices.map((e) => e.id)), t = (e, t) => e.name.localeCompare(t.name), n = X.devices.filter((e) => e.type === "camera").sort(t), r = X.devices.filter((t) => t.type === "discovered" && !e.has(t.discoveredId)).sort(t), i = X.showHidden ? X.devices.filter((t) => t.type === "discovered" && e.has(t.discoveredId)).sort(t) : [];
|
|
1497
1496
|
return [
|
|
1498
1497
|
...n,
|
|
1499
1498
|
...r,
|
|
1500
1499
|
...i
|
|
1501
1500
|
];
|
|
1502
1501
|
});
|
|
1503
|
-
return
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
},
|
|
1502
|
+
return pe(() => {
|
|
1503
|
+
$--, !($ > 0) && ($ = 0, In = setTimeout(() => {
|
|
1504
|
+
$ <= 0 && (Vn(), In = null);
|
|
1505
|
+
}, Pn));
|
|
1507
1506
|
}), {
|
|
1508
|
-
state: f(
|
|
1509
|
-
isConnected: v(() =>
|
|
1510
|
-
isLoading: v(() =>
|
|
1511
|
-
devices: v(() =>
|
|
1512
|
-
isScanning: v(() =>
|
|
1513
|
-
hiddenDevices: v(() =>
|
|
1514
|
-
showHidden: v(() =>
|
|
1515
|
-
error: v(() =>
|
|
1507
|
+
state: f(X),
|
|
1508
|
+
isConnected: v(() => Z?.connected.value ?? !1),
|
|
1509
|
+
isLoading: v(() => X.isLoading),
|
|
1510
|
+
devices: v(() => X.devices),
|
|
1511
|
+
isScanning: v(() => X.isScanning),
|
|
1512
|
+
hiddenDevices: v(() => X.hiddenDevices),
|
|
1513
|
+
showHidden: v(() => X.showHidden),
|
|
1514
|
+
error: v(() => X.error),
|
|
1516
1515
|
sortedDevices: d,
|
|
1517
1516
|
connect: e,
|
|
1518
1517
|
disconnect: t,
|
|
@@ -1555,15 +1554,15 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1555
1554
|
}, or = { class: "flex items-center justify-center" }, sr = { class: "flex items-center justify-center" }, cr = {
|
|
1556
1555
|
key: 1,
|
|
1557
1556
|
class: "flex flex-col items-center justify-center py-6 gap-2"
|
|
1558
|
-
}, lr = { class: "text-muted text-sm" }, ur = { class: "flex flex-wrap items-center gap-2 mt-4" }, dr = /*#__PURE__*/
|
|
1557
|
+
}, lr = { class: "text-muted text-sm" }, ur = { class: "flex flex-wrap items-center gap-2 mt-4" }, dr = /*#__PURE__*/ fe(/* @__PURE__ */ O({
|
|
1559
1558
|
__name: "Cameras",
|
|
1560
1559
|
setup(e) {
|
|
1561
|
-
let { t } =
|
|
1560
|
+
let { t } = K(), r = H(), i = B(), a = ae(), { smBreakpoint: c } = ne(), l = Hn(), d = {
|
|
1562
1561
|
bodyRow: { class: "text-sm text-secondary" },
|
|
1563
1562
|
column: { columnTitle: { class: "text-sm" } },
|
|
1564
1563
|
datatable: { class: "z-0" }
|
|
1565
|
-
}, f = v(() =>
|
|
1566
|
-
function
|
|
1564
|
+
}, f = v(() => G(void 0, "admin")), h = v(() => l.sortedDevices.value), g = v(() => h.value.filter((e) => e.type === "camera")), b = v(() => h.value.filter((e) => e.type === "discovered")), w = v(() => l.isLoading.value), D = v(() => l.isScanning.value), O = v(() => l.hiddenDevices.value), k = v(() => l.showHidden.value), j = v(() => O.value.length);
|
|
1565
|
+
function N(e) {
|
|
1567
1566
|
switch (e) {
|
|
1568
1567
|
case "added": return "green";
|
|
1569
1568
|
case "discovered": return "orange";
|
|
@@ -1572,7 +1571,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1572
1571
|
default: return "gray";
|
|
1573
1572
|
}
|
|
1574
1573
|
}
|
|
1575
|
-
function
|
|
1574
|
+
function P(e) {
|
|
1576
1575
|
switch (e) {
|
|
1577
1576
|
case "added": return t("views.devices.status_added");
|
|
1578
1577
|
case "discovered": return t("views.devices.status_discovered");
|
|
@@ -1581,11 +1580,11 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1581
1580
|
default: return t("views.devices.status_unknown");
|
|
1582
1581
|
}
|
|
1583
1582
|
}
|
|
1584
|
-
function
|
|
1583
|
+
function F(e) {
|
|
1585
1584
|
return l.isHidden(e);
|
|
1586
1585
|
}
|
|
1587
|
-
async function
|
|
1588
|
-
if (!
|
|
1586
|
+
async function I(e) {
|
|
1587
|
+
if (!F(e)) {
|
|
1589
1588
|
if (e.type === "camera") {
|
|
1590
1589
|
a.open({ cameraName: e.name });
|
|
1591
1590
|
return;
|
|
@@ -1603,7 +1602,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1603
1602
|
});
|
|
1604
1603
|
return;
|
|
1605
1604
|
}
|
|
1606
|
-
i.openComponentDialog(
|
|
1605
|
+
i.openComponentDialog(Nn, { data: {
|
|
1607
1606
|
title: `${t("views.devices.connect")}: ${e.name}`,
|
|
1608
1607
|
confirmText: t("views.devices.connect"),
|
|
1609
1608
|
contentProps: {
|
|
@@ -1617,7 +1616,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1617
1616
|
},
|
|
1618
1617
|
schema: n.schema ?? [],
|
|
1619
1618
|
onConnect: async (t) => {
|
|
1620
|
-
|
|
1619
|
+
L(await l.prepareDevice(e.discoveredId, t), e.discoveredId);
|
|
1621
1620
|
}
|
|
1622
1621
|
}
|
|
1623
1622
|
} });
|
|
@@ -1632,8 +1631,8 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1632
1631
|
}
|
|
1633
1632
|
}
|
|
1634
1633
|
}
|
|
1635
|
-
function
|
|
1636
|
-
i.openComponentDialog(
|
|
1634
|
+
function L(e, n) {
|
|
1635
|
+
i.openComponentDialog(Dn, { data: {
|
|
1637
1636
|
title: t("views.devices.confirm_title"),
|
|
1638
1637
|
confirmText: t("views.devices.confirm"),
|
|
1639
1638
|
fullscreen: !0,
|
|
@@ -1650,7 +1649,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1650
1649
|
}
|
|
1651
1650
|
} });
|
|
1652
1651
|
}
|
|
1653
|
-
async function
|
|
1652
|
+
async function R() {
|
|
1654
1653
|
try {
|
|
1655
1654
|
let e = await l.forceRescan();
|
|
1656
1655
|
e.success ? r.add({
|
|
@@ -1673,14 +1672,14 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1673
1672
|
});
|
|
1674
1673
|
}
|
|
1675
1674
|
}
|
|
1676
|
-
function
|
|
1677
|
-
i.openComponentDialog(
|
|
1675
|
+
function te() {
|
|
1676
|
+
i.openComponentDialog(Sn, { data: {
|
|
1678
1677
|
title: t("components.dialog.components.new_camera.add_camera"),
|
|
1679
1678
|
fullscreen: !0,
|
|
1680
1679
|
contentProps: {}
|
|
1681
1680
|
} });
|
|
1682
1681
|
}
|
|
1683
|
-
async function
|
|
1682
|
+
async function re(e, n) {
|
|
1684
1683
|
e.stopPropagation();
|
|
1685
1684
|
try {
|
|
1686
1685
|
let e = await l.hideDevice(n);
|
|
@@ -1728,18 +1727,18 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1728
1727
|
});
|
|
1729
1728
|
}
|
|
1730
1729
|
}
|
|
1731
|
-
function
|
|
1730
|
+
function V() {
|
|
1732
1731
|
l.toggleShowHidden();
|
|
1733
1732
|
}
|
|
1734
|
-
function
|
|
1735
|
-
return
|
|
1733
|
+
function U(e) {
|
|
1734
|
+
return F(e) ? "opacity-50 cursor-not-allowed" : "";
|
|
1736
1735
|
}
|
|
1737
1736
|
return M(() => {
|
|
1738
1737
|
f.value && l.connect();
|
|
1739
1738
|
}), n(() => {
|
|
1740
1739
|
f.value && l.unsubscribe();
|
|
1741
1740
|
}), (e, t) => {
|
|
1742
|
-
let n =
|
|
1741
|
+
let n = Pe, r = me, i = ie, a = se, l = q, v = xe, O = ke, M = Oe, L = Ae, ne = ue, ae = Le, B = oe, H = ee;
|
|
1743
1742
|
return o(), x("div", Un, [
|
|
1744
1743
|
_(c) ? m("", !0) : (o(), x("h1", Wn, s(e.$t(`views.${String(e.$route.name).toLowerCase()}.title`)), 1)),
|
|
1745
1744
|
_(f) ? (o(), x(C, { key: 2 }, [
|
|
@@ -1755,16 +1754,16 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1755
1754
|
severity: "secondary",
|
|
1756
1755
|
label: e.$t("views.devices.rescan"),
|
|
1757
1756
|
loading: _(D),
|
|
1758
|
-
onClick:
|
|
1757
|
+
onClick: R
|
|
1759
1758
|
}, null, 8, ["label", "loading"])
|
|
1760
1759
|
])) : m("", !0),
|
|
1761
1760
|
!_(w) && _(g).length ? (o(), x("div", Qn, [T("span", $n, s(e.$t("views.devices.status_adopted_cameras")), 1), A(r, { class: "cui-card" }, {
|
|
1762
|
-
content: y(() => [A(
|
|
1761
|
+
content: y(() => [A(L, {
|
|
1763
1762
|
value: _(g),
|
|
1764
1763
|
"striped-rows": "",
|
|
1765
1764
|
pt: d,
|
|
1766
1765
|
class: "w-full",
|
|
1767
|
-
onRowClick: t[0] ||= (e) =>
|
|
1766
|
+
onRowClick: t[0] ||= (e) => I(e.data)
|
|
1768
1767
|
}, {
|
|
1769
1768
|
default: y(() => [
|
|
1770
1769
|
A(O, {
|
|
@@ -1772,7 +1771,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1772
1771
|
"header-class": "p-2 pl-4 w-5 max-w-5",
|
|
1773
1772
|
class: "p-2 pl-4 w-5 max-w-5"
|
|
1774
1773
|
}, {
|
|
1775
|
-
body: y(({ data: e }) => [T("div", er, [E(A(v, { style: S({ background:
|
|
1774
|
+
body: y(({ data: e }) => [T("div", er, [E(A(v, { style: S({ background: N(e.status) }) }, null, 8, ["style"]), [[H, { value: P(e.status) }]])])]),
|
|
1776
1775
|
_: 1
|
|
1777
1776
|
}),
|
|
1778
1777
|
A(O, {
|
|
@@ -1822,12 +1821,12 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1822
1821
|
key: 3,
|
|
1823
1822
|
class: u(["flex min-h-0 flex-col", { "mt-6": _(g).length }])
|
|
1824
1823
|
}, [T("span", ir, s(e.$t("views.devices.status_discovered")), 1), A(r, { class: "cui-card" }, {
|
|
1825
|
-
content: y(() => [_(b).length ? (o(), x("div", ar, [A(
|
|
1824
|
+
content: y(() => [_(b).length ? (o(), x("div", ar, [A(L, {
|
|
1826
1825
|
value: _(b),
|
|
1827
1826
|
"striped-rows": "",
|
|
1828
1827
|
pt: d,
|
|
1829
1828
|
class: "w-full",
|
|
1830
|
-
onRowClick: t[1] ||= (e) =>
|
|
1829
|
+
onRowClick: t[1] ||= (e) => I(e.data)
|
|
1831
1830
|
}, {
|
|
1832
1831
|
default: y(() => [
|
|
1833
1832
|
A(O, {
|
|
@@ -1835,7 +1834,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1835
1834
|
"header-class": "p-2 pl-4 w-5 max-w-5",
|
|
1836
1835
|
class: "p-2 pl-4 w-5 max-w-5"
|
|
1837
1836
|
}, {
|
|
1838
|
-
body: y(({ data: e }) => [T("div", or, [E(A(v, { style: S({ background:
|
|
1837
|
+
body: y(({ data: e }) => [T("div", or, [E(A(v, { style: S({ background: N(e.status) }) }, null, 8, ["style"]), [[H, { value: P(e.status) }]])])]),
|
|
1839
1838
|
_: 1
|
|
1840
1839
|
}),
|
|
1841
1840
|
A(O, {
|
|
@@ -1844,7 +1843,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1844
1843
|
"header-class": "p-2",
|
|
1845
1844
|
class: "p-2 w-full min-w-[200px] max-w-0"
|
|
1846
1845
|
}, {
|
|
1847
|
-
body: y(({ data: t }) => [T("div", { class: u(["font-bold text-color truncate",
|
|
1846
|
+
body: y(({ data: t }) => [T("div", { class: u(["font-bold text-color truncate", U(t)]) }, s(t.name), 3), T("div", { class: u(["text-xs text-muted truncate", U(t)]) }, s(t.manufacturer || e.$t("views.devices.unknown")) + " · " + s(t.model || e.$t("views.devices.unknown")), 3)]),
|
|
1848
1847
|
_: 1
|
|
1849
1848
|
}, 8, ["header"]),
|
|
1850
1849
|
A(O, {
|
|
@@ -1855,7 +1854,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1855
1854
|
}, {
|
|
1856
1855
|
body: y(({ data: e }) => [e.address ? (o(), x("span", {
|
|
1857
1856
|
key: 0,
|
|
1858
|
-
class: u(["text-xs text-muted whitespace-nowrap",
|
|
1857
|
+
class: u(["text-xs text-muted whitespace-nowrap", U(e)])
|
|
1859
1858
|
}, s(e.address), 3)) : m("", !0)]),
|
|
1860
1859
|
_: 1
|
|
1861
1860
|
}, 8, ["header"]),
|
|
@@ -1867,7 +1866,7 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1867
1866
|
}, {
|
|
1868
1867
|
body: y(({ data: e }) => [A(M, {
|
|
1869
1868
|
label: e.provider,
|
|
1870
|
-
class: u(["text-xs whitespace-nowrap",
|
|
1869
|
+
class: u(["text-xs whitespace-nowrap", U(e)])
|
|
1871
1870
|
}, null, 8, ["label", "class"])]),
|
|
1872
1871
|
_: 1
|
|
1873
1872
|
}, 8, ["header"]),
|
|
@@ -1876,14 +1875,14 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1876
1875
|
"header-class": "p-2 pr-4 w-12",
|
|
1877
1876
|
class: "p-2 pr-4 w-12"
|
|
1878
1877
|
}, {
|
|
1879
|
-
body: y(({ data: t }) => [T("div", sr, [
|
|
1878
|
+
body: y(({ data: t }) => [T("div", sr, [F(t) ? E((o(), p(l, {
|
|
1880
1879
|
key: 1,
|
|
1881
1880
|
text: "",
|
|
1882
1881
|
rounded: "",
|
|
1883
1882
|
class: "cui-icon-md",
|
|
1884
1883
|
onClick: (e) => z(e, t)
|
|
1885
1884
|
}, {
|
|
1886
|
-
icon: y(() => [A(_(
|
|
1885
|
+
icon: y(() => [A(_(Re), {
|
|
1887
1886
|
width: "100%",
|
|
1888
1887
|
height: "100%",
|
|
1889
1888
|
class: "text-muted"
|
|
@@ -1900,9 +1899,9 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1900
1899
|
text: "",
|
|
1901
1900
|
rounded: "",
|
|
1902
1901
|
class: "cui-icon-md",
|
|
1903
|
-
onClick: (e) =>
|
|
1902
|
+
onClick: (e) => re(e, t)
|
|
1904
1903
|
}, {
|
|
1905
|
-
icon: y(() => [A(_(
|
|
1904
|
+
icon: y(() => [A(_(ze), {
|
|
1906
1905
|
width: "100%",
|
|
1907
1906
|
height: "100%",
|
|
1908
1907
|
class: "text-muted"
|
|
@@ -1918,12 +1917,12 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1918
1917
|
})
|
|
1919
1918
|
]),
|
|
1920
1919
|
_: 1
|
|
1921
|
-
}, 8, ["value"])])) : (o(), x("div", cr, [_(D) ? (o(), p(
|
|
1920
|
+
}, 8, ["value"])])) : (o(), x("div", cr, [_(D) ? (o(), p(ne, {
|
|
1922
1921
|
key: 0,
|
|
1923
1922
|
width: "24px",
|
|
1924
1923
|
height: "24px",
|
|
1925
1924
|
class: "text-muted"
|
|
1926
|
-
})) : (o(), p(
|
|
1925
|
+
})) : (o(), p(ae, {
|
|
1927
1926
|
key: 1,
|
|
1928
1927
|
width: "32px",
|
|
1929
1928
|
height: "32px",
|
|
@@ -1935,14 +1934,14 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1935
1934
|
severity: "secondary",
|
|
1936
1935
|
class: "cui-button-medium",
|
|
1937
1936
|
label: _(k) ? e.$t("views.devices.hide_hidden") : `${e.$t("views.devices.show_hidden")} (${_(j)})`,
|
|
1938
|
-
onClick:
|
|
1937
|
+
onClick: V
|
|
1939
1938
|
}, null, 8, ["label"])) : m("", !0),
|
|
1940
1939
|
A(l, {
|
|
1941
1940
|
severity: "secondary",
|
|
1942
1941
|
class: "cui-button-medium",
|
|
1943
1942
|
label: e.$t("views.devices.rescan"),
|
|
1944
1943
|
loading: _(D),
|
|
1945
|
-
onClick:
|
|
1944
|
+
onClick: R
|
|
1946
1945
|
}, null, 8, ["label", "loading"])
|
|
1947
1946
|
])]),
|
|
1948
1947
|
_: 1
|
|
@@ -1951,16 +1950,16 @@ var Un = { class: "flex flex-col" }, Wn = {
|
|
|
1951
1950
|
content: y(() => [A(n)]),
|
|
1952
1951
|
_: 1
|
|
1953
1952
|
})])),
|
|
1954
|
-
("hasPermission" in e ? e.hasPermission : _(
|
|
1953
|
+
("hasPermission" in e ? e.hasPermission : _(G))(void 0, "admin") ? (o(), p(B, {
|
|
1955
1954
|
key: 3,
|
|
1956
1955
|
"tooltip-props": { value: e.$t("views.cameras.add_camera") },
|
|
1957
1956
|
"button-props": { class: "text-white" },
|
|
1958
|
-
icon: _(
|
|
1957
|
+
icon: _(Ie),
|
|
1959
1958
|
"icon-props": {
|
|
1960
1959
|
width: "30px",
|
|
1961
1960
|
height: "30px"
|
|
1962
1961
|
},
|
|
1963
|
-
onClick:
|
|
1962
|
+
onClick: te
|
|
1964
1963
|
}, null, 8, ["tooltip-props", "icon"])) : m("", !0)
|
|
1965
1964
|
]);
|
|
1966
1965
|
};
|