Files
advanced-camera-card/docs/examples.md
T

54 KiB

Examples

Actions on tap

You can add actions to the card to be trigger on tap, double_tap, hold, start_tap or end_tap.

In this example double clicking the card in any view will cause the card to go into fullscreen mode, except when the view is live in which case the office lights are toggled.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
view:
  actions:
    double_tap_action:
      action: custom:advanced-camera-card-action
      advanced_camera_card_action: fullscreen
live:
  actions:
    entity: light.office_main_lights
    double_tap_action:
      action: toggle

Aspect ratios

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
dimensions:
  aspect_ratio_mode: static
  aspect_ratio: '4:3'

Automation

Responding to fullscreen

This example will automatically turn on the first configured substream when the card is put in fullscreen mode, and turn off the substream when exiting fullscreen mode.

Warning

When fullscreen is entered via a video player's built-in controls (rather than the card's fullscreen menu button), automation actions that replace that video element (e.g. switching substreams from one video to another) will immediately exit fullscreen (as the browser sees the video the user clicked on be destroyed). See the fullscreen condition for details.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    live_provider: image
    dependencies:
      cameras:
        - office_hd
  - camera_entity: camera.office
    title: Office HD
    live_provider: go2rtc
    id: office_hd
    capabilities:
      disable_except:
        - substream
        # Optionally allow media on this substream.
        - clips
        - recordings
        - reviews
        - snapshots
        # Optionally allow PTZ controls on the substream.
        - ptz
automations:
  # Entering fullscreen: turn the substream on.
  - triggers:
      - trigger: fullscreen
        fullscreen: true
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: substream_on
  # Exiting fullscreen: turn it off again.
  - triggers:
      - trigger: fullscreen
        fullscreen: false
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: substream_off

Fullscreen with display mode and substream switching

This example adds a custom menu button that switches to single display mode, activates the HD substream, and enters card fullscreen -- all in a single tap. An automation restores the grid layout and substream when fullscreen is exited. This is useful in grid layouts where the card's standard fullscreen button would show all cameras rather than a single HD stream.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    dependencies:
      cameras:
        - office_hd
  - camera_entity: camera.office_hd
    title: Office HD
    id: office_hd
    capabilities:
      disable_except:
        - substream
live:
  display:
    mode: grid
elements:
  - type: custom:advanced-camera-card-menu-icon
    icon: mdi:fullscreen
    title: Fullscreen HD
    tap_action:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: display_mode_select
        display_mode: single
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: substream_on
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: fullscreen
automations:
  - triggers:
      - trigger: fullscreen
        fullscreen: false
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: substream_off
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: display_mode_select
        display_mode: grid

Responding to key input

In addition to a handful of reconfigurable built-in keyboard shortcuts, automations can be used to take any action based on any keyboard input. These examples use key conditions to assess keyboard state before taking action.

Change to live temporarily

In this example, the view will change to live, when Alt+Z is pressed, and change to the clips view 5 seconds later.

automations:
  - triggers:
      - trigger: key
        key: z
        alt: true
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: live
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: sleep
        duration:
          s: 5
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: clips

Change to live while key held down

In this example, the view will change to live, when Alt+Z is held down, and immediately change to clips when released.

automations:
  # Held down: switch to live.
  - triggers:
      - trigger: key
        key: z
        alt: true
        state: down
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: live
  # Released: switch back to clips.
  - triggers:
      - trigger: key
        key: z
        alt: true
        state: up
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: clips

Cameras

Frigate camera without a camera_entity

In this example, there is no Home Assistant entity linked to the camera, just a frigate camera name:

type: custom:advanced-camera-card
cameras:
  - frigate:
      camera_name: office
    live_provider: go2rtc

A go2rtc stream without a camera_entity

In this example, there is no Home Assistant entity linked to the camera, just a go2rtc stream.

type: custom:advanced-camera-card
cameras:
  - live_provider: go2rtc
    go2rtc:
      stream: office
      url: https://my.go2rtc.url:1984

Warning

Browsers will reject mixed content: if you access Home Assistant over https, you must also put go2rtc behind https and use that in the url parameter. Check go2rtc proxying as an alternative.

Card Mod

This card allows the use of card-mod to style arbitrary card contents.

Warning

Card mod relies on the underlying internal DOM structure to style elements -- as such, while its use is possible, it's not officially supported and zero attempt is made to preserve backwards compatability of the internal DOM between any versions. It may look good, but you're on your own!

This example changes the color and removes the padding around a Picture Elements state label.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
card_mod:
  style:
    advanced-camera-card-elements $:
      hui-state-label-element $: |
        div {
          padding: 0px !important;
          color: blue;
        }

Cast a dashboard

This example will configure an Advanced Camera Card that can cast a dashboard view to a media player, which has a second Advanced Camera Card in panel mode with a low-latency live provider.

