feat: Rework casting profile and documentation (#1602)
* feat: Rework casting profile and documentation * Apply suggestions from code review Co-authored-by: Dermot Duffy <dermot.duffy@gmail.com> * Some other minor details * Update docs/usage/casting.md Co-authored-by: Dermot Duffy <dermot.duffy@gmail.com> * Improve const.ts * Some other small changes * Update docs/usage/casting.md Co-authored-by: Dermot Duffy <dermot.duffy@gmail.com> --------- Co-authored-by: Dermot Duffy <dermot.duffy@gmail.com>
This commit is contained in:
co-authored by
Dermot Duffy
parent
eccf50252f
commit
9098eb3483
+110
-46
@@ -1,18 +1,115 @@
|
|||||||
# Casting the Card
|
# Casting
|
||||||
|
|
||||||
This card can be (Chrome) casted to a device (such as a [Nest
|
This card allows casting a camera stream to a Google Cast device. You can enable the cast button with:
|
||||||
Hub](https://store.google.com/us/product/nest_hub_2nd_gen)) through the use of
|
|
||||||
[Home Assistant Cast](https://cast.home-assistant.io/).
|
|
||||||
|
|
||||||
## Instructions
|
```yaml
|
||||||
|
type: custom:frigate-card
|
||||||
|
cameras:
|
||||||
|
- camera_entity: camera.office
|
||||||
|
live_provider: go2rtc
|
||||||
|
menu:
|
||||||
|
media_player:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
- Visit [Home Assistant Cast](https://cast.home-assistant.io/) and click `Start Casting`
|
Clicking this button will allow you to choose a Google Cast device to cast the camera stream to, or the clip that is currently playing.
|
||||||
- Enter your Home Assistant URL, and authorize your account.
|
|
||||||
- Click `Start Casting` and choose the device to cast to from the browser menu.
|
|
||||||
- Choose which view/dashboard to display.
|
|
||||||
- If successful, the view will be cast to the device.
|
|
||||||
|
|
||||||
## Limitations
|
There are two different casting methods for cameras: `standard` and `dashboard` (see below).
|
||||||
|
|
||||||
|
## Standard Casting
|
||||||
|
|
||||||
|
This is the default casting method.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
type: custom:frigate-card
|
||||||
|
cameras:
|
||||||
|
- camera_entity: camera.office
|
||||||
|
live_provider: go2rtc
|
||||||
|
cast:
|
||||||
|
method: standard
|
||||||
|
menu:
|
||||||
|
media_player:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
This will send the camera stream to the Google Cast device through the use of the [`media_player.play_media` Home Assistant action](https://www.home-assistant.io/integrations/media_source/#playing-media-from-a-media-source).
|
||||||
|
|
||||||
|
The main disadvantage of this method is that the stream will be played through HLS which has a **delay of around 10 seconds**, making it sub-optimal for live monitoring.
|
||||||
|
|
||||||
|
## Dashboard Casting
|
||||||
|
|
||||||
|
This method is powered by [Home Assistant Cast](https://cast.home-assistant.io) and requires additional configuration, but allows **low latency streaming** with go2rtc.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
type: custom:frigate-card
|
||||||
|
cameras:
|
||||||
|
- camera_entity: camera.office
|
||||||
|
live_provider: go2rtc
|
||||||
|
cast:
|
||||||
|
method: dashboard
|
||||||
|
dashboard:
|
||||||
|
dashboard_path: dashboard-cast
|
||||||
|
view_path: office
|
||||||
|
```
|
||||||
|
|
||||||
|
When the cast button is clicked, the card will perform the following Home Assistant action:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
action: cast.show_lovelace_view
|
||||||
|
data:
|
||||||
|
entity_id: media_player.kitchen
|
||||||
|
dashboard_path: dashboard-cast
|
||||||
|
view_path: office
|
||||||
|
```
|
||||||
|
|
||||||
|
Which in turn will cast the specified Home Assistant dashboard (and view) to the Google Cast device.
|
||||||
|
|
||||||
|
For the example above to work, a dashboard with `dashboard-cast` URL must exist:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Within that dashboard, create an `office` view and finally within that view you can place the Frigate card configured for that camera for a proper full-screen casting experience:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
views:
|
||||||
|
- title: Office
|
||||||
|
type: panel
|
||||||
|
path: office
|
||||||
|
cards:
|
||||||
|
- type: custom:frigate-card
|
||||||
|
cameras:
|
||||||
|
- camera_entity: camera.office
|
||||||
|
live_provider: go2rtc
|
||||||
|
profiles:
|
||||||
|
- low-performance
|
||||||
|
- casting
|
||||||
|
```
|
||||||
|
|
||||||
|
The `casting` profile pre-configures the card to be casted to a 16:9 screen (such as a TV), including hiding all interactive elements and the menu. The `low-performance` profile is also recommended, as normally casting devices have limited hardware capabilities.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
When casting to a Google Nest Hub, the following configuration can be used:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
type: custom:frigate-card
|
||||||
|
cameras:
|
||||||
|
- camera_entity: camera.office
|
||||||
|
live_provider: go2rtc
|
||||||
|
profiles:
|
||||||
|
- low-performance
|
||||||
|
- casting
|
||||||
|
menu:
|
||||||
|
style: hidden
|
||||||
|
dimensions:
|
||||||
|
aspect_ratio: 1024:600
|
||||||
|
```
|
||||||
|
|
||||||
|
This restores the menu and sets the aspect ratio to 1024:600, which is the resolution of the Nest Hub.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
Casting Home Assistant dashboards comes with a number of caveats:
|
Casting Home Assistant dashboards comes with a number of caveats:
|
||||||
|
|
||||||
@@ -20,38 +117,5 @@ Casting Home Assistant dashboards comes with a number of caveats:
|
|||||||
([source](https://cast.home-assistant.io/faq.html)). This means clips playing
|
([source](https://cast.home-assistant.io/faq.html)). This means clips playing
|
||||||
and the `ha` live provider can not work. Other live providers such as `jsmpeg`
|
and the `ha` live provider can not work. Other live providers such as `jsmpeg`
|
||||||
and `webrtc-card` function correctly.
|
and `webrtc-card` function correctly.
|
||||||
- The Javascript fullscreen API does not work (so the fullscreen button does not
|
- The Javascript fullscreen API does not work, so the fullscreen button does not
|
||||||
work, but see below for an equivalent).
|
work (use a `panel` view instead).
|
||||||
|
|
||||||
## The `casting` profile
|
|
||||||
|
|
||||||
The optional [casting profile](../configuration/profiles.md?id=casting) provides
|
|
||||||
some defaults to improve your casting experience. Use it like:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
profiles:
|
|
||||||
- casting
|
|
||||||
```
|
|
||||||
|
|
||||||
## Recommended configuration for Nest Hub
|
|
||||||
|
|
||||||
Using a `panel` dashboard with the following base configuration will result in
|
|
||||||
the card consuming the entire device screen:
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
type: custom:frigate-card
|
|
||||||
cameras:
|
|
||||||
- camera_entity: camera.office
|
|
||||||
live_provider: go2rtc
|
|
||||||
dimensions:
|
|
||||||
aspect_ratio: 1024:600
|
|
||||||
aspect_ratio_mode: static
|
|
||||||
profile:
|
|
||||||
- casting
|
|
||||||
```
|
|
||||||
|
|
||||||
### Result
|
|
||||||
|
|
||||||

|
|
||||||
|
|||||||
@@ -1,18 +1,37 @@
|
|||||||
import {
|
import {
|
||||||
CONF_CAMERAS_GLOBAL_IMAGE_REFRESH_SECONDS,
|
CONF_CAMERAS_GLOBAL_IMAGE_REFRESH_SECONDS,
|
||||||
CONF_DIMENSIONS_ASPECT_RATIO,
|
CONF_DIMENSIONS_ASPECT_RATIO,
|
||||||
|
CONF_DIMENSIONS_ASPECT_RATIO_MODE,
|
||||||
CONF_LIVE_AUTO_UNMUTE,
|
CONF_LIVE_AUTO_UNMUTE,
|
||||||
CONF_LIVE_CONTROLS_BUILTIN,
|
CONF_LIVE_CONTROLS_BUILTIN,
|
||||||
CONF_LIVE_SHOW_IMAGE_DURING_LOAD,
|
CONF_LIVE_SHOW_IMAGE_DURING_LOAD,
|
||||||
CONF_MEDIA_VIEWER_CONTROLS_BUILTIN,
|
CONF_MEDIA_VIEWER_CONTROLS_BUILTIN,
|
||||||
|
CONF_MENU_BUTTONS_FULLSCREEN,
|
||||||
|
CONF_MENU_BUTTONS_MEDIA_PLAYER,
|
||||||
|
CONF_MENU_BUTTONS_MUTE,
|
||||||
|
CONF_MENU_BUTTONS_PLAY,
|
||||||
|
CONF_MENU_STYLE,
|
||||||
} from '../../const.js';
|
} from '../../const.js';
|
||||||
|
|
||||||
export const CASTING_PROFILE = {
|
export const CASTING_PROFILE = {
|
||||||
[CONF_LIVE_AUTO_UNMUTE]: ['selected', 'visible'],
|
|
||||||
[CONF_DIMENSIONS_ASPECT_RATIO]: '16:9',
|
|
||||||
[CONF_LIVE_CONTROLS_BUILTIN]: false,
|
[CONF_LIVE_CONTROLS_BUILTIN]: false,
|
||||||
[CONF_MEDIA_VIEWER_CONTROLS_BUILTIN]: false,
|
[CONF_MEDIA_VIEWER_CONTROLS_BUILTIN]: false,
|
||||||
|
|
||||||
|
// TVs are generally not touch-enabled, so we don't want to show the menu
|
||||||
|
[CONF_MENU_STYLE]: 'none',
|
||||||
|
|
||||||
|
// But in case the user enables the menu, let's make sure to enable the
|
||||||
|
// buttons that make sense and disable the ones that don't
|
||||||
|
[`${CONF_MENU_BUTTONS_PLAY}.enabled`]: true,
|
||||||
|
[`${CONF_MENU_BUTTONS_MUTE}.enabled`]: true,
|
||||||
|
[`${CONF_MENU_BUTTONS_FULLSCREEN}.enabled`]: false,
|
||||||
|
[`${CONF_MENU_BUTTONS_MEDIA_PLAYER}.enabled`]: false,
|
||||||
|
|
||||||
|
[CONF_LIVE_AUTO_UNMUTE]: ['selected', 'visible'],
|
||||||
|
|
||||||
|
[CONF_DIMENSIONS_ASPECT_RATIO_MODE]: 'static',
|
||||||
|
[CONF_DIMENSIONS_ASPECT_RATIO]: '16:9',
|
||||||
|
|
||||||
// These values are defaults anyway unless another profile (e.g.
|
// These values are defaults anyway unless another profile (e.g.
|
||||||
// low-performance) is also selected, but at pretty important to a good
|
// low-performance) is also selected, but at pretty important to a good
|
||||||
// experience so are reset here.
|
// experience so are reset here.
|
||||||
|
|||||||
+7
-4
@@ -328,11 +328,14 @@ export const CONF_MENU_STYLE = `${CONF_MENU}.style` as const;
|
|||||||
export const CONF_MENU_BUTTON_SIZE = `${CONF_MENU}.button_size` as const;
|
export const CONF_MENU_BUTTON_SIZE = `${CONF_MENU}.button_size` as const;
|
||||||
export const CONF_MENU_BUTTONS = `${CONF_MENU}.buttons` as const;
|
export const CONF_MENU_BUTTONS = `${CONF_MENU}.buttons` as const;
|
||||||
|
|
||||||
export const CONF_MENU_BUTTONS_FRIGATE = `${CONF_MENU}.buttons.frigate` as const;
|
export const CONF_MENU_BUTTONS_FRIGATE = `${CONF_MENU_BUTTONS}.frigate` as const;
|
||||||
export const CONF_MENU_BUTTONS_CAMERA_UI = `${CONF_MENU}.buttons.camera_ui` as const;
|
export const CONF_MENU_BUTTONS_CAMERA_UI = `${CONF_MENU_BUTTONS}.camera_ui` as const;
|
||||||
|
export const CONF_MENU_BUTTONS_FULLSCREEN = `${CONF_MENU_BUTTONS}.fullscreen` as const;
|
||||||
|
export const CONF_MENU_BUTTONS_PLAY = `${CONF_MENU_BUTTONS}.play` as const;
|
||||||
|
export const CONF_MENU_BUTTONS_MUTE = `${CONF_MENU_BUTTONS}.mute` as const;
|
||||||
export const CONF_MENU_BUTTONS_MEDIA_PLAYER =
|
export const CONF_MENU_BUTTONS_MEDIA_PLAYER =
|
||||||
`${CONF_MENU}.buttons.media_player` as const;
|
`${CONF_MENU_BUTTONS}.media_player` as const;
|
||||||
export const CONF_MENU_BUTTONS_TIMELINE = `${CONF_MENU}.buttons.timeline` as const;
|
export const CONF_MENU_BUTTONS_TIMELINE = `${CONF_MENU_BUTTONS}.timeline` as const;
|
||||||
|
|
||||||
export const CONF_STATUS_BAR = 'status_bar' as const;
|
export const CONF_STATUS_BAR = 'status_bar' as const;
|
||||||
export const CONF_STATUS_BAR_POSITION = `${CONF_STATUS_BAR}.position` as const;
|
export const CONF_STATUS_BAR_POSITION = `${CONF_STATUS_BAR}.position` as const;
|
||||||
|
|||||||
@@ -7,11 +7,17 @@ import { CASTING_PROFILE } from '../../../src/config/profiles/casting';
|
|||||||
it('should contain expected defaults', () => {
|
it('should contain expected defaults', () => {
|
||||||
expect(CASTING_PROFILE).toEqual({
|
expect(CASTING_PROFILE).toEqual({
|
||||||
'cameras_global.image.refresh_seconds': 1,
|
'cameras_global.image.refresh_seconds': 1,
|
||||||
|
'dimensions.aspect_ratio_mode': 'static',
|
||||||
'dimensions.aspect_ratio': '16:9',
|
'dimensions.aspect_ratio': '16:9',
|
||||||
'live.auto_unmute': ['selected', 'visible'],
|
'live.auto_unmute': ['selected', 'visible'],
|
||||||
'live.controls.builtin': false,
|
'live.controls.builtin': false,
|
||||||
'live.show_image_during_load': true,
|
'live.show_image_during_load': true,
|
||||||
'media_viewer.controls.builtin': false,
|
'media_viewer.controls.builtin': false,
|
||||||
|
'menu.buttons.fullscreen.enabled': false,
|
||||||
|
'menu.buttons.media_player.enabled': false,
|
||||||
|
'menu.buttons.mute.enabled': true,
|
||||||
|
'menu.buttons.play.enabled': true,
|
||||||
|
'menu.style': 'none',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user