This is great for testing, but can Rhasspy be run headless - as a service ? Is this why all examples use Docker, even on a dedicated low powered RasPi Zero ?
Maybe I’m being obsessive here, but on a dedicated low-speed RasPi Zero Rhasspy satellite I don’t see a need for Docker or venv to sandbox applications if there is nothing else running in that machine to protect.
It is possible to run Rhasspy as a service; but there were 3 problems:
shutdown and reboot operations require us to enter our sudo password at the (now non-existent) terminal. Given that this is a dedicated voice assistant satellite and not connected to the interweb, I can probably put up with authorising the user “pi” to have root privileges.
Linux system services handle stdout differently from command line. If we had used “ExecStart=rhasspy --profile en” above, we would have got “spawnerr: unknown error making dispatchers for ‘microphone’: ENXIO” errors. See Sherlock - Offline Voice Assistant project for a description
imo running any service with root privileges is not recommended, so here’s my rhasspy.service used on a headless debian (x64) machine:
[Unit]
Description=Rhasspy Service
After=syslog.target network.target mosquitto.service
[Service]
Type=simple
# for command, see https://github.com/rhasspy/rhasspy/issues/42#issuecomment-711472505
ExecStart=/bin/bash -c 'rhasspy -p de --user-profiles /opt/rhasspy/profiles 2>&1 | cat'
WorkingDirectory=/opt/rhasspy
User=rhasspy
Group=audio
RestartSec=10
Restart=on-failure
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=rhasspy
[Install]
WantedBy=multi-user.target
User rhasspy and working dir have to be added manually, obviously, and user rhasspy is added in group audio (despite the fact no direct audio hardware is used).
Suggestions to improve it are welcome, as this also is some kind of copy/paste solution…
Agreed !
Unfortunately just pulling the power plug on a RasPi is not recommended either, as it can corrupt the SD card But i’m not a unix GOD, so I searched for simple explanation with copy&paste code.
I note you are using syslog for StandardOutput and StandardError … but what about StandardInput ? Does your rhasspy satellite hang when you click the red [Restart] or black power button (Reboot/Shutdown System) ?
Beeing also just an ordinary user, I never missed “StandardInput”… (perhaps I somewhen in time will have to have a look at that?)
Wrt. to Restart: No problem with that, that’s the service itself. And I never tried a “Shutdown” command from within Rhasspy, which is running on my central automation machine. If there’s a need for shutdown, login via ssh is required.
But if needed, just allowing the shutdown command within a sudo environment for user rhasspy should be not to hard to configure, I guess.
@donburch@rejoe2 thanks for sharing your service files! I tried to repeat your steps on my RP where I have rhasspy installed as a deb package, but if I start it as a service it doesn’t see audio input and output:
Feb 09 15:02:32 raspberrypi rhasspy[27323]: [ERROR:2022-02-09 15:02:32,027] rhasspymicrophone_pyaudio_hermes: record
Feb 09 15:02:32 raspberrypi rhasspy[27323]: Traceback (most recent call last):
Feb 09 15:02:32 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/rhasspy-microphone-pyaudio-hermes/rhasspymicrophone_pyaudio_hermes/__init__.py", line 119, in record
Feb 09 15:02:32 raspberrypi rhasspy[27323]: stream_callback=callback,
Feb 09 15:02:32 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/usr/local/lib/python3.7/site-packages/pyaudio.py", line 750, in open
Feb 09 15:02:32 raspberrypi rhasspy[27323]: stream = Stream(self, *args, **kwargs)
Feb 09 15:02:32 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/usr/local/lib/python3.7/site-packages/pyaudio.py", line 441, in __init__
Feb 09 15:02:32 raspberrypi rhasspy[27323]: self._stream = pa.open(**arguments)
Feb 09 15:02:32 raspberrypi rhasspy[27323]: OSError: [Errno -9996] Invalid input device (no default output device)
Feb 09 15:03:06 raspberrypi rhasspy[27323]: [ERROR:2022-02-09 15:03:06,229] rhasspyserver_hermes: Command '['aplay', '-q', '-t', 'wav']' returned non-zero exit status 1.
Feb 09 15:03:06 raspberrypi rhasspy[27323]: Traceback (most recent call last):
Feb 09 15:03:06 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/usr/local/lib/python3.7/site-packages/quart/app.py", line 1821, in full_dispatch_request
Feb 09 15:03:06 raspberrypi rhasspy[27323]: result = await self.dispatch_request(request_context)
Feb 09 15:03:06 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/usr/local/lib/python3.7/site-packages/quart/app.py", line 1869, in dispatch_request
Feb 09 15:03:06 raspberrypi rhasspy[27323]: return await handler(**request_.view_args)
Feb 09 15:03:06 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/rhasspy-server-hermes/rhasspyserver_hermes/__main__.py", line 1699, in api_text_to_speech
Feb 09 15:03:06 raspberrypi rhasspy[27323]: results = await asyncio.gather(*aws)
Feb 09 15:03:06 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/rhasspy-server-hermes/rhasspyserver_hermes/__main__.py", line 1685, in speak
Feb 09 15:03:06 raspberrypi rhasspy[27323]: say_chars_per_second=say_chars_per_second,
Feb 09 15:03:06 raspberrypi rhasspy[27323]: File "/usr/lib/rhasspy/rhasspy-server-hermes/rhasspyserver_hermes/__init__.py", line 632, in speak_sentence
Feb 09 15:03:06 raspberrypi rhasspy[27323]: raise AudioServerException(play_response.error)
Feb 09 15:03:06 raspberrypi rhasspy[27323]: rhasspyserver_hermes.AudioServerException: Command '['aplay', '-q', '-t', 'wav']' returned non-zero exit status 1.
Did you also add the user to the mentionned group?
Additionally, as you are using aplay as command, you may have to make sure, rhasspy as a user is allowed to use this (I’m running headless, as already mentionned).
Perhaps you may try to start rhassy from shell using
sudo -u rhasspy --profile en
This is how I started first prior to elaborating the final service file.
Hi pbelevich, sorry for the delay replying. The short answer is that I’m not all that familiar with Rhasspy, or even linux … so no quick easy answer ;-(
I notice that you are using pyaudio, and the errors show that pyaudio is not working for rhasspy when the error was generated. I can think of a couple of possibe reasons
One of the things I found in my own research is that services do not start and run with everything which is available to the command line. I think rejoe2 is likely correct that the rhasspy service might not have access to the audio device.
Possibly the pyaudio service is not yet running when your Rhasspy service is started ? If so, it may be a simple matter of changing the “After=”" line in your rhasspy.service file from “pulseaudio.service” to “pyaudio.service” (or whatver the correct name is)
I am using arecord (simply because it was easiest to test before installing Rhasspy), so you might like to try changing Rhasspy to use arecord instead of pyaudio. I only suggest this since (if it works for you) it will be easier than researching the other suggestions.