Files
linux-voice-assistant/examples/Jabra Speak 410/compose.yml
Omar Amin 2d460b6728 Leds and buttons events (#266)
Use events and commands to control custom onboard leds and buttons. Can be used to communicate with an external Python script via a WebSocket API running in a container alongside LVA.
2026-07-03 19:58:45 +03:00

144 lines
5.5 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
# Jabra Speak 410 – peripheral controller
#
# Runs alongside the linux-voice-assistant container.
# Controls the Jabra Speak 410's LED ring and buttons via USB HID,
# and optionally integrates with PipeWire for volume control and mute detection.
#
# Credit: https://github.com/machineonamission/lva-jabra-speak-410
#
# See hardware notes at the bottom of this file before first run.
services:
jabra-peripheral:
image: ghcr.io/machineonamission/lva-jabra-speak-410:main
container_name: jabra-peripheral
restart: unless-stopped
# -----------------------------------------------------------------------
# USB device access — required for HID LED and button control
# -----------------------------------------------------------------------
devices:
- /dev/bus/usb:/dev/bus/usb
# -----------------------------------------------------------------------
# PipeWire socket — required for mute detection and optional volume control
#
# The mute detect bodge reads from the microphone stream via pw-record to
# detect when the hardware mute engages (all-zero audio = hardware muted).
# Without this, mute/unmute from the Jabra button will not work.
#
# Replace /run/user/1000 with your actual XDG_RUNTIME_DIR if different.
# For the correct path run: echo $XDG_RUNTIME_DIR
# -----------------------------------------------------------------------
volumes:
- /run/user/1000/pipewire-0:/run/user/1000/pipewire-0:ro
- /run/user/1000/pulse:/run/user/1000/pulse:ro
group_add:
- audio
# -----------------------------------------------------------------------
# Environment variables
# -----------------------------------------------------------------------
environment:
- PYTHONUNBUFFERED=1
# LVA peripheral API WebSocket URL.
# If LVA runs on the same host with network_mode: host this default works.
- LVA_WS_URL=ws://localhost:6055
# PipeWire runtime directory — must match the volume mount path above.
- XDG_RUNTIME_DIR=/run/user/1000
- PULSE_SERVER=unix:/run/user/1000/pulse/native
# PipeWire sink for volume control.
# Leave as @DEFAULT_SINK@ or set to a specific sink name.
# Find sink names with: wpctl status
- PW_SINK=@DEFAULT_SINK@
# Volume control mode. Options:
# pipewire – adjust PipeWire volume directly on button press
# (recommended with LVA pipewire volume control PR #272)
# lva – send volume_up / volume_down commands to LVA
# (WARNING: may double-trigger if system also handles HID)
# (unset) – ignore volume button presses entirely
# - VOLUME_CONTROL=pipewire
# -----------------------------------------------------------------------
# Network — host mode so "localhost" reaches the LVA container directly
# -----------------------------------------------------------------------
network_mode: host
healthcheck:
test: ["CMD", "pgrep", "-f", "main.py"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# =============================================================================
# HARDWARE NOTES
# =============================================================================
#
# 1. USB ACCESS — udev rule (recommended)
#
# Add a udev rule on the HOST so the container can access the Jabra device
# without needing additional privileges:
#
# sudo tee /etc/udev/rules.d/99-jabra.rules << 'EOF'
# SUBSYSTEM=="usb", ATTR{idVendor}=="0b0e", MODE="0666", GROUP="plugdev"
# EOF
# sudo udevadm control --reload-rules
# sudo udevadm trigger
#
# Verify the device is visible:
# lsusb | grep 0b0e
#
# 2. PIPEWIRE — required for mute detection
#
# The Jabra Speak 410 does not expose its mute button state over HID when
# not in an active call. As a workaround, the controller reads raw audio
# from PipeWire and detects hardware mute by observing all-zero audio chunks
# (digitally muted audio is impossible in real conditions).
#
# Expose the PipeWire socket from the host to the container as shown in the
# volumes section above. See the LVA audio server documentation for the
# full procedure:
# https://github.com/OHF-Voice/linux-voice-assistant/blob/main/docs/install_audioserver.md
#
# If pw-record is not available inside the container, install wireplumber:
# apt-get install wireplumber
# (already included in the pre-built image)
#
# 3. VOLUME CONTROL
#
# The hidapi library takes full control of the USB HID interface, which
# means external tools like alsa_volume_from_usb_hid will stop working
# while this container is running.
#
# Set VOLUME_CONTROL=pipewire to handle volume buttons via wpctl.
# Set VOLUME_CONTROL=lva to send volume commands to LVA instead.
# Leave unset to ignore volume buttons entirely.
#
# Avoid VOLUME_CONTROL=lva if your system is also processing HID volume
# events at the OS level — this will result in double volume changes.
#
# 4. MICROPHONE INPUT
#
# The Jabra Speak 410 enumerates as a standard USB audio device.
# No driver install is required. Pass it to LVA via:
#
# --audio-input-device "Jabra SPEAK 410"
#
# Or in LVA's compose environment:
# AUDIO_INPUT_DEVICE=Jabra SPEAK 410
#
# =============================================================================