Source card

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    live_provider: image
    cast:
      method: dashboard
      dashboard:
        dashboard_path: cast
        view_path: office

Dashboard configuration

Note

This dashboard is configured at the path /cast/ (path referred to in dashboard_path above).

title: Advanced Camera Card Casting
views:
  - title: Casting
    # This path is referred to in `view_path` above.
    path: office
    # Ensure the video is "maximized" / dashboard in "panel" mode.
    type: panel
    cards:
      - type: custom:advanced-camera-card
        cameras:
          - camera_entity: camera.office
            live_provider: go2rtc

Conditional elements

You can restrict elements to only show for certain views using a custom:advanced-camera-card-conditional element. This example shows a car icon that calls a service but only in the live view.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-conditional
    conditions:
      - condition: view
        views:
          - live
    elements:
      - type: icon
        icon: mdi:car
        style:
          background: rgba(255, 255, 255, 0.25)
          border-radius: 5px
          right: 25px
          bottom: 50px
        tap_action:
          action: perform-action
          service: amcrest.ptz_control
          data:
            entity_id: camera.kitchen
            movement: up

Conditional menu icons

You can have icons conditionally added to the menu based on entity state.

Show a menu icon based on state

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: conditional
    conditions:
      - condition: state
        entity: light.office_main_lights
        state: on
    elements:
      - type: custom:advanced-camera-card-menu-state-icon
        entity: light.office
        tap_action:
          action: toggle

Show a menu icon based on camera triggering

This example adds a menu button to optionally activate a siren when the camera is triggered.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-conditional
    elements:
      - type: custom:advanced-camera-card-menu-icon
        icon: mdi:alarm-bell
        title: Activate alarm
        style:
          color: red
        tap_action:
          action: perform-action
          perform_action: homeassistant.toggle
          target:
            entity_id: siren.siren
    conditions:
      - condition: triggered
        triggered:
          - camera.office

Doorbell

felipecrs/dahua-vto-on-home-assistant provides an example on how this card can be used to answer a doorbell in Home Assistant.

Doorbell example

Inbound call on doorbell press

The doorbell profile turns a dashboard into a phone-like ringer when somebody presses the doorbell, by setting view.triggers.actions.trigger: call and auto-discovering HA event.* entities with device_class: doorbell on the camera's device (Ring, UniFi Protect, Nest, DoorBird, Reolink, etc.). The intended deployment is a wall-mounted tablet sitting on the dashboard.

A doorbell press is instantaneous, so the card synthesizes a ring window from view.triggers.event_hold_seconds (default 30s) -- long enough for a typical phone-style answer window. untrigger_delay_seconds then lingers past that, same as for any stateful trigger.

triggers.motion, triggers.occupancy, and triggers.media_events are off by default -- only the explicit doorbell press triggers the call, so casual motion won't make the card ring.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.front_door
    # `go2rtc` + `webrtc` is needed for two-way audio.
    live_provider: go2rtc
    go2rtc:
      modes:
        - webrtc
profiles:
  - doorbell

Tip

If your doorbell exposes a binary_sensor.* or switch.* instead of an event.* entity, list it under triggers.entities on the camera manually. Auto-discovery only covers event.* based doorbell entities.

With a Zigbee (ZHA / deCONZ) doorbell button

Zigbee buttons connected via ZHA or deCONZ typically don't expose a per-device entity -- they fire raw HA bus events (zha_event, deconz_event) shared across every Zigbee device on the integration. The doorbell profile's auto-discovery doesn't cover this case; reuse the profile (it still wires up trigger: call / untrigger: call and the ring window) but opt out of auto-discovery per camera and add triggers.events with an event_data filter to pick out the right device.

You can copy the exact device_ieee (ZHA) or id (deCONZ) and command values straight out of Developer tools → Events in Home Assistant -- listen to the event type, press the doorbell, and use whatever appears in the data payload.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.front_door
    live_provider: go2rtc
    go2rtc:
      modes:
        - webrtc
    triggers:
      # Opt out of the profile's `event.*` auto-discovery -- this camera
      # uses an HA bus event instead.
      doorbell: false
      events:
        - event_type: zha_event
          event_data:
            device_ieee: '00:11:22:33:44:55:66:77'
            command: press
profiles:
  - doorbell

Alerting the rest of the house

A wall tablet only helps whoever is standing in front of it. This example uses the call trigger to drive an input_boolean that a normal Home Assistant automation can watch, so the rest of the house "rings" too -- and, crucially, stops ringing the moment somebody deals with the caller.

The card knows things Home Assistant cannot see on its own: whether anyone actually picked the call up, and whether it was answered or dismissed. Each phase change gets its own automation.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.front_door
    live_provider: go2rtc
    go2rtc:
      modes:
        - webrtc
profiles:
  - doorbell
