95 lines
4.6 KiB
Markdown
95 lines
4.6 KiB
Markdown
# WebRTC Doorbell Card
|
|
|
|
A Home Assistant Lovelace card that wraps [AlexxIT/WebRTC](https://github.com/AlexxIT/WebRTC)'s `webrtc-camera` and adds a proper doorbell-style call UX:
|
|
|
|
- **Answer / Hangup** buttons that toggle *both* directions of audio at once (incoming via `video.muted`, outgoing via the mic track's `enabled` flag) — unlike the bare WebRTC card whose mute button only affects the incoming stream.
|
|
- **Configurable unlock button** that fires any HA action (`call-service` / `perform-action`).
|
|
- **Haptic + visual feedback** on tap — vibration where supported, scale + flash + checkmark on the unlock button.
|
|
- **Mic captured up-front** but kept disabled until you press Answer, so there's no permission prompt mid-call.
|
|
|
|
## Requirements
|
|
|
|
- [AlexxIT/WebRTC](https://github.com/AlexxIT/WebRTC) integration installed (this card delegates the actual WebRTC streaming to its `webrtc-camera` card).
|
|
- A camera entity that supports two-way audio via go2rtc (Frigate cameras work, as do Dahua VTOs and many others — see the AlexxIT docs).
|
|
|
|
## Installation
|
|
|
|
### HACS (custom repository)
|
|
|
|
1. HACS → Frontend → ⋮ → Custom repositories
|
|
2. Add `https://github.com/naps62/ha-webrtc-doorbell-card`, category **Dashboard**
|
|
3. Install **WebRTC Doorbell Card**, then hard-refresh your browser.
|
|
|
|
### Manual
|
|
|
|
Copy `webrtc-doorbell-card.js` into `/config/www/` and register it as a Lovelace resource of type `module` pointing at `/local/webrtc-doorbell-card.js`.
|
|
|
|
## Usage
|
|
|
|
```yaml
|
|
type: custom:webrtc-doorbell-card
|
|
entity: camera.doorbell # any camera that webrtc-camera can stream
|
|
unlock_action: # optional — omit to hide the unlock button
|
|
action: perform-action
|
|
perform_action: dahua.vto_open_door
|
|
data:
|
|
door_id: 1
|
|
target:
|
|
entity_id: camera.doorbell_main
|
|
unlock_icon: mdi:key # optional, defaults to mdi:key
|
|
mode: webrtc # optional, passed through to webrtc-camera
|
|
top_max_height_vh: 35 # optional, only for layout: split — caps the
|
|
# full-frame top section at this many vh units
|
|
# (default 35). Lower this if the top half feels
|
|
# too dominant on tall portrait screens.
|
|
landscape_hide_top: true # optional, only for layout: split — when true
|
|
# (default), hides the top full-frame view on
|
|
# landscape orientation since the cropped bottom
|
|
# already fills the screen well. Set false to
|
|
# keep the split in landscape too.
|
|
layout: split # optional — 'split' (default), 'cover', or 'contain'
|
|
# split: top half shows the full uncropped frame,
|
|
# bottom half is a center-cropped 'cover' view.
|
|
# One WebRTC connection drives both.
|
|
# cover: single video, fills viewport (crops sides
|
|
# on portrait phones with landscape cameras).
|
|
# contain: single video, letterboxed to preserve frame.
|
|
object_fit: cover # optional, only honored with layout: cover/contain
|
|
```
|
|
|
|
A `panel: true` view works best:
|
|
|
|
```yaml
|
|
title: Doorbell
|
|
path: doorbell
|
|
icon: mdi:doorbell-video
|
|
panel: true
|
|
cards:
|
|
- type: custom:webrtc-doorbell-card
|
|
entity: camera.doorbell
|
|
unlock_action:
|
|
action: perform-action
|
|
perform_action: dahua.vto_open_door
|
|
data: { door_id: 1 }
|
|
target: { entity_id: camera.doorbell_main }
|
|
```
|
|
|
|
## How it works
|
|
|
|
The card creates an inner `webrtc-camera` configured with `media: video,audio,microphone` and `ui: false`, then overlays its own three buttons.
|
|
|
|
- **Mic capture** — a one-time monkey-patch of `navigator.mediaDevices.getUserMedia` stores a reference to the mic stream and starts every audio track disabled. Pressing Answer flips the tracks' `enabled` flag.
|
|
- **Incoming audio** — toggled via `video.muted` on the inner card's `<video>` element.
|
|
|
|
This means the browser's mic permission prompt fires once on stream start (not on every Answer click), and Answer/Hangup feel instant.
|
|
|
|
### Caveats
|
|
|
|
- The `getUserMedia` patch is global to the page. If another card in the same page also requests audio, the most recent stream wins.
|
|
- iOS Safari ignores `navigator.vibrate()`, so iPhone users get the visual feedback only.
|
|
- If you reload the dashboard mid-call, state resets to muted.
|
|
|
|
## License
|
|
|
|
MIT — see `LICENSE`.
|