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:
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -62,9 +62,9 @@ note over User, Card
|
||||
end note
|
||||
|
||||
Card --> User : Inbound audio mutes (<color:#43a047>**""live.auto_mute""**</color>)
|
||||
Card -> Mic : Microphone mutes (<color:#43a047>**""live.microphone.auto_mute""**</color>)
|
||||
Card -> Mic : Microphone mutes and disconnects
|
||||
note over Mic
|
||||
Disconnects after <color:#43a047>**""live.microphone.disconnect_seconds""**</color>
|
||||
unless <color:#43a047>**""live.microphone.always_connected""**</color>
|
||||
The browser stops reporting the microphone as in use, unless
|
||||
<color:#43a047>**""live.microphone.always_connected""**</color> holds it open
|
||||
end note
|
||||
@enduml
|
||||
|
||||
@@ -69,16 +69,22 @@ enabled by default and appears in the `live` view whenever the selected camera
|
||||
[`always_connected`](../configuration/live.md?id=microphone) microphone option
|
||||
is set to `true`. On the first call there may be a brief `webrtc` connection
|
||||
reset to include 2-way audio.
|
||||
- The browser asks for microphone permission when a call needs it. How often it
|
||||
asks depends on the browser: Chrome remembers the choice for the site, Safari
|
||||
asks once per page load, and Firefox asks for every call unless _Remember this
|
||||
decision_ is ticked. Set
|
||||
[`always_connected`](../configuration/live.md?id=microphone) to `true` to be
|
||||
asked once at card load instead.
|
||||
- While a call is in progress the card locks disruptive actions (camera and
|
||||
substream changes, casting, reload, etc.) so an accidental tap, swipe, or
|
||||
button press doesn't cut the call off. Set
|
||||
[`live.controls.call.lock`](../configuration/live.md?id=call) to `false` to
|
||||
disable this.
|
||||
- End the call with the overlay's end-call button. When the call ends the
|
||||
microphone and inbound audio are muted again.
|
||||
- The video automatically resets to remove the microphone after the number of
|
||||
seconds specified by [`disconnect_seconds`](../configuration/live.md?id=microphone)
|
||||
have elapsed since the call ended.
|
||||
microphone and inbound audio are muted again, and the microphone is
|
||||
disconnected. The exception is
|
||||
[`always_connected`](../configuration/live.md?id=microphone), which holds the
|
||||
microphone connected for as long as the card is running.
|
||||
|
||||
Calls can also be controlled programmatically with the
|
||||
[`call_start`](../configuration/actions/custom/README.md?id=call_start),
|
||||
|
||||
+33
-33
@@ -51,39 +51,39 @@ To send an action to a specific named Advanced Camera Card:
|
||||
|
||||
Only a subset of all [actions](../configuration/actions/README.md) are supported in URL form.
|
||||
|
||||
| Action | Supported in URL | Explanation |
|
||||
| ------------------------------------------------------------------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `camera_select` | :white_check_mark: | |
|
||||
| `camera_ui` | :white_check_mark: | |
|
||||
| `clip` | :white_check_mark: | |
|
||||
| `clips` | :white_check_mark: | |
|
||||
| `default` | :white_check_mark: | |
|
||||
| `diagnostics` | :white_check_mark: | |
|
||||
| `download` | :heavy_multiplication_x: | Latest media information is not available on initial render. |
|
||||
| `expand` | :white_check_mark: | |
|
||||
| `folder` | :white_check_mark: | |
|
||||
| `folders` | :white_check_mark: | |
|
||||
| `fullscreen` | :heavy_multiplication_x: | Javascript does not support activating fullscreen without direct human interaction. Use `expand` as an alternative. |
|
||||
| `gallery` | :white_check_mark: | |
|
||||
| `image` | :white_check_mark: | |
|
||||
| `live` | :white_check_mark: | |
|
||||
| `media` | :white_check_mark: | |
|
||||
| `media_player` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
|
||||
| `menu_toggle` | :white_check_mark: | |
|
||||
| `microphone_connect`, `microphone_disconnect`, `microphone_mute`, `microphone_unmute` | :heavy_multiplication_x: | |
|
||||
| `mute`, `unmute` | :heavy_multiplication_x: | |
|
||||
| `play`, `pause` | :heavy_multiplication_x: | |
|
||||
| `ptz` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
|
||||
| `recording` | :white_check_mark: | |
|
||||
| `recordings` | :white_check_mark: | |
|
||||
| `review` | :white_check_mark: | |
|
||||
| `reviews` | :white_check_mark: | |
|
||||
| `screenshot` | :heavy_multiplication_x: | Latest media information is not available on initial render. |
|
||||
| `ptz_controls` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
|
||||
| `snapshot` | :white_check_mark: | |
|
||||
| `snapshots` | :white_check_mark: | |
|
||||
| `substream_off` | :white_check_mark: | The `camera` field is not exposed via URL; the selected camera is used. Use the action config directly to target another camera. |
|
||||
| `substream_on` | :white_check_mark: | Pass the substream camera ID as the URL value to engage it directly; omit the value to cycle. |
|
||||
| Action | Supported in URL | Explanation |
|
||||
| -------------------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `camera_select` | :white_check_mark: | |
|
||||
| `camera_ui` | :white_check_mark: | |
|
||||
| `clip` | :white_check_mark: | |
|
||||
| `clips` | :white_check_mark: | |
|
||||
| `default` | :white_check_mark: | |
|
||||
| `diagnostics` | :white_check_mark: | |
|
||||
| `download` | :heavy_multiplication_x: | Latest media information is not available on initial render. |
|
||||
| `expand` | :white_check_mark: | |
|
||||
| `folder` | :white_check_mark: | |
|
||||
| `folders` | :white_check_mark: | |
|
||||
| `fullscreen` | :heavy_multiplication_x: | Javascript does not support activating fullscreen without direct human interaction. Use `expand` as an alternative. |
|
||||
| `gallery` | :white_check_mark: | |
|
||||
| `image` | :white_check_mark: | |
|
||||
| `live` | :white_check_mark: | |
|
||||
| `media` | :white_check_mark: | |
|
||||
| `media_player` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
|
||||
| `menu_toggle` | :white_check_mark: | |
|
||||
| `microphone_mute`, `microphone_unmute` | :heavy_multiplication_x: | |
|
||||
| `mute`, `unmute` | :heavy_multiplication_x: | |
|
||||
| `play`, `pause` | :heavy_multiplication_x: | |
|
||||
| `ptz` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
|
||||
| `recording` | :white_check_mark: | |
|
||||
| `recordings` | :white_check_mark: | |
|
||||
| `review` | :white_check_mark: | |
|
||||
| `reviews` | :white_check_mark: | |
|
||||
| `screenshot` | :heavy_multiplication_x: | Latest media information is not available on initial render. |
|
||||
| `ptz_controls` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
|
||||
| `snapshot` | :white_check_mark: | |
|
||||
| `snapshots` | :white_check_mark: | |
|
||||
| `substream_off` | :white_check_mark: | The `camera` field is not exposed via URL; the selected camera is used. Use the action config directly to target another camera. |
|
||||
| `substream_on` | :white_check_mark: | Pass the substream camera ID as the URL value to engage it directly; omit the value to cycle. |
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
Reference in New Issue
Block a user