automations:
  # It started ringing: ring the rest of the house and light the porch so the
  # visitor is actually visible on camera.
  - triggers:
      - trigger: call
        to: ringing
    actions:
      - action: perform-action
        perform_action: input_boolean.turn_on
        target:
          entity_id: input_boolean.doorbell_ringing
      - action: perform-action
        perform_action: light.turn_on
        target:
          entity_id: light.porch

  # Somebody answered on the tablet: silence every other device immediately.
  # `from: ringing` keeps this from firing when *you* start an outbound call.
  - triggers:
      - trigger: call
        from: ringing
        to: answered
    actions:
      - action: perform-action
        perform_action: input_boolean.turn_off
        target:
          entity_id: input_boolean.doorbell_ringing

  # Nobody picked up, or somebody rejected it: stop ringing, and announce that
  # a visitor was missed.
  - triggers:
      - trigger: call
        from: ringing
        to: idle
    actions:
      - action: perform-action
        perform_action: input_boolean.turn_off
        target:
          entity_id: input_boolean.doorbell_ringing
      - action: perform-action
        perform_action: notify.mobile_app_phone
        data:
          message: Somebody was at the front door and nobody answered.

  # The conversation ended. Only fires for calls that were actually answered,
  # so an unanswered ring never turns the porch light off early.
  - triggers:
      - trigger: call
        from: answered
        to: idle
    actions:
      - action: perform-action
        perform_action: light.turn_off
        target:
          entity_id: light.porch

Doorbells that stop ringing when two-way audio connects

Warning

This example is only relevant to those doorbells with a design flaw that prevents the doorbell being rung while a 2-way channel is enabled. This means simply watching the stream, when you might in future hold a 2-way conversation on that stream, can disable the actual whole point of a doorbell -- to ring!

The fix is to split the camera:

  • A plain, view-only stream you normally watch (with no backchannel)
  • A second camera carrying the two-way stream, listed as a dependency of the first camera. The card only engages the two-way stream -- and therefore the backchannel -- when you start a call, and automatically drops it again on hang-up. The doorbell keeps ringing until you actually choose to answer.
type: custom:advanced-camera-card
cameras:
  # The camera you normally watch: a view-only stream you have configured to
  # not have a backchannel, so opening the card does not disturb the doorbell.
  - camera_entity: camera.front_doorbell
    id: doorbell
    live_provider: go2rtc
    go2rtc:
      modes: [webrtc]
      # Stream with NO backchannel source
      stream: front_doorbell
    dependencies:
      # The two-way dependent camera (below) only used during a call
      cameras: [doorbell_2way]
  # The two-way camera. Never watched on its own: the call button engages it as
  # a substream for the duration of a call, then drops it on hang-up.
  - camera_entity: camera.front_doorbell
    id: doorbell_2way
    live_provider: go2rtc
    go2rtc:
      modes: [webrtc]
      # The two-way go2rtc stream (carries the backchannel)
      stream: front_doorbell_2way
    capabilities:
      # This camera exists only to supply the call's two-way audio. Disabling
      # everything except `2-way-audio` keeps it out of the camera menu and the
      # substream selector, while still letting the call button target it.
      disable_except:
        - 2-way-audio
profiles:
  - doorbell

Important

This only works if the view-only stream genuinely has no backchannel source in your go2rtc config -- otherwise go2rtc may still take over the doorbell the moment that stream is opened. Test the view-only camera on its own first: if the doorbell stops ringing with just that camera configured, that stream is the culprit. If you can't produce a clean one-way go2rtc stream, try setting the view-only camera to live_provider: ha (HLS / receive-only WebRTC, which never offers a backchannel) instead.

Driving calls from the menu

By default on-screen controls will appear mid-card to handle a call. Setting live.controls.call.enabled: false hides those controls so the call can be driven via some other mechanism. In this example, the card is configured to allow calls to be driven from the menu instead.

The single menu call button handles the whole call: it starts a call, answers an inbound ring (hold to reject it instead), and hangs up. It is shown by default, so only the microphone and audio buttons need enabling below to cover the full functionality of the (in this example: disabled) call controls.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.front_door
    live_provider: go2rtc
    go2rtc:
      modes:
        - webrtc
profiles:
  - doorbell
live:
  controls:
    call:
      # Hide the on-screen call controls overlay -- the menu drives the call.
      enabled: false
menu:
  # The menu hides during a call by default; keep it visible so its call
  # controls stay reachable.
  auto_hide: []
  buttons:
    # Mutes/unmutes your outbound microphone during a call.
    microphone:
      enabled: true
      type: toggle
    # Mutes/unmutes the inbound (caller's) audio during a call.
    mute:
      enabled: true

Events from other cameras

dependencies.cameras allows events/recordings for other cameras to be shown along with the currently selected camera. For example, this can be used to show events with the birdseye camera (since it will not have events of its own).

Using dependent cameras with birdseye

