From 596a72471409184d958aea73a9d42a137fc7b231 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Mon, 20 Jan 2025 18:56:59 -0800 Subject: [PATCH] fix: Add additional troubleshooting pointers for stream load errors (#1844) [skip ci] --- docs/troubleshooting.md | 67 +++++++++++++++++++++++++-------- src/components/live/provider.ts | 29 ++++++++++++-- src/components/message.ts | 15 +++++++- src/const.ts | 2 + src/localize/languages/en.json | 1 + src/scss/live-provider.scss | 1 + src/scss/message.scss | 33 ++++++++++++---- src/scss/themes/base.scss | 11 ++++++ 8 files changed, 130 insertions(+), 29 deletions(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 58e7f4a1..8f3ed8d8 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -1,5 +1,57 @@ # Troubleshooting +## Highlighted Issues + +### Stream does not load + +Stream not loading? Permanent "loading circle"? + +A stream not loading is a relatively common error, but can be caused by any +number of issues (e.g. installation problems, networking problems, video/codec +problems, a Home Assistant bug or card bug). + +During the stream load, the card will show a "loading circle" icon and, for +cameras with a `camera_entity` configured, will show images refreshing once per +second until the stream has fully loaded (unless `live.show_image_during_load` +is set to false). + +Debugging broken streams: + +1. If you're using the default `auto` live provider, or explicitly setting the + `ha` live provider, try opening the `camera_entity` in Home Assistant and + verifying whether the stream loads there. You can press the `e` key on any + Home Assistant dashboard, choose the relevant entity, and see if the stream + loads. If it does not, you have a upstream installation issue with your + camera / the integration for the camera, and need to resolve that first. + Your issue is not related to the card itself. +1. Check whether any URLs specified in your card configuration are accessible + _from the network of the browser_. +1. Check whether or not there are helpful clues shown on your Javascript + console (`F12` in many browsers) that might indicate the source of the + issue. +1. Check you are using the latest version of all relevant camera integrations + (e.g. + [Frigate](https://github.com/blakeblackshear/frigate-hass-integration)). +1. If you're using a Frigate camera and are requesting a `webrtc` stream, + ensure [you have configured Frigate + accordingly](https://docs.frigate.video/configuration/live/#webrtc-extra-configuration). +1. Search for your symptoms on the [card issues + page](https://github.com/dermotduffy/frigate-hass-card/issues) and see if + you find any prior relevant discussions. + +If you're happy with just using an image stream but want the small circle to go +away, use the [`image live provider`](./configuration/cameras/live-provider.md?id=image) . + +### Unknown Command + +`Camera initialization failed: Unknown command` + +Your Frigate integration may not be up to date. Check [the latest Frigate +Integration +releases](https://github.com/blakeblackshear/frigate-hass-integration/releases/tag/v5.7.0). + +## Other Issues + ### 2-way audio doesn't work There are many requirements for 2-way audio to work. See [Using 2-way @@ -50,12 +102,6 @@ stills are used during initial Frigate card load of the `live` view if the show the default media loading controls (e.g. a spinner or empty video player) instead of the blank white image. -### `Camera initialization failed: Unknown command` - -This may be a sign that your Frigate integration is not up to date. Check [the -latest Frigate Integration -releases](https://github.com/blakeblackshear/frigate-hass-integration/releases/tag/v5.7.0). - ### Casting to Chromecast broken This could be for any number of reasons. Chromecast devices can be quite picky @@ -195,15 +241,6 @@ status_bar: style: none ``` -### Watermark shown on livestream - -If the `live.show_image_during_load` option is enabled (the default), a -temporary image from Home Assistant is rendered and refreshed every `1s` while -the full stream is loading. When this temporary image is being shown, a small -circular icon is rendered on the top-right of the livestream to indicate to the -user that this is not the true stream. If the icon persists, it means your -underlying stream is not actually loading and may be misconfigured / broken. - ### `webrtc_card` unloads in the background [AlexxIT's WebRTC Card](https://github.com/AlexxIT/WebRTC) which is embedded by diff --git a/src/components/live/provider.ts b/src/components/live/provider.ts index 22554874..2eeb223c 100644 --- a/src/components/live/provider.ts +++ b/src/components/live/provider.ts @@ -21,6 +21,7 @@ import { LiveConfig, LiveProvider, } from '../../config/types.js'; +import { STREAM_TROUBLESHOOTING_URL } from '../../const.js'; import { localize } from '../../localize/localize.js'; import liveProviderStyle from '../../scss/live-provider.scss'; import { ExtendedHomeAssistant, FrigateCardMediaPlayer } from '../../types.js'; @@ -76,6 +77,9 @@ export class FrigateCardLiveProvider @state() protected _hasProviderError = false; + @state() + protected _showStreamTroubleshooting = false; + protected _refProvider: Ref = createRef(); // A note on dynamic imports: @@ -168,9 +172,11 @@ export class FrigateCardLiveProvider */ protected _shouldShowImageDuringLoading(): boolean { return ( + !this._isVideoMediaLoaded && !!this.cameraConfig?.camera_entity && !!this.hass && !!this.liveConfig?.show_image_during_load && + !this._showStreamTroubleshooting && // Do not continue to show image during loading if an error has occurred. !this._hasProviderError ); @@ -182,6 +188,7 @@ export class FrigateCardLiveProvider protected _videoMediaShowHandler(): void { this._isVideoMediaLoaded = true; + this._showStreamTroubleshooting = false; } protected _providerErrorHandler(): void { @@ -267,8 +274,8 @@ export class FrigateCardLiveProvider this.ariaLabel = this.label; const provider = this._getResolvedProvider(); - const showImageDuringLoading = - !this._isVideoMediaLoaded && this._shouldShowImageDuringLoading(); + const showImageDuringLoading = this._shouldShowImageDuringLoading(); + const showLoadingIcon = !this._isVideoMediaLoaded; const providerClasses = { hidden: showImageDuringLoading, }; @@ -386,12 +393,26 @@ export class FrigateCardLiveProvider ` : html``} `)} - ${showImageDuringLoading && !this._isVideoMediaLoaded + ${showLoadingIcon ? html` { + this._showStreamTroubleshooting = !this._showStreamTroubleshooting; + }} >` - : ''} `; + : ''} + ${this._showStreamTroubleshooting + ? renderMessage( + { + type: 'error', + icon: 'mdi:camera-off', + message: localize('error.stream_not_loading'), + troubleshootingURL: STREAM_TROUBLESHOOTING_URL, + }, + { overlay: true }, + ) + : ''}`; } static get styles(): CSSResultGroup { diff --git a/src/components/message.ts b/src/components/message.ts index 71510026..b8ac1904 100644 --- a/src/components/message.ts +++ b/src/components/message.ts @@ -7,14 +7,25 @@ import messageStyle from '../scss/message.scss'; import { Message } from '../types.js'; import './icon.js'; -export function renderMessage(message: Message | null): TemplateResult { - return html` `; +export function renderMessage( + message: Message | null, + renderOptions?: { + overlay?: boolean; + }, +): TemplateResult { + return html` `; } @customElement('frigate-card-message') export class FrigateCardMessage extends LitElement { @property({ attribute: false }) public message?: Message; + @property({ attribute: true, type: Boolean }) + public overlay = false; + private _controller = new MessageController(); protected render(): TemplateResult | void { diff --git a/src/const.ts b/src/const.ts index a5953f3c..321086b5 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1,5 +1,7 @@ export const REPO_URL = 'https://github.com/dermotduffy/frigate-hass-card' as const; export const TROUBLESHOOTING_URL = `https://card.camera/#/troubleshooting` as const; +export const STREAM_TROUBLESHOOTING_URL = + `${TROUBLESHOOTING_URL}?id=stream-does-not-load` as const; export const CONF_AUTOMATIONS = 'automations' as const; diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json index 3c74bed2..5766fbf3 100644 --- a/src/localize/languages/en.json +++ b/src/localize/languages/en.json @@ -646,6 +646,7 @@ "no_supported_camera": "The selected camera does not support this view", "no_supported_cameras": "No cameras support this view", "reconnecting": "Reconnecting", + "stream_not_loading": "The video stream has not yet loaded. This is could for any number of reasons. If configured (and by default), there will be an image refreshing every second until the stream loads correctly", "too_many_automations": "Too many nested automation calls, please check your configuration for loops", "troubleshooting": "Check troubleshooting", "unknown": "Unknown error", diff --git a/src/scss/live-provider.scss b/src/scss/live-provider.scss index 24d385bb..8fe39c01 100644 --- a/src/scss/live-provider.scss +++ b/src/scss/live-provider.scss @@ -16,4 +16,5 @@ frigate-card-icon { top: 10px; right: 10px; color: var(--primary-color); + cursor: help; } diff --git a/src/scss/message.scss b/src/scss/message.scss index 6d82fe86..8e7d5411 100644 --- a/src/scss/message.scss +++ b/src/scss/message.scss @@ -1,10 +1,6 @@ @use 'dotdotdot.scss'; :host { - display: block; - height: 100%; - width: 100%; - display: flex; flex-direction: column; justify-content: center; @@ -13,8 +9,22 @@ user-select: text; // Safari only has prefixed support. -webkit-user-select: text; +} + +:host(:not([overlay])) { + height: 100%; + width: 100%; - color: var(--primary-text-color); + background: var(--frigate-card-message-background); + color: var(--frigate-card-message-color); +} + +:host([overlay]) { + position: absolute; + inset: 5%; + + background: var(--frigate-card-message-overlay-background); + color: var(--frigate-card-message-overlay-color); } div.wrapper { @@ -50,14 +60,21 @@ div.message div.icon { flex-direction: column; } -.message a { - color: var(--primary-text-color, white); +a { word-break: break-word; } +:host(:not([overlay])) a { + color: var(--frigate-card-message-color); +} + +:host([overlay]) a { + color: var(--frigate-card-message-overlay-color); +} + .message pre { margin-top: 20px; overflow-x: auto; - border: 1px dotted var(--divider-color); + border: 1px dotted var(--frigate-card-divider-color); padding: 1em; } diff --git a/src/scss/themes/base.scss b/src/scss/themes/base.scss index c334a170..1f041179 100644 --- a/src/scss/themes/base.scss +++ b/src/scss/themes/base.scss @@ -133,4 +133,15 @@ --frigate-card-control-background-transparent ); --frigate-card-loading-foreground-color: var(--frigate-card-control-foreground); + + /********* + * Message + *********/ + --frigate-card-message-color: var(--frigate-card-text-color); + --frigate-card-message-background: var(--frigate-card-background); + + --frigate-card-message-overlay-background: var( + --frigate-card-control-background-transparent + ); + --frigate-card-message-overlay-color: var(--frigate-card-control-foreground); }