diff --git a/docs/install_pipewire.md b/docs/install_pipewire.md new file mode 100644 index 0000000..a5d8541 --- /dev/null +++ b/docs/install_pipewire.md @@ -0,0 +1,92 @@ +> +> Install Pipewire On Your Linux Voice Satellite +> + + +## 1. Connect to your Pi over SSH using the username/password you configured during flashing: + +```sh +ssh @ +``` + + +## 2. If already installed Disable/Stop the entire the Linux Voice Assistant service. If not installed, proceed to step (3.): + +```sh +sudo systemctl disable --now linux-voice-assistant.service +sudo rm /etc/systemd/system/linux-voice-assistant.service +``` + + +## 3. Install Pipewire packages and necessary PulseAudio utilities: + +```sh +sudo apt-get update +sudo apt-get install \ + pulseaudio-utils \ + pipewire wireplumber \ + pipewire-audio libspa-0.2-modules +``` + + +## 4. Reboot your Pi: + +```sh +sudo reboot -h now +``` + + +## 5. SSH back in to your Pi. (See step 1.) + + +## 6. Ensure Pipewire is runnining in user mode. + +```sh +systemctl --user status pipewire.service +systemctl --user status pipewire-pulse.service + +``` + + +## 7. (OPTIONAL) If plugging speakers into the headphone jack of the ReSpeaker, set the correct PulseAudio Sink Port: + +Run `pactl list sinks` and scroll to the bottom and notice your Active Port is probably "analog-output-speaker". Run the command below to output audio through the 3.5mm headphone jack. + +```sh +pactl set-sink-port alsa_output.platform-soc_sound.stereo-fallback "analog-output-headphones" +``` + +**Please note that if you are setting this up on a Raspberry Pi 3B or 4B, you need an additional step at this point to make it route the audio through the 2mic hat (and likely the 4mic one as well). Run the following command to do this.** + +```sh +pactl set-default-sink alsa_output.platform-soc_sound.stereo-fallback +``` + + +## 8. Test and make sure you can hear the wav file.: + +```sh +mpv --ao=pipewire --audio-device=default --audio-samplerate=44100 /usr/share/sounds/alsa/Front_Center.wav +``` + +If volume is low, set it to 150%. + +```sh +pactl set-sink-volume alsa_output.platform-soc_sound.stereo-fallback 150% +``` + +**Note that if you have a Raspbery Pi 3B or 4B, this may or may not seem to work, but it will output on the hat as intended.** + + +## 9. Reboot your Pi: (see step 4) + + +## 10. Done! Return to the tutorial to continue the Linux Voice Assistant install. + + + + + + + + diff --git a/docs/install_pulseaudio.md b/docs/install_pulseaudio.md new file mode 100644 index 0000000..c8893a5 --- /dev/null +++ b/docs/install_pulseaudio.md @@ -0,0 +1,239 @@ +## Install PulseAudio On Your Wyoming Voice Satellite + +> Courtesy of https://github.com/FutureProofHomes/wyoming-enhancements/blob/master/snapcast/docs/2_install_pulseaudio.md with minor modifications + +## 1. Connect to your Pi over SSH using the username/password you configured during flashing: + +```sh +ssh @ +``` + + +## 2. If already installed Disable/Stop the entire the Linux Voice Assistant service temporarily. If not installed, proceed to step (3.): + +```sh +sudo systemctl disable --now linux-voice-assistant.service +``` + + +## 3. Install PulseAudio drivers and necessary utilities: + +```sh +sudo apt-get update +sudo apt-get install \ + pulseaudio \ + pulseaudio-utils \ + pamixer +``` + + +## 4. Reboot your Pi: + +```sh +sudo reboot -h now +``` + + +## 5. SSH back in to your Pi. (See step 1.) + + +## 6. Ensure PulseAudio is runnining in "system-wide mode". Per the [official instructions](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/) we first need to stop some existing services to be safe: + +```sh +sudo systemctl --global disable pulseaudio.service pulseaudio.socket +``` + + +## 7. It is also advisable to set `autospawn = no` in `/etc/pulse/client.conf`: + +```sh +sudo sed -i.bak \ + -e '$a### Disable autospawn' \ + -e '$aautospawn = no' \ + /etc/pulse/client.conf +``` + + +## 8. Create the `PulseAudio.service`: + +```sh +sudo cp ~/linux-voice-assistant/service/pulseaudio.service /etc/systemd/system/pulseaudio.service +``` + + +## 9. Start the `PulseAudio.service`. This will require you to type in your password a couple times. + +```sh +systemctl --system enable pulseaudio.service +``` + +```sh +systemctl --system start pulseaudio.service +``` + + +## 10. Ensure pi user is in the `pulse-access` group: +***If you aren't using the default "pi" user, put your user in here instead of "pi".*** +```sh +sudo sed -i '/^pulse-access:/ s/$/root,pi/' /etc/group +``` + + +## 11. Reboot your Pi: (see step 4) + + +## 12. (OPTIONAL) If plugging speakers into the headphone jack of the ReSpeaker, set the correct PulseAudio Sink Port: + +Run `pactl list sinks` and scroll to the bottom and notice your Active Port is probably "analog-output-speaker". Run the command below to output audio through the 3.5mm headphone jack. + +```sh +pactl set-sink-port 1 "analog-output-headphones" +``` + +**Please note that if you are setting this up on a Raspberry Pi 3B or 4B, you need an additional step at this point to make it route the audio through the 2mic hat (and likely the 4mic one as well). Run the following command to do this.** + +```sh +pactl set-default-sink alsa_output.platform-soc_sound.stereo-fallback +``` + + +## 13. Test and make sure you can hear the wav file.: + +```sh +paplay /usr/share/sounds/alsa/Front_Center.wav +``` + +**Note that if you have a Raspbery Pi 3B or 4B, this may or may not seem to work, but it will output on the hat as intended.** + + +## 14. The following modifications are specifically required for LVA's mpv_player.py to work with PA. If you do not have a working PA at this point, do not proceed.: +Backup current PA daemon.conf file. + +```bash +sudo cp /etc/pulse/daemon.conf{,.bak.$(date +%s)} +``` + +Update the PA /etc/pulse/daemon.conf file with required change. Replaces if present (commented or not). + +```bash +sudo sed -i -E \ + -e 's|^[#;[:space:]]*exit-idle-time\s*=.*$|exit-idle-time = -1|' \ + -e 's|^[#;[:space:]]*resample-method\s*=.*$|resample-method = trivial|' \ + -e 's|^[#;[:space:]]*flat-volumes\s*=.*$|flat-volumes = no|' \ + -e 's|^[#;[:space:]]*default-sample-rate\s*=.*$|default-sample-rate = 44100|' \ + -e 's|^[#;[:space:]]*alternate-sample-rate\s*=.*$|alternate-sample-rate = 48000|' \ + -e 's|^[#;[:space:]]*default-fragment-size-msec\s*=.*$|default-fragment-size-msec = 15|' \ + /etc/pulse/daemon.conf +``` + +Just in case the values were missing, may not be needed but shouldn't hurt. + +```bash +for kv in \ + 'exit-idle-time = -1' \ + 'resample-method = trivial' \ + 'flat-volumes = no' \ + 'default-sample-rate = 44100' \ + 'alternate-sample-rate = 48000' \ + 'default-fragment-size-msec = 15'; do + k="${kv%% =*}" + sudo grep -Eq "^[[:space:]]*${k}[[:space:]]*=" /etc/pulse/daemon.conf || echo "$kv" | sudo tee -a /etc/pulse/daemon.conf >/dev/null +done +``` + +Backup current PA system.pa file. + +```bash +sudo cp /etc/pulse/system.pa{,.bak.$(date +%s)} +``` + +Update the PA /etc/pulse/system.pa file with required change. Replaces if present (commented or not). + +```bash +sudo sed -i -E \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-udev-detect)([[:space:]].*)?$|\1 tsched=0|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-native-protocol-unix.*)$|\1|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-default-device-restore.*)$|\1|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-always-sink.*)$|\1|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-position-event-sounds.*)$|\1|' \ + /etc/pulse/system.pa +``` + +Just in case the values were missing, may not be needed but shouldn't hurt. + +```bash +for m in \ + 'load-module module-native-protocol-unix' \ + 'load-module module-default-device-restore' \ + 'load-module module-always-sink' \ + 'load-module module-position-event-sounds'; do + sudo grep -Eq "^[[:space:]]*$m(\s|$)" /etc/pulse/system.pa || echo "$m" | sudo tee -a /etc/pulse/system.pa >/dev/null +done +``` + +Backup current PA default.pa file. + +```bash +sudo cp /etc/pulse/default.pa{,.bak.$(date +%s)} +``` + +Update the PA /etc/pulse/default.pa file with required change. Replaces if present (commented or not). + +```bash +sudo sed -i -E \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-udev-detect)([[:space:]].*)?$|\1 tsched=0|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-native-protocol-unix.*)$|\1|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-default-device-restore.*)$|\1|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-always-sink.*)$|\1|' \ + -e 's|^[#;[:space:]]*(load-module[[:space:]]+module-intended-roles.*)$|\1|' \ + /etc/pulse/default.pa +``` + +Just in case the values were missing, may not be needed but shouldn't hurt. + +```bash +for m in \ + 'load-module module-native-protocol-unix' \ + 'load-module module-default-device-restore' \ + 'load-module module-always-sink' \ + 'load-module module-intended-roles'; do + sudo grep -Eq "^[[:space:]]*$m(\s|$)" /etc/pulse/default.pa || echo "$m" | sudo tee -a /etc/pulse/default.pa >/dev/null +done +``` + +Optional since LVA handles duck/unduck: if you enabled role-ducking explicitly in system.pa, you can comment it out with: + +```bash +sudo sed -i -E 's|^([[:space:]]*)load-module[[:space:]]+module-role-ducking\b|# \0|' /etc/pulse/system.pa +``` +## 15. Restart PA and verify + +```bash +sudo systemctl restart pulseaudio.service +``` + +Test mpv can ouput to PA with current configs: + +```bash +mpv --ao=pulse --audio-device=default --audio-samplerate=44100 /usr/share/sounds/alsa/Front_Center.wav +``` + +If you disabled your Linux Voice Assistant service in step 2., enable it now: + +```bash +sudo systemctl enable --now linux-voice-assistant.service +``` + +## 16. Reboot your Pi: (see step 4) + + +## 17. Done! Return to the tutorial to continue the Linux Voice Assistant install. + + + + + + + + + diff --git a/docs/linux-voice-assistant-2mic-install.md b/docs/linux-voice-assistant-2mic-install.md new file mode 100644 index 0000000..da3ee4a --- /dev/null +++ b/docs/linux-voice-assistant-2mic-install.md @@ -0,0 +1,302 @@ +# Linux Voice Assistant on RaspberryPi with ReSpeaker 2‑Mic — Installation & Configuration Guide + +> Created using ChatGPT 5 with the following prompt: +```html + Using the following github document as a guide + https://github.com/rhasspy/wyoming-satellite/blob/master/docs/tutorial_2mic.md, + take the attached bash history of commands and create a similar document + detailing the installation and configuration of this linux-voice-assistant project. +``` +> Modeled after the Wyoming Satellite two‑mic tutorial, adapted from actual shell history. + +This guide reproduces a working setup of the **linux-voice-assistant** project with **Wyoming OpenWakeWord** or **MicroWakeWord** on a Raspberry PI Zero 2W and a Respeaker 2‑mic HAT (e.g., seeed-2mic-voicecard). It assumes a fresh system with sudo access and the default "pi" user. Included is the option to use PipeWire or PulseAudio instead of ALSA. + +## Prerequisites +- Raspberry Pi OS Lite (64-bit) + - Linux 6.12.34+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.12.34-1+rpt1~bookworm + - (2025-06-26) aarch64 GNU/Linux +- Default Python 3.11+ recommended +- A ReSpeaker 2‑mic sound card or compatable +- Network access to your Home Assistant instance + + +## 1. Install system packages + +```bash +sudo apt update +sudo apt upgrade +sudo apt install libportaudio2 build-essential git \ + libmpv-dev mpv python3.11-dev avahi-daemon avahi-utils +sudo reboot +``` + + +## 2. Get the code + +```bash +git clone https://github.com/imonlinux/linux-voice-assistant.git +``` + + +## 3. Install ReSpeaker drivers + +```bash +chmod +x ~/linux-voice-assistant/respeaker2mic/install-respeaker-drivers.sh +sudo ~/linux-voice-assistant/respeaker2mic/install-respeaker-drivers.sh +sudo reboot +``` + + +## 4. Wyoming OpenWakeWord (OWW), skip to step 5. if using MicroWakeWord (MWW) + + +```bash +git clone https://github.com/rhasspy/wyoming-openwakeword.git +``` + +```bash +cp ~/linux-voice-assistant/wyoming-openwakeword/requirements.txt ~/wyoming-openwakeword/requirements.txt +cd wyoming-openwakeword/ +script/setup +``` + + +## 5. Linux Voice Assistant (LVA) + +```bash +cd ~/linux-voice-assistant/ +script/setup +``` + + +## 6. Choose your install option "Choose your Adventure!" + +Pick **one** of the following install paths. Expand a section to see the exact steps. + +> Tip: PipeWire options run services in *user* mode (requires `loginctl enable-linger`); PulseAudio/ALSA options run services in *system* mode. + +
+PipeWire + OpenWakeWord (user-mode services) + +**Prep (PipeWire):** Follow the PipeWire tutorial first: [the tutorial](install_pipewire.md). + +**Enable linger (required for user services to start after reboot):** +```bash +sudo loginctl enable-linger pi +``` + +**Install user-mode services:** +```bash +mkdir -p ~/.config/systemd/user + +# LVA +cp ~/linux-voice-assistant/service/user-pw-oww-linux-voice-assistant.service.service ~/.config/systemd/user/linux-voice-assistant.service + +# OWW +cp ~/linux-voice-assistant/service/user-wyoming-openwakeword.service.service ~/.config/systemd/user/wyoming-openwakeword.service +``` + +**Enable & start:** +```bash +systemctl --user daemon-reload +systemctl --user enable --now wyoming-openwakeword.service +systemctl --user enable --now linux-voice-assistant.service +``` + +**Verify:** +```bash +systemctl --user status linux-voice-assistant wyoming-openwakeword --no-pager -l +``` +
+ +
+PipeWire + MicroWakeWord (user-mode services) + +**Prep (PipeWire):** Follow the PipeWire tutorial first: [the tutorial](install_pipewire.md). + +**Enable linger:** +```bash +sudo loginctl enable-linger pi +``` + +**Install user-mode service:** +```bash +mkdir -p ~/.config/systemd/user +cp ~/linux-voice-assistant/service/user-pw-mww-linux-voice-assistant.service.service ~/.config/systemd/user/linux-voice-assistant.service +``` + +**Enable & start:** +```bash +systemctl --user daemon-reload +systemctl --user enable --now linux-voice-assistant.service +``` + +**Verify:** +```bash +systemctl --user status linux-voice-assistant --no-pager -l +``` +
+ +
+PulseAudio + OpenWakeWord (system services) + +**Prep (PulseAudio):** Follow the PulseAudio tutorial first: [the tutorial](install_pulseaudio.md). + +**Install LVA (system) + tuning drop-in:** +```bash +sudo cp ~/linux-voice-assistant/service/pa-oww-linux-voice-assistant.service /etc/systemd/system/linux-voice-assistant.service + +sudo mkdir -p /etc/systemd/system/linux-voice-assistant.service.d +sudo cp ~/linux-voice-assistant/service/10-tuning.conf /etc/systemd/system/linux-voice-assistant.service.d/10-tuning.conf +``` + +**Install OWW (system):** +```bash +sudo cp ~/linux-voice-assistant/service/wyoming-openwakeword.service /etc/systemd/system/wyoming-openwakeword.service +``` + +**Enable & start:** +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now wyoming-openwakeword linux-voice-assistant +sudo systemctl status linux-voice-assistant wyoming-openwakeword --no-pager -l +``` +
+ +
+PulseAudio + MicroWakeWord (system services) + +**Prep (PulseAudio):** Follow the PulseAudio tutorial first: [the tutorial](install_pulseaudio.md). + +**Install LVA (system) + tuning drop-in:** +```bash +sudo cp ~/linux-voice-assistant/service/pa-mww-linux-voice-assistant.service /etc/systemd/system/linux-voice-assistant.service + +sudo mkdir -p /etc/systemd/system/linux-voice-assistant.service.d +sudo cp ~/linux-voice-assistant/service/10-tuning.conf /etc/systemd/system/linux-voice-assistant.service.d/10-tuning.conf +``` + +**Enable & start:** +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now linux-voice-assistant +sudo systemctl status linux-voice-assistant --no-pager -l +``` +
+ +
+ALSA + OpenWakeWord (system services) + +**No extra audio stack needed.** If you’re using a different sound card/driver, confirm device names: +```bash +arecord -l +aplay -l +``` + +**Install LVA (system):** +```bash +sudo cp ~/linux-voice-assistant/service/alsa-oww-linux-voice-assistant.service /etc/systemd/system/linux-voice-assistant.service +``` + +**Install OWW (system):** +```bash +sudo cp ~/linux-voice-assistant/service/wyoming-openwakeword.service /etc/systemd/system/wyoming-openwakeword.service +``` + +**Enable & start:** +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now wyoming-openwakeword linux-voice-assistant +sudo systemctl status linux-voice-assistant wyoming-openwakeword --no-pager -l +``` +
+ +
+ALSA + MicroWakeWord (system services) + +**No extra audio stack needed.** If you’re using a different sound card/driver, confirm device names: +```bash +arecord -l +aplay -l +``` + +**Install LVA (system):** +```bash +sudo cp ~/linux-voice-assistant/service/alsa-mww-linux-voice-assistant.service /etc/systemd/system/linux-voice-assistant.service +``` + +**Enable & start:** +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now linux-voice-assistant +sudo systemctl status linux-voice-assistant --no-pager -l +``` +
+ +
+Optional: Advertise LVA to Home Assistant via Avahi + +**Generate & install ESPHome-style mDNS service:** +```bash +chmod +x ~/linux-voice-assistant/script/gen-esphome-avahi.sh +sudo ~/linux-voice-assistant/script/gen-esphome-avahi.sh +sudo systemctl restart avahi-daemon.service +``` +
+ + +## 7. Connect to Home Assistant + +### If HA does not discover the new LVA: + +1. In Home Assistant, go to "Settings" -> "Device & services" +2. Click the "Add integration" button +3. Choose "ESPHome" and then "Set up another instance of ESPHome" +4. Enter the IP address of your voice satellite with port 6053 +5. Click "Submit" +6. During the registration process, use the wake word that you configured in your linux-voice-assistant.service file. Default is "alexa". + + +## 8. Verification +- Use "journalctl -u linux-voice-assistant.service -f" to check for errors for ALSA and PluseAudio. Debugging is enabled. +- Use "journalctl --user -u linux-voice-assistant.service -f" to check for errors when using PipeWire. Debugging is enabled. + - Expect logs like `Connected to Home Assistant` + - Look for `[OWW] Detection: name=...` followed by re-arming/cycling + - Ask: *“What time is it?”* and confirm TTS reply +- If you do not get a voice response, check the Voice Assistant that you choose during registration has a voice assigned to it. + + ### Settings -> Voice assistants -> Assist (the assistant you configured) -> Text-to-speech -> Voice + + +## 9. Change OWW detection model + +After the LVA is registered with HA, you can change the Wake Word model used in the ESPHome Voice Assistant entity. + +Project OWW models include: + +```text +alexa_v0.1.tflite -> Alexa +hey_jarvis_v0.1.tflite -> Hey Jarvis +hey_mycroft_v0.1.tflite -> Hey Mycroft +hey_rhasspy_v0.1.tflite -> Hey Rhasspy +ok_nabu_v0.1.tflite -> OK Nabo **(I had to say OK Nobu)** +``` + +Additional community provided OWW models available from this repository: +https://github.com/fwartner/home-assistant-wakewords-collection + +You just copy the ones you want into the ~/wyoming-openwakeword/wyoming-openwakeword/models directory. If a model is currupted, the wyoming-openwakeword.service will fail to start. + +**Word of warning. I have had problems with some of the community provided wake words. YMMV** + + +## 10. Switching between OWW and MWW. Or ALSA, PW, PA see section 6. + +If you intend to switch from PA to ALSA, you must first stop the pusleaudio.service. + +```bash +sudo systemctl stop pulseaudio.service +``` +```bash +sudo systemctl disable pulseaudio.service +``` diff --git a/respeaker2mic/install-respeaker-drivers.sh b/respeaker2mic/install-respeaker-drivers.sh new file mode 100644 index 0000000..4e7ff22 --- /dev/null +++ b/respeaker2mic/install-respeaker-drivers.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# Installs drivers for the ReSpeaker 2mic and 4mic HATs on Raspberry Pi OS. +# Must be run with sudo. +# Requires: curl raspberrypi-kernel-headers dkms i2c-tools libasound2-plugins alsa-utils + +set -eo pipefail + +kernel_formatted="$(uname -r | cut -f1,2 -d.)" +driver_url_status="$(curl -ILs https://github.com/HinTak/seeed-voicecard/archive/refs/heads/v$kernel_formatted.tar.gz | tac | grep -o "^HTTP.*" | cut -f 2 -d' ' | head -1)" + +if [ ! "$driver_url_status" = 200 ]; then +echo "Could not find driver for kernel $kernel_formatted" +exit 1 +fi + +apt-get update +apt-get install --no-install-recommends --yes \ + curl raspberrypi-kernel-headers dkms i2c-tools libasound2-plugins alsa-utils + +temp_dir="$(mktemp -d)" + +function finish { + rm -rf "${temp_dir}" +} + +trap finish EXIT + +pushd "${temp_dir}" + +# Download source code to temporary directory +# NOTE: There are different branches in the repo for different kernel versions. +echo 'Downloading source code' +curl -L -o - "https://github.com/HinTak/seeed-voicecard/archive/refs/heads/v$kernel_formatted.tar.gz" | \ + tar -xzf - + +cd seeed-voicecard-"$kernel_formatted"/ + +# 1. Build kernel module +echo 'Building kernel module' +ver='0.3' +mod='seeed-voicecard' +src='./' +kernel="$(uname -r)" +marker='0.0.0' +threads="$(getconf _NPROCESSORS_ONLN)" +memory="$(LANG=C free -m|awk '/^Mem:/{print $2}')" + +if [ "${memory}" -le 512 ] && [ "${threads}" -gt 2 ]; then +threads=2 +fi + +mkdir -p "/usr/src/${mod}-${ver}" +cp -a "${src}"/* "/usr/src/${mod}-${ver}/" + +dkms add -m "${mod}" -v "${ver}" +dkms build -k "${kernel}" -m "${mod}" -v "${ver}" -j "${threads}" && { + dkms install --force -k "${kernel}" -m "${mod}" -v "${ver}" +} + +mkdir -p "/var/lib/dkms/${mod}/${ver}/${marker}" + +# 2. Install kernel module and configure +echo 'Updating boot configuration' +config='/boot/config.txt' + +cp seeed-*-voicecard.dtbo /boot/overlays +grep -q "^snd-soc-ac108$" /etc/modules || echo "snd-soc-ac108" >> /etc/modules +sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' "${config}" +echo "dtoverlay=i2s-mmap" >> "${config}" +echo "dtparam=i2s=on" >> "${config}" +mkdir -p /etc/voicecard +cp *.conf *.state /etc/voicecard +cp seeed-voicecard /usr/bin/ +cp seeed-voicecard.service /lib/systemd/system/ +systemctl enable --now seeed-voicecard.service + +echo 'Done. Please reboot the system.' +popd diff --git a/service/10-avahi.conf b/service/10-avahi.conf new file mode 100644 index 0000000..dc5ca11 --- /dev/null +++ b/service/10-avahi.conf @@ -0,0 +1,3 @@ +[Unit] +Wants=avahi-daemon.service +After=avahi-daemon.service diff --git a/service/10-tuning.conf b/service/10-tuning.conf new file mode 100644 index 0000000..b5dc628 --- /dev/null +++ b/service/10-tuning.conf @@ -0,0 +1,8 @@ +# /etc/systemd/system/linux-voice-assistant.service.d/10-tuning.conf +[Service] +# Keep mpv logs at warning by default; override with environment if desired +Environment=LVA_MPV_MSG_LEVEL=all=warn + +# Faster, cleaner shutdowns +TimeoutStopSec=5s +KillMode=mixed diff --git a/service/alsa-mww-linux-voice-assistant.service b/service/alsa-mww-linux-voice-assistant.service new file mode 100644 index 0000000..ed5e5fd --- /dev/null +++ b/service/alsa-mww-linux-voice-assistant.service @@ -0,0 +1,27 @@ +[Unit] +Description=Linux Voice Assistant (ALSA - ReSpeaker 2mic HAT) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=pi +Group=pi +WorkingDirectory=/home/pi/linux-voice-assistant + +Environment=PYTHONUNBUFFERED=1 + +# Use ALSA ReSpeaker 2mic HAT hardware device +Environment="MPV_DEFAULT_DEVICE=alsa/plughw:CARD=seeed2micvoicec,DEV=0" + +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite ALSA MWW' \ + --audio-input-device default \ + --audio-output-device ${MPV_DEFAULT_DEVICE} \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/service/alsa-oww-linux-voice-assistant.service b/service/alsa-oww-linux-voice-assistant.service new file mode 100644 index 0000000..3466db7 --- /dev/null +++ b/service/alsa-oww-linux-voice-assistant.service @@ -0,0 +1,31 @@ +[Unit] +Description=Linux Voice Assistant (ALSA - ReSpeaker 2mic HAT) +After=network-online.target wyoming-openwakeword.service +Wants=network-online.target +Requires=wyoming-openwakeword.service + +[Service] +Type=simple +User=pi +Group=pi +WorkingDirectory=/home/pi/linux-voice-assistant + +Environment=PYTHONUNBUFFERED=1 + +# Use ALSA ReSpeaker 2mic HAT hardware device +Environment="MPV_DEFAULT_DEVICE=alsa/plughw:CARD=seeed2micvoicec,DEV=0" + +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite ALSA OWW' \ + --audio-input-device default \ + --audio-output-device ${MPV_DEFAULT_DEVICE} \ + --wake-uri 'tcp://127.0.0.1:10400' \ + --wake-word-name 'alexa' \ + --wake-models-dir '/home/pi/wyoming-openwakeword/wyoming_openwakeword/models' + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/service/pa-mww-linux-voice-assistant.service b/service/pa-mww-linux-voice-assistant.service new file mode 100644 index 0000000..3548e3c --- /dev/null +++ b/service/pa-mww-linux-voice-assistant.service @@ -0,0 +1,33 @@ +[Unit] +Description=Linux Voice Assistant (PulseAudio - Headphone Jack) +After=network-online.target pulseaudio.service +Wants=network-online.target +Requires=pulseaudio.service + +[Service] +Type=simple +User=pi +Group=pi +WorkingDirectory=/home/pi/linux-voice-assistant + +# Environment +Environment=PYTHONUNBUFFERED=1 +Environment="PULSE_SERVER=unix:/var/run/pulse/native" +Environment="PULSE_LATENCY_MSEC=60" +Environment="MPV_DEFAULT_DEVICE=pulse/alsa_output.platform-soc_sound.stereo-fallback" + +# Wait briefly for the Pulse native socket to be ready +ExecStartPre=/bin/sh -c 'for i in $(seq 1 40); do [ -S /var/run/pulse/native ] && exit 0; sleep 0.5; done; echo "PulseAudio socket not found" >&2; exit 1' + +# Launch the assistant +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite PA MWW' \ + --audio-input-device default \ + --audio-output-device ${MPV_DEFAULT_DEVICE} \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/service/pa-oww-linux-voice-assistant.service b/service/pa-oww-linux-voice-assistant.service new file mode 100644 index 0000000..20712fb --- /dev/null +++ b/service/pa-oww-linux-voice-assistant.service @@ -0,0 +1,36 @@ +[Unit] +Description=Linux Voice Assistant (PulseAudio - Headphone Jack) +After=network-online.target pulseaudio.service wyoming-openwakeword.service +Wants=network-online.target +Requires=pulseaudio.service wyoming-openwakeword.service + +[Service] +Type=simple +User=pi +Group=pi +WorkingDirectory=/home/pi/linux-voice-assistant + +# Environment +Environment=PYTHONUNBUFFERED=1 +Environment="PULSE_SERVER=unix:/var/run/pulse/native" +Environment="PULSE_LATENCY_MSEC=60" +Environment="MPV_DEFAULT_DEVICE=pulse/alsa_output.platform-soc_sound.stereo-fallback" + +# Wait briefly for the Pulse native socket to be ready +ExecStartPre=/bin/sh -c 'for i in $(seq 1 40); do [ -S /var/run/pulse/native ] && exit 0; sleep 0.5; done; echo "PulseAudio socket not found" >&2; exit 1' + +# Launch the assistant +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite PA OWW' \ + --audio-input-device default \ + --audio-output-device ${MPV_DEFAULT_DEVICE} \ + --wake-uri 'tcp://127.0.0.1:10400' \ + --wake-word-name 'alexa' \ + --wake-models-dir '/home/pi/wyoming-openwakeword/wyoming_openwakeword/models' \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/service/pulseaudio.service b/service/pulseaudio.service new file mode 100644 index 0000000..174bf60 --- /dev/null +++ b/service/pulseaudio.service @@ -0,0 +1,9 @@ +[Unit] +Description=PulseAudio system server + +[Service] +Type=notify +ExecStart=pulseaudio --daemonize=no --system --realtime --log-target=journal + +[Install] +WantedBy=multi-user.target diff --git a/service/user-pa-mww-linux-voice-assistant.service.service b/service/user-pa-mww-linux-voice-assistant.service.service new file mode 100644 index 0000000..359bef2 --- /dev/null +++ b/service/user-pa-mww-linux-voice-assistant.service.service @@ -0,0 +1,21 @@ +[Unit] +Description=Linux Voice Assistant (PulseAudio + MWW) +After=pulseaudio.service +Wants=pulseaudio.service + +[Service] +Type=simple +WorkingDirectory=/home/pi/linux-voice-assistant +Environment=PYTHONUNBUFFERED=1 + +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite PA' \ + --audio-input-device default \ + --audio-output-device pulse/alsa_output.platform-soc_sound.stereo-fallback \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=default.target diff --git a/service/user-pa-oww-linux-voice-assistant.service.service b/service/user-pa-oww-linux-voice-assistant.service.service new file mode 100644 index 0000000..64b1ffa --- /dev/null +++ b/service/user-pa-oww-linux-voice-assistant.service.service @@ -0,0 +1,26 @@ +[Unit] +Description=Linux Voice Assistant (PulseAudio + OWW) +After=pulseaudio.service wyoming-openwakeword.service +Wants=pulseaudio.service wyoming-openwakeword.service +Requires=wyoming-openwakeword.service +After=wyoming-openwakeword.service + +[Service] +Type=simple +WorkingDirectory=/home/pi/linux-voice-assistant +Environment=PYTHONUNBUFFERED=1 + +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite PA' \ + --audio-input-device default \ + --audio-output-device pulse/alsa_output.platform-soc_sound.stereo-fallback \ + --wake-uri 'tcp://127.0.0.1:10400' \ + --wake-word-name 'alexa' \ + --wake-models-dir '/home/pi/wyoming-openwakeword/wyoming_openwakeword/models' \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=default.target diff --git a/service/user-pw-mww-linux-voice-assistant.service.service.service b/service/user-pw-mww-linux-voice-assistant.service.service.service new file mode 100644 index 0000000..31ecb86 --- /dev/null +++ b/service/user-pw-mww-linux-voice-assistant.service.service.service @@ -0,0 +1,21 @@ +[Unit] +Description=Linux Voice Assistant (PipeWire + MWW) +After=pipewire.service pipewire-pulse.service +Wants=pipewire-pulse.service + +[Service] +Type=simple +WorkingDirectory=/home/pi/linux-voice-assistant +Environment=PYTHONUNBUFFERED=1 + +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite PW MWW' \ + --audio-input-device default \ + --audio-output-device pipewire/default \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=default.target diff --git a/service/user-pw-oww-linux-voice-assistant.service.service b/service/user-pw-oww-linux-voice-assistant.service.service new file mode 100644 index 0000000..1d1623b --- /dev/null +++ b/service/user-pw-oww-linux-voice-assistant.service.service @@ -0,0 +1,26 @@ +[Unit] +Description=Linux Voice Assistant (PipeWire + OWW) +After=pipewire.service pipewire-pulse.service wyoming-openwakeword.service +Wants=pipewire-pulse.service wyoming-openwakeword.service +Requires=wyoming-openwakeword.service +After=wyoming-openwakeword.service + +[Service] +Type=simple +WorkingDirectory=/home/pi/linux-voice-assistant +Environment=PYTHONUNBUFFERED=1 + +ExecStart=/home/pi/linux-voice-assistant/script/run \ + --name 'Linux Satellite Test PW' \ + --audio-input-device default \ + --audio-output-device pipewire/default \ + --wake-uri 'tcp://127.0.0.1:10400' \ + --wake-word-name 'alexa' \ + --wake-models-dir '/home/pi/wyoming-openwakeword/wyoming_openwakeword/models' \ + --debug + +Restart=always +RestartSec=2 + +[Install] +WantedBy=default.target diff --git a/service/user-wyoming-openwakeword.service.service b/service/user-wyoming-openwakeword.service.service new file mode 100644 index 0000000..56af08a --- /dev/null +++ b/service/user-wyoming-openwakeword.service.service @@ -0,0 +1,25 @@ +[Unit] +Description=Wyoming openWakeWord + +[Service] +Type=simple +WorkingDirectory=/home/pi/wyoming-openwakeword + +ExecStart=/usr/bin/env bash -lc '\ + cd /home/pi/wyoming-openwakeword && \ + exec ./script/run \ + --uri tcp://0.0.0.0:10400 \ + --models-dir /home/pi/wyoming-openwakeword/wyoming_openwakeword/models \ + \ + --preload-model alexa_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model hey_jarvis_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model hey_mycroft_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model hey_rhasspy_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model ok_nabu_v0.1 --threshold 0.5 --trigger-level 3 \ +' + +Restart=always +RestartSec=2 + +[Install] +WantedBy=default.target diff --git a/service/wyoming-openwakeword.service b/service/wyoming-openwakeword.service new file mode 100644 index 0000000..bfdeefa --- /dev/null +++ b/service/wyoming-openwakeword.service @@ -0,0 +1,27 @@ +# /etc/systemd/system/wyoming-openwakeword.service +[Unit] +Description=Wyoming openWakeWord +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=pi +WorkingDirectory=/home/pi/wyoming-openwakeword +ExecStart=/usr/bin/env bash -lc '\ + cd /home/pi/wyoming-openwakeword && \ + exec ./script/run \ + --uri tcp://0.0.0.0:10400 \ + --models-dir /home/pi/wyoming-openwakeword/wyoming_openwakeword/models \ + \ + --preload-model alexa_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model hey_jarvis_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model hey_mycroft_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model hey_rhasspy_v0.1 --threshold 0.5 --trigger-level 3 \ + --preload-model ok_nabu_v0.1 --threshold 0.5 --trigger-level 3 \ +' +Restart=always +RestartSec=2 + +[Install] +WantedBy=multi-user.target