This example shows events for two other cameras when birdseye is selected.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
  - camera_entity: camera.kitchen
  - frigate:
      camera_name: birdseye
    dependencies:
      cameras:
        - camera.office
        - camera.kitchen

Using dependent cameras with birdseye for all cameras

This example shows events for all other cameras when birdseye is selected. This is just a shortcut for naming all other cameras.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.kitchen
  - camera_entity: camera.sitting_room
  - frigate:
      camera_name: birdseye
    dependencies:
      all_cameras: true

Folders

These examples create folders that can be viewed in the media_gallery.

Tip

Having difficulty configuring your folders? Consult the Worked Examples in the folders documentation.

Home Assistant default root

This example creates a folder at the Home Assistant media root.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
folders:
  - type: ha

Folder within the Home Assistant default root

This example applies a title match against the Home Assistant media root folder looking for a folder entitled Frigate, and shows all items within it (since no matcher is specified at the lowest level).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
folders:
  - type: ha
    ha:
      path:
        - matchers:
            - type: title
              title: 'Frigate'
        - {}

Folder date parsing and matching

This example parses dates from a folder, and matches only those dates in the last two days. It then parses times from the media items themselves.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
folders:
  - type: ha
    ha:
      url: >-
        https://my-ha-instance.local/media-browser/browser/app%2Cmedia-source%3A%2F%2Freolink/playlist%2Cmedia-source%3A%2F%2Freolink%2FCAM%7C01J8XHYTNH77WE3C654K03KX1F%7C0
      path:
        # Matches against the "Low resolution" folder.
        - matchers:
            - type: title
              regexp: (?<value>.*) resolution
              title: Low
        # Parses the date out of the next level (auto-detected format).
        - parsers:
            - type: date
          matchers:
            - type: date
              since:
                days: 2
        # Parses the time out of the items themselves (user-specified format).
        - parsers:
            - type: date
              format: 'HH:mm:ss'

Folder date matching by template

This example dynamically includes media from two subfolders, one for today and one for yesterday both in %Y/%-m/%d format. Templating is used to dynamically refer to "today" and "yesterday".

Tip

Using a date matcher (as above) should be preferred for matching dates, this example is included for illustration.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
folders:
  - type: ha
    ha:
      url: https://my-ha-instance.local/media-browser/browser/app%2Cmedia-source%3A%2F%2Freolink/playlist%2Cmedia-source%3A%2F%2Freolink%2FCAM%7C01J8XAATNH77WE5D654K07KY1F%7C0
      path:
        - matchers:
            - type: title
              title: 'Low resolution'
        - matchers:
            - type: or
              matchers:
                - type: template
                  value_template: "{{ acc.media.title == now().strftime('%Y/%-m/%d') }}"
                - type: template
                  value_template: "{{ acc.media.title == (now() - dt.timedelta(days=1)) | timestamp_custom('%Y/%-m/%d') }}"
        - {}

Folder Paths

This example starts with the media-source://frigate folder, and looks for a precisely titled Clips [my-instance] folder within that. The resulting media will be the contents of that folder (if found).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
folders:
  - type: ha
    ha:
      path:
        - id: 'media-source://frigate'
        - title: 'Clips [my-instance]'

Folder URLs

This example uses the url parameter to establish the root of the query. Within that folder, it looks for a sub-folder that matches the regular expression Clips.*, and within that looks for a folder that matches the regular expression Person.*. The resulting media will be the contents of that folder (if found).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
folders:
  - type: ha
    ha:
      url: https://my-ha-instance.local/media-browser/browser/app%2Cmedia-source%3A%2F%2Ffrigate
      path:
        - matchers:
            - type: title
              regexp: 'Clips.*'
        - matchers:
            - type: title
              regexp: 'Person.*'

Show a folder as a camera's default media

By default a camera shows its own events / recordings. Setting media.type: folder instead makes a configured folder the camera's default media, so its contents drive the timeline and gallery. This is useful when the camera's interesting media (e.g. detection clips) only lives in a Home Assistant media folder rather than being exposed as native events.

The camera references the folder by its id. Parsing a startdate from each item lets the timeline place the media in time.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.reolink_doorbell
    media:
      type: folder
      folders:
        - reolink-detections
folders:
  - id: reolink-detections
    type: ha
    ha:
      # Open HA -> Media, navigate into the desired folder and copy its URL here.
      url: https://my-ha-instance.local/media-browser/browser/app%2Cmedia-source%3A%2F%2Freolink/playlist%2Cmedia-source%3A%2F%2Freolink%2FCAM%7C01J8XAATNH77WE5D654K07KY1F%7C0
      path:
        # Match every item in the folder and parse its start time.
        - parsers:
            - type: startdate

Show only matching items as a camera's default media

The card can only point at folders the Home Assistant Media browser actually exposes. If your integration surfaces a single flat list of recordings rather than a dedicated folder per event type, you can add a title matcher to keep only the items you care about (in this example clips whose title mentions Person or Vehicle).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.reolink_doorbell
    media:
      type: folder
      folders:
        - reolink-detections
