ckdo / airplay2-receiver

AirPlay 2 receiver - python implementation only for testing
125 stars 7 forks source link

Docker / Raspi 4 - no sound #10

Closed PaulWieland closed 3 years ago

PaulWieland commented 3 years ago

I’m just testing out the docker image on my raspberry pi 4 and for some reason I am not getting any sound output.

The client (iOS 14.4) connects and I see what looks like audio being buffered in the container log, but I have no audio coming from the 1/8” port on the pi.

I tested aplay a wav file locally to make sure there isn’t something wrong with my pi and it seems to work just fine.

I’m really interested in this project. It would be excellent to have a basic airplay 2 receiver for multi room audio with the pi acting as a receiver and a digital signal processor for DML speakers.

UPDATE: I ran docker run -it --rm --device /dev/snd --entrypoint /bin/bash invano/ap2-receiver to get to the containers shell, and then ran speaker-test. This is producing static on the pi's headphone jack, which tells me that the the hardware + docker are all working just fine.

PaulWieland commented 3 years ago

I believe this is some sort of a problem with pyaudio (or even portaudio), but I cannot figure it out. I can't get pyaudio to output any sound under docker on my raspberry pi 4.

I created a new docker image that only installs the libraries and then attempts to play a wav file using the example script from the pyaudio home page. This doesn't produce any sound, however aplay works just fine.

Then then tried compiling portaudio and running the test/patest_sine8. program - (which I am blindly assuming outputs a sine wave sweep) which also produces no sound.

Stuck.

systemcrash commented 3 years ago

Probably portaudio - I think portaudio is intended for macOS only. Could be wrong.

PaulWieland commented 3 years ago

Well, doesn’t the receiver script rely on pyaudio to output sound (regardless of OS)?

from what I understand pyaudio is a python wrapper for portaudio.

systemcrash commented 3 years ago

I was completely wrong XD - PortAudio is cross-platform 🤦

PaulWieland commented 3 years ago

I built a test dockerfile that does the bare minimum. It's built on the official python3 image and it uses the demo play.py file from pyaudio. No sound.

https://github.com/PaulWieland/pyaudio_test

M-Whitaker commented 3 years ago

I'm currently also having this issue @PaulWieland do you have this fork working outside of docker? Also I have tried on macOS Big Sur with no luck (however due to Big Sur being different in lots of ways I kind of expected that)

PaulWieland commented 3 years ago

@M-Whitaker I can't get a RaspberryPi to output sound correctly with pyaudio (see my pyaudio_test container in the previous reply). Docker or not doesn't seem to matter.

From what I understand, the docker container is incompatible with macOS because it expects to output to /dev/snd - which is normal for Linux but not for macOS.

The ap2 receiver does work on macOS if you run it natively using the instructions in the Readme.

M-Whitaker commented 3 years ago

Ah perfect thanks for the clarification. For information I was using the native install for macOS Big Sur as like you I noted the /dev forwarding wasn't going to work. What devices have you got this working on? as I'm slightly confused as to what is working and what shouldn't as I understand this is a POC.

PaulWieland commented 3 years ago

I'm running the receiver under 10.15.7 (I haven't updated to Big Sur yet because of compatibility issues with my company's VPN).

Tested Clients:

This combination works perfectly fine for me.

M-Whitaker commented 3 years ago

Ok, thanks for that as said it is really not a surprise that Big Sur breaks things (I'm also running M1 but that shouldn't effect anything from what I have seen skimming the code). I have to say on the docker/portaudio front I haven't previously tried running audio applications though docker as I know getting devices & drivers to work this way can be a pain. Would be interesting to see if #9 works (i.e. not using docker) on your setup as I couldn't get past an error: amixer: Unable to find simple control 'PCM',0

PaulWieland commented 3 years ago

The program should not be trying to call amixer under darwin (macOS).

https://github.com/ckdo/airplay2-receiver/blob/cf2d54c6dd0534e08acbd02dafef166dff113dfd/ap2/utils.py#L44

Can you run a quick test to verify what python thinks your OS is?

Go to a terminal and type in python3 and press enter. Now type in the following two lines:

