fix: Release the microphone to the browser when a call ends (#2685)

The microphone is connected when a call needs it and released the moment
that
call ends, so the browser stops reporting it as in use at hangup rather
than
`disconnect_seconds` later.

Existing configurations are migrated automatically by the visual editor.

 - Closes: #2681 

BREAKING CHANGE: `live.microphone.disconnect_seconds` is removed. The
microphone is released when a call ends, so there is no idle countdown
to
configure. Use `live.microphone.always_connected` to hold it open
instead.

BREAKING CHANGE: The `microphone_connect` and `microphone_disconnect`
actions
are removed. The card owns the microphone lifecycle; `microphone_mute`
and
`microphone_unmute` remain.

BREAKING CHANGE: `call` is removed from `live.microphone.auto_mute`,
whose
default is now `[]`. The microphone is muted when a call ends regardless
of
this option.

BREAKING CHANGE: `microphone_unmute` has no effect outside a call.
Nothing
carries the audio at any other time, so the request is ignored rather
than
opening the microphone.
This commit is contained in:
Dermot Duffy authored and GitHub committed 2026-08-14 16:17:31 -07:00
1 parent 65bc52d18e
commit 85d6811761
33 files changed
+1480 -572

No files matched your search

+7 -37
View File
@@ -289,24 +289,6 @@ action: custom:advanced-camera-card-action
advanced_camera_card_action: menu_toggle
```
## `microphone_connect`
Connect the microphone for [2-way audio](../../../usage/2-way-audio.md).
```yaml
action: custom:advanced-camera-card-action
advanced_camera_card_action: microphone_connect
```
## `microphone_disconnect`
Disconnect the microphone during [2-way audio](../../../usage/2-way-audio.md).
```yaml
action: custom:advanced-camera-card-action
advanced_camera_card_action: microphone_disconnect
```
## `microphone_mute`
Mute the microphone during [2-way audio](../../../usage/2-way-audio.md).
@@ -913,48 +895,36 @@ elements:
advanced_camera_card_action: menu_toggle
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-p-circle
title: Microphone connect
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: microphone_connect
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-q-circle
title: Microphone disconnect
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: microphone_disconnect
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-r-circle
title: Microphone mute
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: microphone_mute
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-s-circle
icon: mdi:alpha-q-circle
title: Microphone unmute
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: microphone_unmute
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-t-circle
icon: mdi:alpha-r-circle
title: Mute
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: mute
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-u-circle
icon: mdi:alpha-s-circle
title: Pause
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: pause
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-v-circle
icon: mdi:alpha-t-circle
title: Play
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: play
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-x-circle
icon: mdi:alpha-u-circle
title: Real PTZ Preset
tap_action:
action: custom:advanced-camera-card-action
@@ -962,14 +932,14 @@ elements:
ptz_action: preset
ptz_preset: doorway
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-y-circle
icon: mdi:alpha-v-circle
title: Show PTZ Controls
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: ptz_controls
enabled: true
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alpha-z-circle
icon: mdi:alpha-x-circle
title: Go to precise digital location
tap_action:
action: custom:advanced-camera-card-action
+18 -18
View File
@@ -421,28 +421,28 @@ triggers:
muted: true
```
| Parameter | Description |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `condition` / `trigger` | Must be `microphone`. |
| `connected` | If `true` or `false`, matches when the card does or does not hold an open microphone stream from the browser. See the note below. |
| `muted` | If `true` or `false`, matches when the microphone is muted or unmuted respectively. |
| Parameter | Description |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `condition` / `trigger` | Must be `microphone`. |
| `connected` | If `true` or `false`, matches when the card does or does not hold an open microphone stream from the browser. See the note below. |
| `muted` | If `true` or `false`, matches when the microphone is muted or unmuted respectively. A disconnected microphone counts as muted. See the note below. |
> [!NOTE]
> The `connected` parameter is about **browser microphone access**, not about
> calls. It is `true` while the card holds an open microphone stream from the
> browser -- the same state that lights your browser's "microphone in use"
> indicator (e.g. useful for showing privacy indicators).
> The `connected` parameter is about **browser microphone access**. It is `true`
> while the card holds an open microphone stream from the browser -- the same
> state that lights your browser's "microphone in use" indicator (e.g. useful for
> showing privacy indicators).
>
> A [two-way audio](../usage/2-way-audio.md) call opens the microphone, but so do
> several things that involve no call at all: setting
> [`live.microphone.always_connected`](live.md?id=microphone), or a
> [`microphone_connect`](actions/custom/README.md?id=microphone_connect) or
> [`microphone_unmute`](actions/custom/README.md?id=microphone_unmute) action. It
> closes again after
> [`live.microphone.disconnect_seconds`](live.md?id=microphone) of disuse, or on
> a `microphone_disconnect` action.
> The microphone is connected while a [two-way audio](../usage/2-way-audio.md)
> call is in progress, and closes when that call ends. It is also open for as
> long as the card runs when
> [`live.microphone.always_connected`](live.md?id=microphone) is set.
>
> To match a call in progress, use [`call`](#call) instead.
> `muted` is `true` whenever the microphone is disconnected, so outside a call
> it is always `true`. It is `false` only during a call with the microphone
> unmuted. `muted: false` is therefore the way to match "the user can be heard
> right now"; to match the absence of a call, use [`call`](#call) rather than
> `muted: true`.
## `not`
+7 -10
View File
@@ -222,13 +222,12 @@ 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 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 an answered [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 is started (or answered for inbound calls). By default this list is empty, so the microphone stays muted even after answering (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`. The countdown is suspended for the duration of a [two-way audio](../usage/2-way-audio.md) call, and restarts in full when the call ends. |
| `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 connected while the card is running. By default the microphone is connected when a [two-way audio](../usage/2-way-audio.md) call needs it and disconnected when that call ends. Setting this to `true` connects it at card load and never disconnects it, which avoids the connection setup on the first call at the cost of the browser reporting the microphone as in use for as long as the card is running. |
| `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. The microphone is always muted when a call ends. |
| `auto_unmute` | `[]` | A list of conditions in which the microphone is unmuted. `call` will automatically unmute the microphone when a [two-way audio](../usage/2-way-audio.md) call is started (or answered for inbound calls). `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. By default this list is empty, so the microphone stays muted even after answering (push-to-talk) -- tap the microphone button in the call overlay to talk. Unmuting only has an effect during a call: at any other time nothing can carry the audio, so the request is ignored. |
| `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.
@@ -304,10 +303,8 @@ live:
24h: true
microphone:
always_connected: false
auto_mute:
- call
auto_mute: []
auto_unmute: []
disconnect_seconds: 90
mute_after_microphone_mute_seconds: 60
display:
mode: single