folders:
  - id: reolink-detections
    type: ha
    ha:
      url: https://my-ha-instance.local/media-browser/browser/app%2Cmedia-source%3A%2F%2Freolink/playlist%2Cmedia-source%3A%2F%2Freolink%2FCAM%7C01J8XAATNH77WE5D654K07KY1F%7C0
      path:
        - matchers:
            # Keep only clips whose title mentions a person or vehicle detection.
            - type: title
              regexp: Person|Vehicle
          parsers:
            - type: startdate

go2rtc

This example will use a custom go2rtc server, automatically proxying the video stream via the Home Assistant process if hass-web-proxy-integration is detected. See proxying.

type: custom:advanced-camera-card
cameras:
  - live_provider: go2rtc
    go2rtc:
      stream: office
      # This would normally risk mixed content issues with browsers (accessing
      # `http` content over a `https` connection to Home Assistant is often
      # forbidden by browsers). In this scenario, since hass-web-proxy-integration
      # has been installed separately by the user, the video will be automatically
      # proxied.
      url: http://my-go2rtc:1984

Warning

You may need to set api.origin: '*' in your go2rtc configuration.

Human interaction

This example will automatically use a HD live substream when the mouse cursor interacts with the card.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    live_provider: image
    dependencies:
      cameras:
        - camera.office_hd
  - camera_entity: camera.office_hd
    live_provider: go2rtc
    capabilities:
      disable_except:
        - substream
        # Also allow PTZ controls on the substream.
        - ptz
automations:
  # On interaction: turn the HD substream on.
  - triggers:
      - trigger: interaction
        interaction: true
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: substream_on
  # Once the interaction lapses: turn it off again.
  - triggers:
      - trigger: interaction
        interaction: false
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: substream_off

Media layout

These examples change how the media fits and is positioned within the card dimensions.

Stretch a camera into a 4:4 square

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.landing
    dimensions:
      aspect_ratio: '4:4'
      layout:
        fit: fill

Convert a landscape camera to a portrait live view

Take the left-hand side (position with x == 0) and use that as the basis of a 9:16 (i.e. portrait) live view.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    dimensions:
      aspect_ratio: '9:16'
      layout:
        fit: cover
        position:
          x: 0

Menu alignment

This example moves the fullscreen button into its own group aligned to the left, enables the image button and orders it furthest to the right.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
menu:
  alignment: right
  buttons:
    image:
      enabled: true
      priority: 100
    fullscreen:
      alignment: opposing

Menu icons

You can add custom icons to the menu with arbitrary actions. This example adds an icon that navigates the browser to the releases page for this card:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-icon
    icon: mdi:book
    tap_action:
      action: url
      url_path: https://github.com/dermotduffy/advanced-camera-card/releases

Menu state icons

You can add custom state icons to the menu to show the state of an entity and complete arbitrary actions. This example adds an icon that represents the state of the light.office_main_lights entity, that toggles the light on double click.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-state-icon
    entity: light.office_main_lights
    tap_action:
      action: toggle

Multiple actions

This example shows how to configure multiple actions for a single Advanced Camera Card user interaction, in this case both selecting a different camera and changing the view on tap. Note that multiple actions are not supported on stock Picture Elements, see actions for more information.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-icon
    icon: mdi:chair-rolling
    tap_action:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: camera_select
        camera: camera.office
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: live

Multiple providers

Cameras can be repeated with different providers (note the required use of id to provide a separate unambiguous way of referring to that camera, since the camera_entity is shared between the two cameras).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    live_provider: jsmpeg
    title: Office (JSMPEG)
  - camera_entity: camera.office
    live_provider: webrtc-card
    title: Office (WebRTC)
    id: office-webrtc

Notifications

Show a notification with controls that respond to different interactions. In this example, tapping the control navigates to the clips (media gallery) view and double-tapping navigates to the clip (media player) view.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-icon
    icon: mdi:bell
    title: Show notification
    tap_action:
      action: custom:advanced-camera-card-action
      advanced_camera_card_action: notification
      notification:
        heading:
          text: Motion detected
          icon: mdi:motion-sensor
          severity: medium
        text: Motion was detected in the office.
        controls:
          - icon: mdi:filmstrip
            tooltip: View clips (tap) / clip (double-tap)
            actions:
              tap_action:
                action: custom:advanced-camera-card-action
                advanced_camera_card_action: clips
              double_tap_action:
                action: custom:advanced-camera-card-action
                advanced_camera_card_action: clip
            dismiss: false

Overriding configuration

You can override card configuration when certain conditions are met.

Change menu position based on HA state

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
overrides:
  - conditions:
      - condition: state
        entity: light.office_main_lights
        state: 'on'
    merge:
      menu:
        position: bottom

Change default view based on HA state

