Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'import soundcard' throws an error when run through a systemd service #133

Open
Teufeuleu opened this issue Jul 26, 2021 · 9 comments
Open

Comments

@Teufeuleu
Copy link

Hey,
I have the following code:

#test.py
import soundcard
while True:
	pass

It runs fine with
python test.py

But it does not when I want to run it using a systemd service.

Here's the service definition:

[Unit]
Description=Soundcard test service
Requires=sound.target
After=sound.target

[Service]
ExecStart=python test.py
User=pi

[Install]
WantedBy=default.target

And the error it throws:

pi@raspberrypi:sudo systemctl start test.service
pi@raspberrypi:~ $ sudo systemctl status test.service
● caravane.service - Soundcard test service
   Loaded: loaded (/lib/systemd/system/test.service; disabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2021-07-26 20:58:23 CEST; 3s ago
  Process: 2649 ExecStart=/usr/bin/python /home/pi/test.py (code=exited, status=1/FAILURE)
 Main PID: 2649 (code=exited, status=1/FAILURE)

juil. 26 20:58:23 raspberrypi python[2649]:     import soundcard
juil. 26 20:58:23 raspberrypi python[2649]:   File "/home/pi/.local/lib/python3.7/site-packages/soundcard/__init__.py", line 4, in <module>
juil. 26 20:58:23 raspberrypi python[2649]:     from soundcard.pulseaudio import *
juil. 26 20:58:23 raspberrypi python[2649]:   File "/home/pi/.local/lib/python3.7/site-packages/soundcard/pulseaudio.py", line 261, in <module>
juil. 26 20:58:23 raspberrypi python[2649]:     _pulse = _PulseAudio()
juil. 26 20:58:23 raspberrypi python[2649]:   File "/home/pi/.local/lib/python3.7/site-packages/soundcard/pulseaudio.py", line 72, in __init__
juil. 26 20:58:23 raspberrypi python[2649]:     assert self._pa_context_get_state(self.context)==_pa.PA_CONTEXT_READY
juil. 26 20:58:23 raspberrypi python[2649]: AssertionError
juil. 26 20:58:23 raspberrypi systemd[1]: test.service: Main process exited, code=exited, status=1/FAILURE
juil. 26 20:58:23 raspberrypi systemd[1]: test.service: Failed with result 'exit-code'.

I tried with the sounddevice module instead of soundcard and I dont get this error so I guess the problem comes from soundcard and not PulseAudio?

Why all this: I'm making a sound installation, the main python program runs fine on the Raspberry (using multiple sound cards handled by the soundcard module, threading, ...), but I struggle to make it start at boot. It seems to run too early with rc.local or a crontab (because sound cards and/or pulseaudio itself are not initialized yet, I guess), so I tried with systemd but I faced the problem described above.

I'm still learning programming and how linux work so sorry if I missed something obvious and if the problem is actually unrelated to soundcard itself.

@Chum4k3r
Copy link

SoundDevice is a python wrapper for PortAudio, which does not use PulseAudio. Your problem seems to be on these two lines

juil. 26 20:58:23 raspberrypi python[2649]:     assert self._pa_context_get_state(self.context)==_pa.PA_CONTEXT_READY
juil. 26 20:58:23 raspberrypi python[2649]: AssertionError

And seems that it is what you think is the problem is, really is the problem. You are running it too early.

@Teufeuleu
Copy link
Author

Teufeuleu commented Jul 28, 2021

SoundDevice is a python wrapper for PortAudio, which does not use PulseAudio

My bad, I still get those mixed up.

You are running it too early.

I think I don't I get what "too early" refers to, because the copy-pasted errors are from me trying to manually start the service (sudo systemctl start test.service), after that the system has fully booted, and after that python test.py ran successfully.

@bastibe
Copy link
Owner

bastibe commented Jul 28, 2021

I would think that the service somehow does not have access to pulseaudio.

Can you check the value of self._pa_context_get_state(self.context) in this case? Perhaps that will tell you more.

@Teufeuleu
Copy link
Author

Can you check the value of self._pa_context_get_state(self.context) in this case?

Well I learn by trying! I spent maybe 10h trying to get that damn value but finally I got it. After countless tries, I "simply" had to install the soundcard module globally instead of locally, then modify soundcard/pulseaudio.py to get it logging the said value, and make the service run as root instead of pi (because logging would not work otherwise for some reason).

Now the result: self._pa_context_get_state(self.context) = 5 when the error happens (test.py ran as a systemd service). Its value is 4 when everything runs fine (manually run python test.py).

So if I get it correctly from the pulseaudio documentation, self._pa_context_get_state(self.context) = 5 means that the pulseaudio context connection failed or was disconnected, but I can't go any further, and I can't tell if the issue comes from soundcard or how python/pulseaudio/systemd interact with each other.

@bastibe
Copy link
Owner

bastibe commented Aug 15, 2021

Thank you very much for going to such lengths in debugging this issue.

This does indeed point to some configuration issue in pulseaudio that prevents the systemd unit from accessing pulseaudio for some reason. I believe pulse communicates over a socket, which is (or can be) exposed through an environment variable. Perhaps checking that variable and/or socket might be a next step in debugging this issue.

@Teufeuleu
Copy link
Author

Could you be a bit more specific? Apparently pulseaudio does uses some environment variables, but I don't understand how to get or set any of those. None of those appear in the output of the env command.
It seems that the pulseaudio server socket is something like /run/user/1000/pulse but I'm not sure what to do with that. Is there a way I could "listen to" whatever goes through this socket?

I also ran pulseaudio -vvvvv which outputs a lot of info when I run python test.py or my other project files (everything goes fine), but absolutely nothing when starting the test.service.

@bastibe
Copy link
Owner

bastibe commented Aug 15, 2021

I'm not very well-versed in pulse, either, sorry. At least you could check whether your systemd unit can read that server socket. Beyond that, I'm not sure either.

@ronny-rentner
Copy link

@Teufeuleu: You could try to use pulseaudio's paplay from your service to see if it actually has access to pulseaudio and can play something. Then you know if the issue is with your pulseaudio setup or with SoundCard.

@arvind-cp
Copy link

arvind-cp commented Jan 31, 2022

@ronny-rentner @Teufeuleu : I have the same issue. It works fine on systemd service in ubuntu 18.04 with pulseaudio version 11.1
It fails on systemd service in ubuntu 20.04 pulseaudio version 13.9. soundcard library version is 0.4.1 on both machines.
paplay seems to be fine though - both via systemd service as well as command line execution.

Update: After adding 'sound.target' as a dependency and sourcing these 2 env variables, it started working in systemd.

Environment="XDG_RUNTIME_DIR=/run/user/1000"
Environment="PULSE_RUNTIME_PATH=/run/user/1000/pulse/"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants