Compare commits

..
Author SHA1 Message Date
nc 61d5d540db Add --unduck-delay to keep music ducked after TTS 2026-10-15 13:47:27 +03:00
43a183a232 Add --music-output-device to route music separately from voice (#350)
* Add --music-output-device to route music separately from voice

Music/media and TTS both play through --audio-output-device today, with no
way to send them to different sinks. Add an optional --music-output-device
(env MUSIC_OUTPUT_DEVICE) that the music player uses instead, defaulting to
--audio-output-device so existing setups are unchanged. Wired through
docker-entrypoint.sh and documented in the README and install docs.

* docs: fix swapped Default/Description columns in env var table

The MIC_VOLUME, MIC_AUTO_GAIN, MIC_NOISE_SUPPRESSION and
AUDIO_INPUT_CHANNELS rows had their Default and Description columns
swapped relative to the table header; fix the ordering and the
'Suppresion' misspelling. Also repair the UNMUTE_SOUND row, whose
description was garbled and which was missing its closing table pipe.

---------

Co-authored-by: Matthew Davis <fedoraproject@virtual.drop.net>
Co-authored-by: Florian Asche <github@florian-asche.de>
Co-authored-by: Omar Amin <65174210+omaramin-2000@users.noreply.github.com>
2026-08-02 23:49:51 +02:00
Florian Asche a2d0a4e68e fix(docker): correct conditional check for DISABLE_PERIPHERAL_API
Fix the syntax error in the shell script where the comparison was
incorrectly structured, and remove the redundant passing of the
variable value to the flag.
2026-08-02 22:58:16 +02:00
Omar Amin b94a5a4663 Documentation Improvements (#385)
* Enhance README
2026-08-02 02:19:05 +02:00
dependabot[bot] 2b0388f454 Bump docker/login-action from 4.5.1 to 4.6.0 (#386)
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.5.1 to 4.6.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/abd2ef45e78c5afb21d64d4ca52ee8550d9572c7...dbcb813823bdd20940b903addbd779551569679f)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 19:42:01 +02:00
mrbubble62 0eafd4f7cd Update Jabra Speak DOCS.md (#387)
Add instructions for installing the Jabra peripheral controller bare metal as a service.
2026-07-31 14:58:12 +03:00
Omar Amin 8a36a74bda Revise Key Components in AGENTS.md
Clarified API server descriptions in AGENTS.md.
2026-07-29 02:38:08 +03:00
florian-asche bf3bf0d942 Update changelog for v1.1.14
This commit was created by changelog-from-release in 'Generate changelog' CI workflow
2026-07-28 00:16:28 +00:00
26 changed files with 279 additions and 89 deletions

No files matched your search

+3
View File
@@ -101,6 +101,9 @@ LVA_PULSE_COOKIE="/run/user/${LVA_USER_ID}/pulse/cookie"
### Delay before mic opens for continued conversation (optional):
# CONTINUE_CONVERSATION_DELAY="0.5"
### Unducking delay (optional)
# UNDUCK_DELAY="1.2"
### Sound files (optional):
# path for custom files in docker is for example "sounds/custom/your_soundfile.flac"
# WAKEUP_SOUND="sounds/wake_word_triggered.flac"
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
echo "REPOSITORY_LOWER=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Log in to the Container registry
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
echo "REPOSITORY_LOWER=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Log in to the Container registry
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v7
- name: Log in to the Container registry
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
+2 -1
View File
@@ -28,7 +28,8 @@
- `linux_voice_assistant/webrtc.py` - WebRTC noise gain/NS processing
- `linux_voice_assistant/mpv_player.py` - MPV-based media player
- `linux_voice_assistant/entity.py` - Entity definitions (MediaPlayer, MuteSwitch, etc.)
- `linux_voice_assistant/api_server.py` - Peripheral WebSocket API server
- `linux_voice_assistant/api_server.py` - ESPHome API server
- `linux_voice_assistant/peripheral_api.py` - Peripheral WebSocket API server
- `linux_voice_assistant/models.py` - Preferences and ServerState dataclasses
## Development Commands
+67
View File
@@ -1,3 +1,68 @@
<a id="v1.1.14"></a>
# [v1.1.14](https://github.com/OHF-Voice/linux-voice-assistant/releases/tag/v1.1.14) - 2026-07-28
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### Exciting New Features 🎉
* Colored Debug Logging and move Voice Event to Info level in logger by [@aryanhasgithub](https://github.com/aryanhasgithub) in [#271](https://github.com/OHF-Voice/linux-voice-assistant/pull/271)
### Other Changes
* build(dev): enhance local development environment and setup workflow by [@florian-asche](https://github.com/florian-asche) in [#358](https://github.com/OHF-Voice/linux-voice-assistant/pull/358)
* docs(github): establish repository governance and automation workflows by [@florian-asche](https://github.com/florian-asche) in [#359](https://github.com/OHF-Voice/linux-voice-assistant/pull/359)
* Bump docker/build-push-action from 5.3.0 to 7.3.0 by [@dependabot](https://github.com/dependabot)[bot] in [#364](https://github.com/OHF-Voice/linux-voice-assistant/pull/364)
* Bump actions/attest-build-provenance from 1 to 4 by [@dependabot](https://github.com/dependabot)[bot] in [#363](https://github.com/OHF-Voice/linux-voice-assistant/pull/363)
* Bump docker/metadata-action from 5.5.1 to 6.2.0 by [@dependabot](https://github.com/dependabot)[bot] in [#362](https://github.com/OHF-Voice/linux-voice-assistant/pull/362)
* Bump docker/setup-qemu-action from 3 to 4 by [@dependabot](https://github.com/dependabot)[bot] in [#361](https://github.com/OHF-Voice/linux-voice-assistant/pull/361)
* Bump docker/login-action from 3.1.0 to 4.4.0 by [@dependabot](https://github.com/dependabot)[bot] in [#360](https://github.com/OHF-Voice/linux-voice-assistant/pull/360)
* chore(ci): update github actions and docker dependencies by [@florian-asche](https://github.com/florian-asche) in [#368](https://github.com/OHF-Voice/linux-voice-assistant/pull/368)
* fix Respeaker USB Mic Array v2 LEDs by [@litinoveweedle](https://github.com/litinoveweedle) in [#357](https://github.com/OHF-Voice/linux-voice-assistant/pull/357)
* Update install.md - Fixed log path by [@maximilianovermeyer](https://github.com/maximilianovermeyer) in [#372](https://github.com/OHF-Voice/linux-voice-assistant/pull/372)
* Bump docker/setup-buildx-action from 3 to 4 by [@dependabot](https://github.com/dependabot)[bot] in [#371](https://github.com/OHF-Voice/linux-voice-assistant/pull/371)
* fix race condition between LVA registration to the HA and peripheral … by [@litinoveweedle](https://github.com/litinoveweedle) in [#373](https://github.com/OHF-Voice/linux-voice-assistant/pull/373)
* Bump actions/checkout from 4 to 7 by [@dependabot](https://github.com/dependabot)[bot] in [#370](https://github.com/OHF-Voice/linux-voice-assistant/pull/370)
* feat(ai): integrate Kilo agent framework and coding instructions by [@florian-asche](https://github.com/florian-asche) in [#366](https://github.com/OHF-Voice/linux-voice-assistant/pull/366)
* Bump docker/login-action from 4.4.0 to 4.5.0 by [@dependabot](https://github.com/dependabot)[bot] in [#375](https://github.com/OHF-Voice/linux-voice-assistant/pull/375)
* docs: add realtime scheduling tuning for constrained hardware Closes [#164](https://github.com/OHF-Voice/linux-voice-assistant/issues/164) by [@SpiliosDimakopoulos](https://github.com/SpiliosDimakopoulos) in [#376](https://github.com/OHF-Voice/linux-voice-assistant/pull/376)
* Bump docker/login-action from 4.5.0 to 4.5.1 by [@dependabot](https://github.com/dependabot)[bot] in [#377](https://github.com/OHF-Voice/linux-voice-assistant/pull/377)
## New Contributors
* [@dependabot](https://github.com/dependabot)[bot] made their first contribution in [#364](https://github.com/OHF-Voice/linux-voice-assistant/pull/364)
* [@litinoveweedle](https://github.com/litinoveweedle) made their first contribution in [#357](https://github.com/OHF-Voice/linux-voice-assistant/pull/357)
* [@maximilianovermeyer](https://github.com/maximilianovermeyer) made their first contribution in [#372](https://github.com/OHF-Voice/linux-voice-assistant/pull/372)
* [@SpiliosDimakopoulos](https://github.com/SpiliosDimakopoulos) made their first contribution in [#376](https://github.com/OHF-Voice/linux-voice-assistant/pull/376)
**Full Changelog**: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.13...v1.1.14
[Changes][v1.1.14]
<a id="v1.1.13"></a>
# [v1.1.13](https://github.com/OHF-Voice/linux-voice-assistant/releases/tag/v1.1.13) - 2026-07-18
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### Exciting New Features 🎉
* (Temporary workaround) Switch between MWW/OWW models from the UI by [@omaramin-2000](https://github.com/omaramin-2000) in [#348](https://github.com/OHF-Voice/linux-voice-assistant/pull/348)
* Leds and buttons events by [@omaramin-2000](https://github.com/omaramin-2000) in [#266](https://github.com/OHF-Voice/linux-voice-assistant/pull/266)
* Add Tests For LVA by [@aryanhasgithub](https://github.com/aryanhasgithub) in [#312](https://github.com/OHF-Voice/linux-voice-assistant/pull/312)
* feat: add --listen-during-wake-sound argument by [@wangwillian0](https://github.com/wangwillian0) in [#273](https://github.com/OHF-Voice/linux-voice-assistant/pull/273)
### Other Changes
* perf(player): limit cache to 32 MiB by [@florian-asche](https://github.com/florian-asche) in [#309](https://github.com/OHF-Voice/linux-voice-assistant/pull/309)
* Allow using python versions above 3.11 by [@omaramin-2000](https://github.com/omaramin-2000) in [#345](https://github.com/OHF-Voice/linux-voice-assistant/pull/345)
* Modify USB control transfer settings in respeaker_usb_mic_array.py by [@omaramin-2000](https://github.com/omaramin-2000) in [#349](https://github.com/OHF-Voice/linux-voice-assistant/pull/349)
* Broadcast entity state to all API clients; don't desync on a second connection by [@JSRossie](https://github.com/JSRossie) in [#329](https://github.com/OHF-Voice/linux-voice-assistant/pull/329)
* Fix lint_mypy by [@omaramin-2000](https://github.com/omaramin-2000) in [#352](https://github.com/OHF-Voice/linux-voice-assistant/pull/352)
## New Contributors
* [@JSRossie](https://github.com/JSRossie) made their first contribution in [#329](https://github.com/OHF-Voice/linux-voice-assistant/pull/329)
* [@wangwillian0](https://github.com/wangwillian0) made their first contribution in [#273](https://github.com/OHF-Voice/linux-voice-assistant/pull/273)
**Full Changelog**: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.12...v1.1.13
[Changes][v1.1.13]
<a id="v1.1.12"></a>
# [v1.1.12](https://github.com/OHF-Voice/linux-voice-assistant/releases/tag/v1.1.12) - 2026-06-22
@@ -299,6 +364,8 @@ Initial release
[Changes][v1.0.0]
[v1.1.14]: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.13...v1.1.14
[v1.1.13]: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.12...v1.1.13
[v1.1.12]: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.11...v1.1.12
[v1.1.11]: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.10...v1.1.11
[v1.1.10]: https://github.com/OHF-Voice/linux-voice-assistant/compare/v1.1.9...v1.1.10
+4 -3
View File
@@ -19,7 +19,7 @@ Because it runs on a full Linux system and offers access significantly more loca
- Supports multiple wake words and languages
- Supports multiple architectures (linux/amd64 and linux/aarch64)
- Automated builds with artifact attestation for security
- Supports announcments, start/continue conversation, and timers
- Supports [announcments](https://www.home-assistant.io/actions/assist_satellite.announce/), [start](https://www.home-assistant.io/actions/assist_satellite.start_conversation/)/continue conversation, and timers
- Tested and works with Python 3.11 and Python 3.13.
- Prebuild docker image available on [GitHub Container Registry](https://github.com/OHF-Voice/linux-voice-assistant/pkgs/container/linux-voice-assistant)
- Prebuild [Raspberry Pi image](https://github.com/florian-asche/PiCompose)
@@ -74,7 +74,7 @@ For all other users, we have different installation methods available (Docker, s
💡 **Note:** There is an [environment variable](docs/install_application.md#environment-variables-reference) for each parameter if you use docker or systemd based setup.
```sh
usage: __main__.py [-h] [--name NAME] [--audio-input-device AUDIO_INPUT_DEVICE] [--list-input-devices] [--audio-input-block-size AUDIO_INPUT_BLOCK_SIZE] [--audio-output-device AUDIO_OUTPUT_DEVICE] [--list-output-devices] [--wake-word-dir WAKE_WORD_DIR] [--mic-auto-gain] [--mic-noise-suppression]
usage: __main__.py [-h] [--name NAME] [--audio-input-device AUDIO_INPUT_DEVICE] [--list-input-devices] [--audio-input-block-size AUDIO_INPUT_BLOCK_SIZE] [--audio-output-device AUDIO_OUTPUT_DEVICE] [--music-output-device MUSIC_OUTPUT_DEVICE] [--list-output-devices] [--wake-word-dir WAKE_WORD_DIR] [--mic-auto-gain] [--mic-noise-suppression]
[--wake-model WAKE_MODEL] [--stop-model STOP_MODEL] [--download-dir DOWNLOAD_DIR] [--refractory-seconds REFRACTORY_SECONDS] [--wakeup-sound WAKEUP_SOUND] [--timer-finished-sound TIMER_FINISHED_SOUND] [--processing-sound PROCESSING_SOUND]
[--mute-sound MUTE_SOUND] [--unmute-sound UNMUTE_SOUND] [--preferences-file PREFERENCES_FILE] [--host HOST] [--network-interface NETWORK_INTERFACE] [--port PORT] [--enable-thinking-sound] [--listen-during-wake-sound] [--debug]
```
@@ -85,6 +85,7 @@ usage: __main__.py [-h] [--name NAME] [--audio-input-device AUDIO_INPUT_DEVICE]
| `--audio-input-device` | Soundcard name for input device | Autodetected |
| `--audio-input-block-size` | Audio input block size in samples | 1024 |
| `--audio-output-device` | mpv name for output device | Autodetected |
| `--music-output-device` | mpv name for the music/media output device | `--audio-output-device` |
| `--mic-volume` | Control microphone volume | 100 |
| `--mic-auto-gain` | Add WebRTC Gain to Mic | 0 |
| `--mic-noise-suppression` | Add WebRTC Noise Suppression to Mic | 0 |
@@ -116,7 +117,7 @@ usage: __main__.py [-h] [--name NAME] [--audio-input-device AUDIO_INPUT_DEVICE]
| `--colored-debug` | Print colored DEBUG messages to console | False |
| `--output-only` | Enable output only mode | False |
💡 **Note:** There is a detailed explanation on the gain, noise suppression, and wake word sensitivity flags in the [audio options](docs/audio_options.md) file.
💡 **Note:** There are detailed explanations on the controlled entities from device page in the [configuration](docs/configuration.md) file.
## Build Information
+10 -2
View File
@@ -44,6 +44,10 @@ if [ -n "${AUDIO_OUTPUT_DEVICE}" ]; then
EXTRA_ARGS+=( "--audio-output-device" "$AUDIO_OUTPUT_DEVICE" )
fi
if [ -n "${MUSIC_OUTPUT_DEVICE}" ]; then
EXTRA_ARGS+=( "--music-output-device" "$MUSIC_OUTPUT_DEVICE" )
fi
if [ -n "${MIC_VOLUME}" ]; then
EXTRA_ARGS+=( "--mic-volume" "$MIC_VOLUME" )
fi
@@ -88,6 +92,10 @@ if [ -n "${CONTINUE_CONVERSATION_DELAY}" ]; then
EXTRA_ARGS+=( "--continue-conversation-delay" "$CONTINUE_CONVERSATION_DELAY" )
fi
if [ -n "${UNDUCK_DELAY}" ]; then
EXTRA_ARGS+=( "--unduck-delay" "$UNDUCK_DELAY" )
fi
if [ -n "${WAKEUP_SOUND}" ]; then
EXTRA_ARGS+=( "--wakeup-sound" "$WAKEUP_SOUND" )
fi
@@ -128,8 +136,8 @@ if [ -n "${PERIPHERAL_VOLUME_STEP}" ]; then
EXTRA_ARGS+=( "--peripheral-volume-step" "$PERIPHERAL_VOLUME_STEP" )
fi
if [ -n "$DISABLE_PERIPHERAL_API" = "1" ]; then
EXTRA_ARGS+=( "--disable-peripheral-api" "$DISABLE_PERIPHERAL_API" )
if [ "$DISABLE_PERIPHERAL_API" = "1" ]; then
EXTRA_ARGS+=( "--disable-peripheral-api" )
fi
if [ "$ENABLE_OUTPUT_ONLY" = "1" ]; then
-73
View File
@@ -1,73 +0,0 @@
# Audio Options: Gain, Noise Suppression, and Wake Word Sensitivity
## What do Gain and Noise Suppression do
### Gain
When you change gain, LVA(using the [webrtc](https://github.com/OHF-Voice/webrtc-noise-gain) library) automatically adjusts the microphone input volume to keep it at a consistent level. If you're speaking quietly it boosts the signal, if you're speaking loudly it reduces it. Useful in the following ways:-
- Microphones that are too quiet by default
- Environments where you move around relative to the mic
- Keeping wake word detection consistent regardless of speaking volume
### Noise Suppression
When you change noise suppression, LVA(using the [webrtc](https://github.com/OHF-Voice/webrtc-noise-gain) library) filters out constant background noise from the audio signal. It works by learning what "silence" sounds like in your environment and subtracting that from the audio. Useful in the following ways:
- Noisy environments
- Improving STT accuracy by sending cleaner audio to Home Assistant
- Reducing false wake word triggers from background noise
## Using Gain and Noise Suppression with LVA
LVA implements gain and Noise Suppression in two ways:
- [CLI Argument/ENV file](#cli-argumentenv-file)
- [Home Assistant Entity](#home-assistant-entity)
### CLI Argument/ENV file
#### CLI Argument
Using docker-entrypoint.sh the following flags can be used to set gain and noise suppression:
- `--mic-auto-gain`(ranges from 0-31)
- `--mic-noise-suppression`(ranges from 0-4)
#### ENV file
You can add/edit these variables in the .env file to set gain and noise suppression:
- `MIC_AUTO_GAIN="0"`
- `MIC_NOISE_SUPPRESSION="0"`
### Home Assistant Entity
LVA exposes two slider entities to change these gain and noise suppression from which you can edit the gain and noise suppression at runtime.
💡 **Note:** Setting the flag and ENV values to 0 turns them off and are not used.
💡 **Note:** Keep in mind that when the flags are set they will overwrite the previous value in the preferences file and also they will be overridden if the value is changed in Home Assistant(Also applies to the ENV file but the ENV file will always overwrite the last value on startup).
## Wake Word Sensitivity
LVA exposes three numeric controls in the Home Assistant device page for fine-grained sensitivity tuning. These let you dial in the exact probability threshold that best matches your microphone quality, room acoustics, and false-activation tolerance.
| Entity | Description | Default |
|--------|-------------|---------|
| **Wake Word 1 Sensitivity** | Probability cutoff for the primary wake word | From model manifest |
| **Wake Word 2 Sensitivity** | Probability cutoff for the secondary wake word (if active) | From model manifest |
| **Stop Word Sensitivity** | Probability cutoff for the stop word | From model manifest |
Values range from `0.0` to `1.0`:
- **Higher value** (e.g. `0.95`) → more selective, fewer false activations, may miss quieter or accented speech
- **Lower value** (e.g. `0.50`) → more responsive, but more likely to trigger on similar-sounding words
The defaults are read directly from each model's `.json` manifest file (the `probability_cutoff` field), so bundled models like `okay_nabu` (0.85), `hey_jarvis` (0.97), and custom downloaded models all start at their author-tested baseline. Changes made in the Home Assistant UI are persisted in `preferences.json` and survive restarts.
**Tuning guide:**
- If the wake word **rarely activates** (misses your voice): lower the value slightly, e.g. by `0.05` steps
- If the wake word **activates too often** (false triggers from TV, music, or similar words): raise the value slightly
- Start from the model's default and make small adjustments — a change of `0.05–0.10` is usually enough to notice a difference
- Far-field microphones with noise cancellation (e.g. ReSpeaker, Satellite1) generally work well at the default values; basic USB microphones may need a lower threshold
+130
View File
@@ -0,0 +1,130 @@
# Dashboard / Home Assistant Entities
Once your satellite is connected, Home Assistant exposes a set of controls on its device page (via the ESPHome integration) that let you change LVA's behavior at runtime, without restarting the container or editing config files. This document walks through each of those entities.
> **Go to [Settings > Devices & services](https://my.home-assistant.io/redirect/integrations/) and select the ESPHome integration.**
![Device page overview](./images/overview.png)
## Wake Word
The device page exposes one or two wake word selects (**Wake Word 1**, **Wake Word 2**), depending on whether your assistant is configured for dual wake words. Changing the selection here takes effect immediately and is persisted to `preferences.json`, so it survives restarts.
![Wake word select](./images/wake_word.png)
💡 **Note:** Models suffixed with **(OWW)** in the dropdown are [openWakeWord](https://github.com/dscripka/openWakeWord) models; everything else is a [microWakeWord](https://github.com/kahrendt/microWakeWord) model. Both engines can be mixed and matched, but keep in mind:
- **microWakeWord** models are lighter-weight and use engine that can run on lower-end devices and are located in the `wakewords` directory.
- **openWakeWord** models use higher engine with more accuracy and are located in the `wakewords/openWakeWord` directory.
See the [Wake Word section](install_application.md#wake-word) of the installation guide for the full list of bundled models and how to add custom ones.
## Mute Switch
The **Mute** switch disables wake word detection and stops the assistant from responding to any wake word or button-triggered listening, without stopping the LVA process itself. While muted, a configurable sound plays to confirm the mute/unmute transition (`--mute-sound` / `--unmute-sound`).
![Mute Switch](./images/mute_switch.png)
## Thinking Sound
The **Thinking Sound** switch toggles whether a short audible chime plays while the assistant is processing your request (between the end of listening and the start of the response). This is the same setting as the `--enable-thinking-sound` CLI flag / `ENABLE_THINKING_SOUND` environment variable, but can be flipped on or off at runtime from this switch. The change is saved to `preferences.json`.
![Thinking Sound](./images/thinking_sound.png)
## Media Player
The **Media Player** entity controls playback (play/pause/stop) and volume for both:
- Music/media played through the satellite, and
- The assist pipeline itself (wake word chime, TTS responses, thinking/processing sound, etc.)
Both share a single volume control — there is no separate volume for the pipeline versus music playback. Adjusting the volume slider on this entity changes both at once, and the value is persisted to `preferences.json` so it's restored on the next startup.
![Media player entity](images/media_player.png)
## Microphone Settings
### Volume
Controls the microphone volume to adjust the area distance from which the microphone can pick up your voice. The volume slider is persisted to `preferences.json` so it's restored on the next startup.
![Mic Volume](./images/mic_volume.png)
### What do Gain and Noise Suppression do
#### Gain
When you change gain, LVA(using the [webrtc](https://github.com/OHF-Voice/webrtc-noise-gain) library) automatically adjusts the microphone input volume to keep it at a consistent level. If you're speaking quietly it boosts the signal, if you're speaking loudly it reduces it. Useful in the following ways:-
- Microphones that are too quiet by default
- Environments where you move around relative to the mic
- Keeping wake word detection consistent regardless of speaking volume
#### Noise Suppression
When you change noise suppression, LVA(using the [webrtc](https://github.com/OHF-Voice/webrtc-noise-gain) library) filters out constant background noise from the audio signal. It works by learning what "silence" sounds like in your environment and subtracting that from the audio. Useful in the following ways:
- Noisy environments
- Improving STT accuracy by sending cleaner audio to Home Assistant
- Reducing false wake word triggers from background noise
### Using Gain and Noise Suppression with LVA
LVA implements gain and Noise Suppression in two ways:
- [CLI Argument/ENV file](#cli-argumentenv-file)
- [Home Assistant Entity](#home-assistant-entity)
### CLI Argument/ENV file
#### CLI Argument
Using docker-entrypoint.sh the following flags can be used to set gain and noise suppression:
- `--mic-auto-gain`(ranges from 0-31)
- `--mic-noise-suppression`(ranges from 0-4)
#### ENV file
You can add/edit these variables in the .env file to set gain and noise suppression:
- `MIC_AUTO_GAIN="0"`
- `MIC_NOISE_SUPPRESSION="0"`
### Home Assistant Entity
LVA exposes two entities to change these gain and noise suppression from which you can edit them at runtime.
- ![Mic Gain](./images/mic_gain.png)
- ![Mic Noise Suppresion](./images/mic_nosie_suppression.png)
💡 **Note:** Setting the flag and ENV values to 0 turns them off and are not used.
💡 **Note:** Keep in mind that when the flags are set they will overwrite the previous value in the preferences file and also they will be overridden if the value is changed in Home Assistant(Also applies to the ENV file but the ENV file will always overwrite the last value on startup).
### Wake Word Sensitivity
LVA exposes three numeric controls in the Home Assistant device page for fine-grained sensitivity tuning. These let you dial in the exact probability threshold that best matches your microphone quality, room acoustics, and false-activation tolerance.
| Entity | Description | Default |
|--------|-------------|---------|
| **Wake Word 1 Sensitivity** ![WW 1 Sensitivity](./images/wake_word_sensitivity.png) | Probability cutoff for the primary wake word | From model manifest |
| **Wake Word 2 Sensitivity** ![WW 2 Sensitivity](./images/wake_word_sensitivity_2.png) | Probability cutoff for the secondary wake word (if active) | From model manifest |
| **Stop Word Sensitivity** ![alt text](./images/stop_word_sensitivity.png) | Probability cutoff for the stop word | From model manifest |
Values range from `0.0` to `1.0`:
- **Higher value** (e.g. `0.95`) → more selective, fewer false activations, may miss quieter or accented speech
- **Lower value** (e.g. `0.50`) → more responsive, but more likely to trigger on similar-sounding words
The defaults are read directly from each model's `.json` manifest file (the `probability_cutoff` field), so bundled models like `okay_nabu` (0.85), `hey_jarvis` (0.97), and custom downloaded models all start at their author-tested baseline. Changes made in the Home Assistant UI are persisted in `preferences.json` and survive restarts.
**Tuning guide:**
- If the wake word **rarely activates** (misses your voice): lower the value slightly, e.g. by `0.05` steps
- If the wake word **activates too often** (false triggers from TV, music, or similar words): raise the value slightly
- Start from the model's default and make small adjustments — a change of `0.05–0.10` is usually enough to notice a difference
- Far-field microphones with noise cancellation (e.g. ReSpeaker, Satellite1) generally work well at the default values; basic USB microphones may need a lower threshold
## Support
If a dashboard control doesn't behave as expected, enable `--debug` (or `ENABLE_DEBUG=1`) and check the logs — every change made from the Home Assistant device page is logged when it's received and persisted.
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+12 -6
View File
@@ -176,6 +176,7 @@ Environment=PREFERENCES_FILE="/home/pi/linux-voice-assistant/preferences.json"
# Environment=PORT="6053"
# Environment=AUDIO_INPUT_DEVICE="default"
# Environment=AUDIO_OUTPUT_DEVICE="default"
# Environment=MUSIC_OUTPUT_DEVICE="default"
# Environment=MIC_VOLUME="1.0"
# Environment=MIC_AUTO_GAIN="0"
# Environment=MIC_NOISE_SUPPRESSION="0"
@@ -269,10 +270,11 @@ The following variables can be configured in the `.env` or in the service file:
| `PORT` | `6053` | API server port |
| `AUDIO_INPUT_DEVICE` | Autodetected | Audio input device name |
| `AUDIO_OUTPUT_DEVICE` | Autodetected | Audio output device name |
| `MIC_VOLUME` | Control microphone volume | 100 |
| `MIC_AUTO_GAIN` | Add WebRTC Gain to Mic | 0 |
| `MIC_NOISE_SUPPRESSION` | Add WebRTC Noise Suppresion to Mic | 0 |
| `AUDIO_INPUT_CHANNELS` | Number of audio input channels | 2 |
| `MUSIC_OUTPUT_DEVICE` | `AUDIO_OUTPUT_DEVICE` | Music/media output device name (defaults to the voice output device) |
| `MIC_VOLUME` | 100 | Control microphone volume |
| `MIC_AUTO_GAIN` | 0 | Add WebRTC Gain to Mic |
| `MIC_NOISE_SUPPRESSION` | 0 | Add WebRTC Noise Suppression to Mic |
| `AUDIO_INPUT_CHANNELS` | 2 | Number of audio input channels |
| `ENABLE_THINKING_SOUND` | false | Set to "1" to enable thinking sound |
| `WAKE_WORD_DIR` | `app/wakewords` | Path to the wake word directory |
| `WAKE_MODEL` | `okay_nabu` | Wake word model to use |
@@ -286,7 +288,7 @@ The following variables can be configured in the `.env` or in the service file:
| `PROCESSING_SOUND` | `sounds/processing.wav` | Sound file for processing state |
| `LISTEN_DURING_WAKE_SOUND` | false | Set to "1" to start listening immediately after wake word detection, without waiting for the wake sound to finish |
| `MUTE_SOUND` | `sounds/mute_switch_on.flac` | Sound file for mute on |
| `UNMUTE_SOUND` | `sounds/mute_switch_off.flac` | Sound file for Configure Audio Devices
| `UNMUTE_SOUND` | `sounds/mute_switch_off.flac` | Sound file for mute off |
| `PERIPHERAL_HOST` | 0.0.0.0 | Host for the peripheral WebSocket API |
| `PERIPHERAL_PORT` | 6055 | Port for the peripheral WebSocket API |
| `PERIPHERAL_VOLUME_STEP` | %(default)s | Volume change per button press |
@@ -314,6 +316,8 @@ If you want to use your own sounds, you can add them to the `sounds/custom` aka
### Wake Word:
💡 **Note:** The active wake word(s) can also be changed at runtime from the Home Assistant device page, without editing `.env` or restarting LVA — see [Wake Word](configuration.md#wake-word) in the dashboard documentation.
#### Available Wake Word Models:
The following wake word models are available:
@@ -326,7 +330,6 @@ The following wake word models are available:
- `hey_morgan` - Morgan wake word
- `hey_luna` - Luna wake word
- `hey_home_assistant` - Home Assistant wake word
- `stop` - Stop wake word
- `okay_computer` - Okay Computer wake word
- `choo_choo_homie` - Choo Choo Homie wake word
@@ -337,6 +340,9 @@ The following wake word models are available:
- `hey_mycroft` - Mycroft wake word
- `hey_rhasspy` - Rhasspy wake word
### Stop Word:
The `stop` wake word is used to stop the current process (response, announcement, or timer). It is available in the `wakewords` directory (using the microWakeWord engine) and can be referenced in the `.env` file with `STOP_MODEL=stop`.
### Custom Wake Word:
+30
View File
@@ -153,7 +153,37 @@ export XDG_RUNTIME_DIR=/run/user/1000
export PULSE_SERVER=unix:/run/user/1000/pulse/native
python main.py
```
To make it persistent across reboots
```
mkdir -p ~/.config/systemd/user/
nano ~/.config/systemd/user/jabra-lva.service
```
```
[Unit]
Description=Jabra Speak 410 LVA Controller
After=network.target pipewire.service
[Service]
Type=simple
WorkingDirectory=%h/linux-voice-assistant/examples/Jabra Speak 410
ExecStart=%h/linux-voice-assistant/venv/bin/python main.py
Restart=always
RestartSec=5
Environment="VOLUME_CONTROL=pipewire"
Environment="LVA_WS_URL=ws://localhost:6055"
Environment="XDG_RUNTIME_DIR=/run/user/1000"
Environment="PULSE_SERVER=unix:/run/user/1000/pulse/native"
[Install]
WantedBy=default.target
```
Enable and start service
```
systemctl --user daemon-reload
systemctl --user enable jabra-lva
systemctl --user start jabra-lva
```
---
## Configuration
+12 -1
View File
@@ -66,6 +66,10 @@ async def main() -> None:
"--audio-output-device",
help="Name for the audio output device (see --list-output-devices)",
)
parser.add_argument(
"--music-output-device",
help="mpv name for the music/media output device (defaults to --audio-output-device)",
)
parser.add_argument(
"--list-output-devices",
action="store_true",
@@ -114,6 +118,12 @@ async def main() -> None:
default=0.5,
help="Seconds to wait after TTS finishes before opening the mic for continued conversation (default: 0.5)",
)
parser.add_argument(
"--unduck-delay",
type=float,
default=0.0,
help="Seconds to keep music ducked after TTS finishes (default: 0.0)",
)
parser.add_argument(
"--wakeup-sound",
default=str(_SOUNDS_DIR / "wake_word_triggered.flac"),
@@ -419,7 +429,7 @@ async def main() -> None:
wake_words=wake_models,
active_wake_words=active_wake_words,
stop_word=stop_model,
music_player=MpvMediaPlayer(device=args.audio_output_device),
music_player=MpvMediaPlayer(device=args.music_output_device or args.audio_output_device),
tts_player=MpvMediaPlayer(device=args.audio_output_device),
wakeup_sound=args.wakeup_sound,
start_listening_sound=args.start_listening_sound,
@@ -434,6 +444,7 @@ async def main() -> None:
preferences_path=preferences_path,
refractory_seconds=args.refractory_seconds,
continue_conversation_delay=args.continue_conversation_delay,
unduck_delay=args.unduck_delay,
output_only=args.output_only,
download_dir=args.download_dir,
volume=initial_volume,
+1
View File
@@ -124,6 +124,7 @@ class ServerState:
preferences_path: Path
download_dir: Path
continue_conversation_delay: float = 0.5 # seconds to wait after TTS before opening mic
unduck_delay: float = 0.0 # seconds to keep music ducked after TTS ends
media_player_entity: "Optional[MediaPlayerEntity]" = None
satellite: "Optional[VoiceSatelliteProtocol]" = None
+5
View File
@@ -957,6 +957,11 @@ class VoiceSatelliteProtocol(APIServer):
threading.Timer(self.state.continue_conversation_delay, _start_continued_conversation).start()
else:
self._continue_conversation = False
unduck_delay = self.state.unduck_delay
if unduck_delay > 0:
_LOGGER.debug("Unducking after %.2fs", unduck_delay)
threading.Timer(unduck_delay, self.unduck).start()
else:
self.unduck()
self._emit(LVAEvent.IDLE)