This example changes the default card view from live to image depending on the value of the binary_sensor.alarm_armed sensor. The override alone will only change the default when the card next is requested to change to the default view. By also including the view.default_reset.entities parameter, we ask the card to trigger a card update based on that entity -- which causes it to use the new overriden default immediately.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
view:
  default: live
  default_reset:
    entities:
      - binary_sensor.alarm_armed
overrides:
  - conditions:
      - condition: state
        entity: binary_sensor.alarm_armed
        state: 'off'
    merge:
      view:
        default: image

Change grid behavior in full screen

This example will always render 5 columns in fullscreen mode in both the live and media viewer views, and will not enlarge the selected item. The normal auto-layout behavior will be used outside of fullscreen mode.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
overrides:
  - conditions:
      - condition: fullscreen
        fullscreen: true
      - condition: display_mode
        display_mode: grid
    merge:
      live:
        display:
          grid_columns: 5
          grid_selected_width_factor: 1
      media_viewer:
        display:
          grid_columns: 5
          grid_selected_width_factor: 1

Change menu style when expanded

This example changes the menu style to overlay in expanded mode in order to take advantage of the extra horizontal space of the dialog/popup.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
menu:
  style: hidden
overrides:
  - conditions:
      - condition: expand
        expand: true
    merge:
      menu:
        style: overlay

Hide menu in fullscreen

This example disables the menu unless the card is in fullscreen mode, and uses a card-wide action to enable fullscreen mode on double_tap.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
view:
  actions:
    double_tap_action:
      action: custom:advanced-camera-card-action
      advanced_camera_card_action: fullscreen
overrides:
  - conditions:
      - condition: fullscreen
        fullscreen: true
    merge:
      menu:
        style: none

Remove a camera when an entity state changes

This example removes a camera from the card when an entity is disabled (e.g. a switch controlling power to the camera).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
  - camera_entity: camera.kitchen
overrides:
  - conditions:
      - condition: state
        entity: switch.kitchen_camera_power
        state: off
    delete:
      - 'cameras[1]'

Disable PTZ controls in the Home Assistant Companion App

This example disables the PTZ controls when the card is viewed on the Companion app:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
overrides:
  - conditions:
      - condition: user_agent
        companion: true
    set:
      live.controls.ptz.mode: 'off'

PTZ control

The card supports using PTZ controls to conveniently control pan, tilt and zoom for cameras. If you're using a Frigate camera, and Frigate itself shows PTZ controls, this should work straight out of the box without any extra configuration:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office

If you're using a non-Frigate camera, or Frigate itself does not support the PTZ controls on your camera but Home Assistant does, you can still manually configure actions for the card to perform for each PTZ control:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    ptz:
      actions_left:
        action: perform-action
        perform_action: homeassistant.toggle
        target:
          entity_id: switch.camera_move_left

See the full Camera PTZ Configuration for more information.

screen conditions

These examples show altering the card configuration based on device or viewport properties.

Change menu position when orientation changes

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
  - camera_entity: camera.kitchen
menu:
  style: overlay
overrides:
  - conditions:
      - condition: screen
        media_query: '(orientation: landscape)'
    merge:
      menu:
        position: left

Hide menu & controls when viewport width <= 300 (e.g. PIP mode)

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
  - camera_entity: camera.kitchen
overrides:
  - conditions:
      - condition: screen
        media_query: '(max-width: 300px)'
    merge:
      menu:
        style: none
      live:
        controls:
          next_previous:
            style: none
          thumbnails:
            mode: none

State Badges

You can add a state badge to the card showing arbitrary entity states. This example adds a state badge showing the temperature and hides the label text:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: state-badge
    entity: sensor.office_temperature
    style:
      right: '-20px'
      top: 100px
      color: rgba(0,0,0,0)
      opacity: 0.5

Picture elements temperature example

Static images

This example fetches a static image every 10 seconds (in this case the latest image saved on the Frigate server for a given camera).

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
view:
  default: image
image:
  src: https://my-friage-server/api/living_room/latest.jpg
  refresh_seconds: 10

Status bar

Disable status bar

This example disables the status bar.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
status_bar:
  style: none

Dynamic status bar contents

This example shows an icon and a message on the status bar when a camera is triggered, replacing the existing contents of the status bar through the use of exclusive.

Dynamic Status Messages

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
automations:
  # Camera triggered: show the alert.
  - triggers:
      - trigger: triggered
        triggered:
          - camera.office
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: status_bar
        status_bar_action: add
        items:
          - type: custom:advanced-camera-card-status-bar-icon
            icon: mdi:alarm-light
            exclusive: true
          - type: custom:advanced-camera-card-status-bar-string
            string: Intruder detected!
            expand: true
            exclusive: true
            sufficient: true
  # No longer triggered: reset the status bar.
  - triggers:
      - trigger: triggered
        triggered: []
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: status_bar
        status_bar_action: reset

