feat: Add 'call' support to improve 2-way audio experience (#2486)

Draws significant inspiration (and direct styling) from
https://github.com/dermotduffy/advanced-camera-card/pull/2447 . Thank
you @Maudfer !

BREAKING CHANGE:

The microphone condition previously bundled two unrelated signals —
whether a two-way-audio session was connected and whether the microphone
was muted. Connection state is now its own dedicated call condition, and
microphone is reserved purely for mute state. Configs are upgraded
automatically (the card rewrites affected conditions under overrides,
elements, and automations). If you maintain config by hand, convert as
follows:

If you only used connected:

# Before
```yaml
condition: microphone
connected: true
```

# After
```yaml
condition: call
call: true
```
If you used both connected and muted — they must be split into two
conditions, since they no longer live together:

# Before
```yaml
condition: microphone
connected: true
muted: false
```

# After
```yaml
condition: and
conditions:
  - condition: call
    call: true
  - condition: microphone
    muted: false
```
This commit is contained in:
Dermot Duffy
2026-06-30 17:45:13 -07:00
committed by dermotduffy
parent bb061a1a55
commit abcba884e5
116 changed files with 3871 additions and 845 deletions
+57 -31
View File
@@ -7,23 +7,23 @@ live:
# [...]
```
| Option | Default | Description |
| ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actions` | | [Actions](actions/README.md) to use for the `live` view. |
| `auto_mute` | `[unselected, hidden, microphone]` | A list of conditions in which live camera feeds are muted. `unselected` will automatically mute when a camera is unselected in the carousel or grid. `hidden` will automatically mute when the camera becomes hidden (e.g. browser tab change) or `microphone` will automatically mute after the microphone is muted as long as the camera stays selected (see the `live.microphone.mute_after_microphone_mute_seconds` to control how long after). Use an empty list (`[]`) to never automatically mute. Note that if `auto_play` is enabled, the stream may mute itself automatically in order to honor the `auto_play` setting, as some browsers will not auto play media that is unmuted -- that is to say, where necessary, the `auto_play` parameter will take priority over the `auto_mute` parameter. |
| `auto_pause` | `[]` | A list of conditions in which live camera feeds are automatically paused. `unselected` will automatically pause when a camera is unselected in the carousel or grid. `hidden` will automatically pause when the browser/tab becomes hidden. Use an empty list (`[]`) to never automatically pause. **Caution**: Some live providers (e.g. `jsmpeg`) may not offer human-accessible means to resume play if it is paused, unless the `auto_play` option is used. |
| `auto_play` | `[selected, visible]` | A list of conditions in which live camera feeds are automatically played. `selected` will automatically play when a camera is selected in a carousel or grid. `visible` will automatically play when a camera becomes visible (e.g. browser tab change, or visible in a grid but not selected). Use an empty list (`[]`) to never automatically play. Some live providers (e.g. `webrtc-card`, `jsmpeg`) do not support the prevention of automatic play on initial load, but should still respect the value of this parameter on play-after-pause. |
| `auto_unmute` | `[microphone]` | A list of conditions in which live camera feeds are unmuted. `selected` will automatically unmute when a camera is selected in a carousel or grid. `visible` will automatically unmute when a camera becomes visible (e.g. a browser/tab change, or visible in a grid but not selected). `microphone` will automatically unmute after the microphone is unmuted. Use an empty list (`[]`) to never automatically unmute. Some browsers will not allow automated unmute until the user has interacted with the page in some way -- if the user has not then the browser may pause the media instead. |
| `controls` | | Configuration for the `live` view controls. See [`controls`](#controls). |
| `display` | | Controls whether to show a single or grid `live` view. See [`display`](#display). |
| `draggable` | `true` | Whether or not the live carousel can be dragged left or right, via touch/swipe and mouse dragging. |
| `lazy_load` | `true` | Whether or not to lazily load cameras in the camera carousel. Setting this to `false` will cause all cameras to load simultaneously when the `live` carousel is opened (or cause all cameras to load continually if `preload` is also `true`). This will result in a smoother carousel experience at a cost of (potentially) a substantial amount of continually streamed data. |
| `lazy_unload` | `[]` | A list of conditions in which live camera feeds are unloaded. `unselected` will unload a camera when it is not visible in the carousel/grid and `hidden` will unload a camera when the browser itself is minimized or the browser tab changes. An empty list (`[]`, the default) will never automatically unload a stream once loaded unless the user navigates away entirely, so that it's always instantly visible on carousel scroll. Once unloaded, subsequently revisiting the camera will cause a reloading delay. Some live providers (e.g. `webrtc-card`) implement their own lazy unloading independently which may occur regardless of the value of this setting. |
| `microphone` | | See [`microphone`](#microphone). |
| `preload` | `false` | Whether or not to preload the live view. Preloading causes the live view to render in the background regardless of what view is actually shown, so it's instantly available when requested. The currently-selected camera's media is loaded in the background; other cameras follow the `lazy_load` setting (set `lazy_load: false` to preload them all). This consumes additional network/CPU resources continually. |
| `show_image_during_load` | `true` | If `true`, during the initial stream load, the `image` live provider will be shown instead of the loading video stream. This still image will auto-refresh and is replaced with the live stream once loaded. |
| `transition_effect` | `slide` | Effect to apply as a transition between live cameras. Accepted values: `slide` or `none`. |
| `zoomable` | `true` | Whether or not the live carousel can be zoomed and panned, via touch/pinch and mouse scroll wheel with `ctrl` held. |
| Option | Default | Description |
| ------------------------ | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actions` | | [Actions](actions/README.md) to use for the `live` view. |
| `auto_mute` | `[unselected, hidden, microphone, call]` | A list of conditions in which live camera feeds are muted. `unselected` will automatically mute when a camera is unselected in the carousel or grid. `hidden` will automatically mute when the camera becomes hidden (e.g. browser tab change). `microphone` will automatically mute after the microphone is muted as long as the camera stays selected (see the `live.microphone.mute_after_microphone_mute_seconds` to control how long after). `call` will automatically mute the inbound audio when a [two-way audio](../usage/2-way-audio.md) call ends. Use an empty list (`[]`) to never automatically mute. Note that if `auto_play` is enabled, the stream may mute itself automatically in order to honor the `auto_play` setting, as some browsers will not auto play media that is unmuted -- that is to say, where necessary, the `auto_play` parameter will take priority over the `auto_mute` parameter. |
| `auto_pause` | `[]` | A list of conditions in which live camera feeds are automatically paused. `unselected` will automatically pause when a camera is unselected in the carousel or grid. `hidden` will automatically pause when the browser/tab becomes hidden. Use an empty list (`[]`) to never automatically pause. **Caution**: Some live providers (e.g. `jsmpeg`) may not offer human-accessible means to resume play if it is paused, unless the `auto_play` option is used. |
| `auto_play` | `[selected, visible]` | A list of conditions in which live camera feeds are automatically played. `selected` will automatically play when a camera is selected in a carousel or grid. `visible` will automatically play when a camera becomes visible (e.g. browser tab change, or visible in a grid but not selected). Use an empty list (`[]`) to never automatically play. Some live providers (e.g. `webrtc-card`, `jsmpeg`) do not support the prevention of automatic play on initial load, but should still respect the value of this parameter on play-after-pause. |
| `auto_unmute` | `[microphone, call]` | A list of conditions in which live camera feeds are unmuted. `selected` will automatically unmute when a camera is selected in a carousel or grid. `visible` will automatically unmute when a camera becomes visible (e.g. a browser/tab change, or visible in a grid but not selected). `microphone` will automatically unmute after the microphone is unmuted. `call` will automatically unmute the inbound audio when a [two-way audio](../usage/2-way-audio.md) call starts, so the caller can be heard immediately. Use an empty list (`[]`) to never automatically unmute. Some browsers will not allow automated unmute until the user has interacted with the page in some way -- if the user has not then the browser may pause the media instead. |
| `controls` | | Configuration for the `live` view controls. See [`controls`](#controls). |
| `display` | | Controls whether to show a single or grid `live` view. See [`display`](#display). |
| `draggable` | `true` | Whether or not the live carousel can be dragged left or right, via touch/swipe and mouse dragging. |
| `lazy_load` | `true` | Whether or not to lazily load cameras in the camera carousel. Setting this to `false` will cause all cameras to load simultaneously when the `live` carousel is opened (or cause all cameras to load continually if `preload` is also `true`). This will result in a smoother carousel experience at a cost of (potentially) a substantial amount of continually streamed data. |
| `lazy_unload` | `[]` | A list of conditions in which live camera feeds are unloaded. `unselected` will unload a camera when it is not visible in the carousel/grid and `hidden` will unload a camera when the browser itself is minimized or the browser tab changes. An empty list (`[]`, the default) will never automatically unload a stream once loaded unless the user navigates away entirely, so that it's always instantly visible on carousel scroll. Once unloaded, subsequently revisiting the camera will cause a reloading delay. Some live providers (e.g. `webrtc-card`) implement their own lazy unloading independently which may occur regardless of the value of this setting. |
| `microphone` | | See [`microphone`](#microphone). |
| `preload` | `false` | Whether or not to preload the live view. Preloading causes the live view to render in the background regardless of what view is actually shown, so it's instantly available when requested. The currently-selected camera's media is loaded in the background; other cameras follow the `lazy_load` setting (set `lazy_load: false` to preload them all). This consumes additional network/CPU resources continually. |
| `show_image_during_load` | `true` | If `true`, during the initial stream load, the `image` live provider will be shown instead of the loading video stream. This still image will auto-refresh and is replaced with the live stream once loaded. |
| `transition_effect` | `slide` | Effect to apply as a transition between live cameras. Accepted values: `slide` or `none`. |
| `zoomable` | `true` | Whether or not the live carousel can be zoomed and panned, via touch/pinch and mouse scroll wheel with `ctrl` held. |
## `controls`
@@ -38,11 +38,28 @@ live:
| Option | Default | Description |
| --------------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| `builtin` | `true` | Whether to show the built in (browser) video controls on live video. |
| `call` | | Configures the on-screen [two-way audio](../usage/2-way-audio.md) call controls. See [`call`](#call). |
| `next_previous` | | Configures how the "Next & Previous" controls are shown on the `live` view. See [`next_previous`](#next_previous). |
| `thumbnails` | | Configures how thumbnails are shown on the `live` view. See [`thumbnails`](#thumbnails). |
| `timeline` | | Configures how the mini-timeline is shown on the `live` view. See [`timeline`](#timeline). |
| `wheel` | `true` | Whether to allow mouse wheel to scroll through the carousel. |
### `call`
Configures the on-screen controls shown during a [two-way audio](../usage/2-way-audio.md) call. The overlay appears whenever a call is in progress and offers buttons to mute/unmute the microphone, mute/unmute the inbound audio, and end the call.
```yaml
live:
controls:
call:
# [...]
```
| Option | Default | Description |
| ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `button_size` | `40` | The size of the call control buttons in pixels. Must be >= `20`. |
| `lock` | `true` | Whether to lock the rest of the card controls/actions while a call is in progress. Prevents an accidental tap, swipe or action mid-call. Set to `false` to allow interactions regardless of call state. |
### `next_previous`
Configures how the "Next & Previous" controls are shown on the live view.
@@ -54,10 +71,11 @@ live:
# [...]
```
| Option | Default | Description |
| ------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `size` | `48` | The size of the next/previous controls in pixels. Must be >= `20`. |
| `style` | `chevrons` | When viewing live cameras, what kind of controls to show to move to the previous/next camera. Acceptable values: `chevrons`, `icons`, `none` . |
| Option | Default | Description |
| ----------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `auto_hide` | `[call, casting]` | The conditions under which the next/previous controls auto-hide: a list of zero or more of `call` (a [two-way audio](../usage/2-way-audio.md) call is active) and `casting` (the card is being cast). Set to `[]` to disable. |
| `size` | `48` | The size of the next/previous controls in pixels. Must be >= `20`. |
| `style` | `chevrons` | When viewing live cameras, what kind of controls to show to move to the previous/next camera. Acceptable values: `chevrons`, `icons`, `none` . |
### `ptz`
@@ -177,14 +195,13 @@ live:
microphone:
```
| Option | Default | Description |
| ------------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `always_connected` | `false` | Whether or not to keep the microphone stream continually connected while the card is running, or only when microphone is used (default). In the latter case there'll be a connection reset when the microphone is first used -- using this option can avoid that reset. |
| `auto_mute` | `[]` | A list of conditions in which the microphone is muted. `unselected` will automatically mute the microphone when a camera is unselected in the carousel or grid. `hidden` will automatically mute the microphone when the card becomes hidden (e.g. browser/tab change). Use an empty list (`[]`, the default) to never automatically mute the microphone via these conditions. |
| `auto_unmute` | `[]` | A list of conditions in which the microphone is unmuted. `selected` will automatically unmute the microphone when a camera is selected in the carousel or grid (useful for an always-hot mic on the currently selected camera). `visible` will automatically unmute when the card becomes visible. Use an empty list (`[]`, the default) to never automatically unmute the microphone via these conditions. The browser will still prompt for microphone permission on first unmute. |
| `disconnect_seconds` | `90` | The number of seconds after microphone usage to disconnect the microphone from the stream. `0` implies never. Not relevant if `always_connected` is `true`. |
| `lock` | `true` | Whether to lock disruptive actions (view/camera/substream changes, pause, reload, casting) while the microphone is unmuted. Prevents an accidental tap, swipe, or button press from cutting off the session mid-sentence during 2-way audio. Set to `false` to allow all actions regardless of microphone state. |
| `mute_after_microphone_mute_seconds` | `60` | The number of seconds after the microphone mutes to automatically mute the inbound audio when `live.auto_mute` includes `microphone`. |
| Option | Default | Description |
| ------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `always_connected` | `false` | Whether or not to keep the microphone stream continually connected while the card is running, or only connect it when first needed (default) -- typically when a [two-way audio](../usage/2-way-audio.md) call is started. In the latter case there'll be a connection reset the first time the microphone connects -- using this option can avoid that reset. |
| `auto_mute` | `[call]` | A list of conditions in which the microphone is muted. `unselected` will automatically mute the microphone when a camera is unselected in the carousel or grid. `hidden` will automatically mute the microphone when the card becomes hidden (e.g. browser/tab change). `call` will automatically mute the microphone when a [two-way audio](../usage/2-way-audio.md) call ends. Use an empty list (`[]`) to never automatically mute the microphone via these conditions. |
| `auto_unmute` | `[]` | A list of conditions in which the microphone is unmuted. `selected` will automatically unmute the microphone when a camera is selected in the carousel or grid. `visible` will automatically unmute when the card becomes visible. `call` will automatically unmute the microphone when a [two-way audio](../usage/2-way-audio.md) call starts. By default this list is empty, so the microphone stays muted when a call starts (push-to-talk) -- tap the microphone button in the call overlay to talk. The microphone is still connected when the call starts (just left muted), so the browser may prompt for microphone permission at that point. |
| `disconnect_seconds` | `90` | The number of seconds after microphone usage to disconnect the microphone from the stream. `0` implies never. Not relevant if `always_connected` is `true`. |
| `mute_after_microphone_mute_seconds` | `60` | The number of seconds after the microphone mutes to automatically mute the inbound audio when `live.auto_mute` includes `microphone`. |
See [Using 2-way audio](../usage/2-way-audio.md) for more information about the very particular requirements that must be followed for 2-way audio to work.
@@ -201,8 +218,11 @@ live:
auto_mute:
- unselected
- hidden
- microphone
- call
auto_unmute:
- microphone
- call
preload: false
lazy_load: true
lazy_unload: []
@@ -211,7 +231,13 @@ live:
transition_effect: slide
controls:
builtin: true
call:
button_size: 40
lock: true
next_previous:
auto_hide:
- call
- casting
style: chevrons
size: 48
wheel: true
@@ -247,10 +273,10 @@ live:
24h: true
microphone:
always_connected: false
auto_mute: []
auto_mute:
- call
auto_unmute: []
disconnect_seconds: 90
lock: true
mute_after_microphone_mute_seconds: 60
display:
mode: single