import platform
platform.system()

It will output your system name, which if you are on a mac should be 'Darwin'.

image
M-Whitaker commented 3 years ago

Sorry, this is on my PI4. (My Mistake)

PaulWieland commented 3 years ago

Ok, in that case you need to find out what the alsa device name is (which can be different on each machine - which is why ckdo added the --no-volume-management flag).

On mine it's Headphone (not PCM).

So the solution is to run it without volume management - or or to modify the get/set_volume subroutines in the utils.py script.

Launch a container and jump into the shell: docker run -it --rm --device /dev/snd --net host invano/ap2-receiver /bin/bash

Then type amixer scontrols and it should tell you what your mixer name is.

image

Then modify utils.py accordingly:

Get Volume becomes:

    line_pct = subprocess.check_output(["amixer", "get", "Headphone"]).splitlines()[-1]

Set Volume becomes:

    subprocess.run(["amixer", "set", "Headphone", "%d%%" % pct])
M-Whitaker commented 3 years ago

Thanks, that was a bit simple of me... Shouldn't have skipped over that. So this is now working the same as the docker container (no audio) which I assume is the same place you are on your PI4?

PaulWieland commented 3 years ago

Correct. The client can connect and play/pause/disconnect/reconnect/adjust volume. But there's no sound. I'm trying to get help from the port audio mailing list, because I believe this is an issue with that library. The python script is using pyaudio (which depends on portaudio).

My pyaudio_test was an attempt to isolate the problem.

satrik commented 3 years ago

@PaulWieland I'm testing it currently with Docker on Debian Buster (kernel 4.19) and it works if I use --privileged for the audio device. I know --privileged isn't a (nice) solution, but it helps to narrow down the error further. I will do some tests on the weekend and maybe I'll find the cause and a nice solution :)

PaulWieland commented 3 years ago

A small update. I replaced portaudio with alsa and everything works fine.

https://github.com/PaulWieland/airplay2-receiver/blob/alsaaudio/ap2/connections/audio.py

I’m sure this change breaks cross platform support but shairport-sync writes directly to alsa as well so...

Neustradamus commented 3 years ago

@ all : Do not forget, to work with the upstream...

PaulWieland commented 3 years ago

@Neustradamus > @ all : Do not forget, to work with the upstream...

Please stop with this.

satrik commented 3 years ago

A small update. I replaced portaudio with alsa and everything works fine.

@PaulWieland sounds great! I've tested to build the container from your alsaaudio branch, but it fails while step 6 Installing build dependencies. anything I need to change for the build?

docker build -f docker/Dockerfile -t invano/ap2-receiver .
PaulWieland commented 3 years ago

@satrik I'm working on optimizing the dockerfile into a multi stage build so the image is a little smaller. You can use your existing image with the python code from the alsaaudio branch.

The volume flag will start the container and map the repo on your host to the /airplay2 directory in the container. That way you can modify the python code and test the changes without rebuilding.

e.g. clone and then checkout the branch, in your home directory and then start the container: run -it --rm --device /dev/snd -v ~/airplay2-receiver:/airplay2 --env AP2IFACE=eth0 --net host invano/ap2-receiver

I hope to get the dockerfile working soon, but try the above if you are impatient :)

PaulWieland commented 3 years ago

@satrik I just got around to building/testing the docker image in my alsaaudio branch. It works perfectly well on my rpi4 with 2gb of ram. However, I only managed to get the image down to 445mb.

satrik commented 3 years ago

@PaulWieland nice, I will try it out in the days :)

if this works now, than we just need to figure out how the HomeKit pairing works and implement it^^

PaulWieland commented 3 years ago

Closing, since replacing pyaudio with pyalsaaudio solves the issue.

systemcrash commented 3 years ago

@PaulWieland - could you give portaudio 19.7 a try, and see whether any of the newer fixes resolve your audio issue, please?

PaulWieland commented 2 years ago

@systemcrash I had tried 19.7 when it first released at the advice of the portaudio devs - it didn't work. But now that shairport-sync supports airplay 2 it doesn't really matter...