Submenus

You can add submenus to the menu -- buttons that when pressed reveal a dropdown submenu of configurable options.

Basic submenu

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-submenu
    icon: mdi:menu
    items:
      - title: Lights
        icon: mdi:lightbulb
        entity: light.office_main_lights
        tap_action:
          action: toggle
      - title: Google
        icon: mdi:google
        tap_action:
          action: url
          url_path: https://www.google.com
      - title: Fullscreen
        icon: mdi:fullscreen
        tap_action:
          action: custom:advanced-camera-card-action
          advanced_camera_card_action: fullscreen

Conditional submenu

This example shows submenus conditional on the camera selected.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-conditional
    conditions:
      - condition: camera
        cameras:
          - camera.office
    elements:
      - type: custom:advanced-camera-card-menu-submenu
        icon: mdi:door
        items:
          - title: Office Lights
            icon: mdi:lightbulb
            entity: light.office_main_lights
            tap_action:
              action: toggle
  - type: custom:advanced-camera-card-conditional
    conditions:
      - condition: camera
        cameras:
          - camera.kitchen
    elements:
      - type: custom:advanced-camera-card-menu-submenu
        icon: mdi:sofa
        items:
          - title: Kitchen Lights
            icon: mdi:lightbulb
            entity: light.kitchen_lights
            tap_action:
              action: toggle
          - title: Kitchen Lamp
            icon: mdi:lightbulb
            entity: light.kitchen_lamp
            tap_action:
              action: toggle

select submenu

You can easily add a submenu to the menu based on a select or input_select entity. This example imagines the user has an input_select entity configured in their Home Assistant configuration like so:

input_select:
  office_scene:
    name: Office Scene Select
    options:
      - scene.office_quiet_scene
      - scene.office_party_scene
    icon: mdi:lightbulb

The following will convert this entity into a submenu:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-submenu-select
    entity: input_select.office_scene

To override 1 or more individual options (e.g. to set custom icons and titles)

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: custom:advanced-camera-card-menu-submenu-select
    icon: mdi:lamps
    entity: input_select.office_scene
    options:
      scene.office_quiet_scene:
        icon: mdi:volume-off
        title: Ssssssh
      scene.office_party_scene:
        icon: mdi:party-popper
        title: Party!

Substreams

The card supports configuring 'substreams' (alternative live views) a given camera through the use of camera dependencies.

This example shows two substreams for a single live camera, and uses the 'HD' icon.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    live_provider: image
    dependencies:
      cameras:
        - office_hd
  - camera_entity: camera.office
    title: Office HD
    live_provider: go2rtc
    id: office_hd
    capabilities:
      disable_except:
        # This camera serves only as a substream.
        - substream
        # Also allow PTZ controls on the substream.
        - ptz
menu:
  buttons:
    substreams:
      icon: mdi:high-definition

Templates in actions

Accessing Home Assistant state

Perhaps the most common usage of templates is to access Home Assistant state values. In the below example a fictitious service homeassistant.service is called with data that refers to the current state of the light.sunroom_ceiling entity.

tap_action:
  action: perform-action
  perform_action: homeassistant.service
  data:
    key: '{{ hass.states["light.sunroom_ceiling"].state }}'

See Stock Templates.

Accessing Advanced Camera Card state

In this example, the currently selected camera and view are passed as data to a fictitious service homeassistant.service.

tap_action:
  action: perform-action
  perform_action: homeassistant.service
  data:
    camera: '{{ acc.camera }}'
    view: '{{ acc.view }}'

See Custom Templates.

Accessing Trigger state

In this example, an automation is triggered, and values associated with the triggering are included in the action.

automations:
  - triggers:
      - trigger: camera
    actions:
      - action: perform-action
        perform_action: homeassistant.service
        data:
          from_camera: '{{ trigger.from_acc.camera }}'
          to_camera: '{{ trigger.to_acc.camera }}'

See Trigger Templates.

Theme

Custom border radius

This example shows how to customize the border radius for both the card and buttons to create a cohesive squared-off look:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
view:
  theme:
    overrides:
      # Set a custom border radius for the card
      '--advanced-camera-card-border-radius': '12px'

      # Match the button border radius to complement the card
      '--advanced-camera-card-button-border-radius': '12px'

Trigger actions

You can control the card itself with the custom:advanced-camera-card-action action. This example shows an icon that toggles the card fullscreen mode.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
elements:
  - type: icon
    icon: mdi:fullscreen
    style:
      left: 40px
      top: 40px
    tap_action:
      action: custom:advanced-camera-card-action
      advanced_camera_card_action: fullscreen

Trigger fullscreen

The card cannot automatically natively trigger fullscreen mode without the user clicking, since Javascript (understandbly) prevents random websites from triggering fullscreen mode without the user having activated it.

This example uses hass-browser_mod with an automation to trigger a popup. Thanks to conorlap@ for the following example:

