Skip to content
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM python:3.13-slim-trixie

ENV LANG=C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
apt-get install --yes --no-install-recommends \
avahi-utils alsa-utils libportaudio2 portaudio19-dev \
build-essential libmpv-dev pulseaudio

WORKDIR /srv
COPY . ./
RUN ./script/setup

ENTRYPOINT ["./script/run"]
32 changes: 32 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: "3.8"
services:
linux-voice-assistant:
build: .
image: ohf/linux-voice-assistant:local
container_name: linux-voice-assistant
restart: unless-stopped
devices:
- "/dev/snd:/dev/snd"
group_add:
- audio
environment:
- FIXED_MAC_ADDRESS=device_mac_address
# - XDG_RUNTIME_DIR=/run/user/1000
# - PULSE_SERVER=unix:/run/user/1000/pulse/native
- AUDIO_OUTPUT_DEVICE=default
volumes:
- ./config:/app/.config
- ./wakewords:/app/wakewords
- ./sounds:/app/sounds
# - /var/run/pulse/native:/var/run/pulse/native
# - /run/user/1000:/run/user/1000
ports:
- "6053:6053"
tty: true
command:
- "--name"
- "voice-satellite"
- "--audio-input-device"
- "default"
- "--wake-model"
- "hey_jarvis"
5 changes: 5 additions & 0 deletions linux_voice_assistant/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ async def main() -> None:
parser.add_argument(
"--timer-finished-sound", default=str(_SOUNDS_DIR / "timer_finished.flac")
)
parser.add_argument(
"--processing-sound", default=str(_SOUNDS_DIR / "processing.wav"),
help="Short sound to play while assistant is processing (thinking)"
)
#
parser.add_argument("--preferences-file", default=_REPO_DIR / "preferences.json")
#
Expand Down Expand Up @@ -184,6 +188,7 @@ async def main() -> None:
tts_player=MpvMediaPlayer(device=args.audio_output_device),
wakeup_sound=args.wakeup_sound,
timer_finished_sound=args.timer_finished_sound,
processing_sound=args.processing_sound,
preferences=preferences,
preferences_path=preferences_path,
libtensorflowlite_c_path=libtensorflowlite_c_path,
Expand Down
1 change: 1 addition & 0 deletions linux_voice_assistant/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class ServerState:
music_player: "MpvMediaPlayer"
tts_player: "MpvMediaPlayer"
wakeup_sound: str
processing_sound: str
timer_finished_sound: str
preferences: Preferences
preferences_path: Path
Expand Down
10 changes: 10 additions & 0 deletions linux_voice_assistant/satellite.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def __init__(self, state: ServerState) -> None:
self._tts_played = False
self._continue_conversation = False
self._timer_finished = False
self._processing = False

def handle_voice_event(
self, event_type: VoiceAssistantEventType, data: Dict[str, str]
Expand All @@ -75,6 +76,15 @@ def handle_voice_event(
self._tts_url = data.get("url")
self._tts_played = False
self._continue_conversation = False
elif event_type == VoiceAssistantEventType.VOICE_ASSISTANT_INTENT_START:
# Play short "thinking/processing" sound if configured
processing = getattr(self.state, "processing_sound", None)
if processing:
_LOGGER.debug("Playing processing sound: %s", processing)
self.state.stop_word.is_active = True
self._processing = True
self.duck()
self.state.tts_player.play(self.state.processing_sound)
elif event_type in (
VoiceAssistantEventType.VOICE_ASSISTANT_STT_VAD_END,
VoiceAssistantEventType.VOICE_ASSISTANT_STT_END,
Expand Down
6 changes: 6 additions & 0 deletions linux_voice_assistant/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@
import uuid
from collections.abc import Callable
from typing import Optional
import os


def get_mac() -> str:
# Check for fixed MAC in environment variable
mac_env = os.getenv("FIXED_MAC_ADDRESS")
if mac_env:
return mac_env.lower()
# Fallback to uuid.getnode()
mac = uuid.getnode()
mac_str = ":".join(f"{(mac >> i) & 0xff:02x}" for i in range(40, -1, -8))
return mac_str
Expand Down
Binary file added sounds/processing.wav
Binary file not shown.
Binary file added sounds/timer_finished_old.wav
Binary file not shown.
Binary file added sounds/wake_word_triggered_old.wav
Binary file not shown.