alias: >-
  Doorbell Pressed OR Human Detected - Firefox browser full screen video feed
  for 15 seconds
description: ''
trigger:
  - platform: state
    from: 'off'
    to: 'on'
    entity_id:
      - binary_sensor.frontdoor_person_occupancy
  - platform: state
    entity_id:
      - binary_sensor.front_door_dahua_button_pressed
    to: 'on'
condition: []
action:
  - service: browser_mod.popup
    data:
      size: wide
      timeout: 15000
      content:
        type: custom:advanced-camera-card
        aspect_ratio: 55%
        cameras:
          - camera_entity: camera.frontdoor
            live_provider: ha
        menu:
          style: none
        live:
          controls:
            title:
              mode: none
    target:
      device_id:
        - d0e93101edfg44y3yt35y5y45y54y
mode: single

Trigger live

This example will change to live when a camera is triggered, using different trigger conditions per camera. It will change back to the default view when untriggered.

type: custom:advanced-camera-card
cameras:
  # This is a Frigate camera which will automatically
  # be triggered when events occur.
  - camera_entity: camera.office
  # This is a Frigate camera which will only be triggered
  # by motion entity changes or a door being opened.
  - camera_entity: camera.kitchen
    triggers:
      occupancy: false
      motion: true
      entities:
        - binary_sensor.kitchen_door_opened
      media_events: []
view:
  triggers:
    show_trigger_status: true
    filter_selected_camera: false
    actions:
      trigger: live
      untrigger: default

Video control from menu

Disable the stock video controls and add menu button equivalents.

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
live:
  controls:
    builtin: false
media_viewer:
  controls:
    builtin: false
menu:
  buttons:
    play:
      enabled: true
    mute:
      enabled: true

URL actions

The card can respond to actions in the query string. See URL Actions.

Note

These examples assume the dashboard URL is https://ha.mydomain.org/lovelace-test/0 .

Choosing clips view on a named card

This example assumes that one card (of potentially multiple Advanced Camera Cards on the dashboard) is configured with a card_id parameter:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
card_id: main
https://ha.mydomain.org/lovelace-test/0?advanced-camera-card-action.main.clips

Choosing the camera from a separate picture elements card

In this example, the card will select a given camera when the user navigates from a separate Picture Elements card:

Advanced Camera Card configuration:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
  - camera_entity: camera.kitchen

Picture Elements configuration:

type: picture-elements
image: https://demo.home-assistant.io/stub_config/floorplan.png
elements:
  - type: icon
    icon: mdi:cctv
    style:
      top: 22%
      left: 30%
    tap_action:
      action: navigate
      navigation_path: /lovelace-test/0?advanced-camera-card-action.camera_select=camera.office
  - type: icon
    icon: mdi:cctv
    style:
      top: 71%
      left: 42%
    tap_action:
      action: navigate
      navigation_path: /lovelace-test/0?advanced-camera-card-action.camera_select=camera.kitchen

Taking card actions via the URL

Selecting a camera in expanded mode via query string

https://ha.mydomain.org/lovelace-test/0?advanced-camera-card-action.camera_select=kitchen&advanced_camera_card_action-action.expand

WebRTC Card configuration

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    live_provider: webrtc-card
    webrtc_card:
      ui: true

Zoom

Pre-defining camera zoom and pan

This example changes the default zoom/pan settings for a camera to always zoom in on a given area:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    dimensions:
      layout:
        zoom: 3
        pan:
          x: 20
          y: 80

Disable zooming in media views

This example prevents zooming on the media viewer but keeps it on in other views (e.g. live view):

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    dimensions:
      layout:
        zoom: 3
        pan:
          x: 20
          y: 80
media_viewer:
  zoomable: false

Different zoom settings in media viewer vs live

This example uses different settings for the media viewer and live view, by overriding the camera configuration:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.office
    dimensions:
      layout:
        zoom: 2
overrides:
  - conditions:
      - condition: view
        views:
          - media
    set:
      'cameras[0].dimensions.layout':
        zoom: 3
        pan:
          x: 100
          y: 100

Automatically zoom based on state

This example automatically zooms in and out based on the state of an entity:

type: custom:advanced-camera-card
cameras:
  - camera_entity: camera.living_room
    live_provider: go2rtc
debug:
  logging: true
automations:
  # Door opens: zoom in.
  - triggers:
      - trigger: state
        entity_id: binary_sensor.door_contact
        to: 'on'
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: ptz_digital
        target_id: camera.living_room
        absolute:
          zoom: 4
          pan:
            x: 38
            y: 20
  # Door closes: zoom back out.
  - triggers:
      - trigger: state
        entity_id: binary_sensor.door_contact
        to: 'off'
    actions:
      - action: custom:advanced-camera-card-action
        advanced_camera_card_action: ptz_digital
        target_id: camera.living_room

Zoom automation example