dubo-dubon-duponey / docker-spotify

Librespot container for amd64, arm64, arm/v7, arm/v6 (based on debian:buster-slim)
https://hub.docker.com/r/dubodubonduponey/librespot
MIT License
22 stars 2 forks source link

More audio backends #7

Closed mmallozzi closed 3 years ago

mmallozzi commented 4 years ago

Would it be possible (or are there any downsides) to this image including librespot built with more of the audio backends, at least the ones that apply to Linux? I'm mainly interested in PulseAudio, but it seems like the others might be generally useful.

I tried adding it myself to the Dockerfile, but I couldn't get the image to build locally using the development instructions.

Thanks!

dubo-dubon-duponey commented 4 years ago

Hey

Sure, if that’s not introducing too much bloat, definitely.

My laptop just died unfortunately so I cant look into it right now but I will later on.

About the build instructions, anything specific blocking you?

mmallozzi commented 4 years ago

Thank you! Right now I'm playing around with outputting to a named pipe that I've mounted into the container, and then trying to paplay/pacat that into an arrangement of PulseAudio combined and pipe sinks on my host that ultimately feed into a Snapcast container. But if I can get each of my audio source containers to play directly to a particular PulseAudio sink that would remove one layer of named pipes and the paplay/pacat hack that isn't fully working, which should give me fewer moving parts and less chance for latency or quality loss :)

I should have taken notes on my build issues, but I hacked around with a few things before giving up. I think the first was that DEBIAN_DATE=2019-12-01 was invalid. Looking at the images page it didn't seem like any from 2019 still existed. I tried changing it to the latest, and that one I believe led me to an error where the cargo and libasound2-dev packages were not found to be installed. I changed the date to one or two versions earlier than the latest, and that got me past that problem. There was an issue with arm/v6 so I just removed all but linux/amd64 from the platforms. After that I think the build mostly finished, but the health checks were unable to run because a specific golang version was needed in the image. At one point I did update the librespot version hash since the included one was from November, I forget if that was to address a particular problem. I tried the same with the health check version hash in case an update called for a more recent golang version, but I saw the health check repo is super simple with only a couple of commits. I suppose I might be able to disable the health checks entirely and see how it goes, but this is my first attempt to build a Docker container so I was hoping for a clean build that I could hack from there.

dubo-dubon-duponey commented 4 years ago

Sorry for the hustle.

Try this to build your own:

git checkout pulseaudio # <- and/or fork from this branch 

VENDOR=dubodubondupooney IMAGE_TAG=dev-with-pulse DEBIAN_DATE=2020-02-15 PLATFORMS=linux/amd64 ./build.sh

Tweak "VENDOR" to reflect your Docker HUB account name, and "PLATFORMS" to reflect what you want to target.

Also, I just pushed to Docker HUB:

dubodubonduponey/librespot:dev-with-pulse

Unfortunately my laptop is still under repair (working on a shitty spare) and I can't test right now (nor sign my commits :s).

Do you mind testing either the image I pushed above or build yourself the branch and let me know if it works as expected?

(note: I also updated librespot to v0.1.1)

Finally, extra arguments passed when starting the image will get fed to librespot itself (eg: to select the backend).

dubo-dubon-duponey commented 4 years ago

Sorry again about the issues building this. Unfortunately I had a bunch of changes lined-up that I did not push and that were on my regular laptop.

All the issues you mentioned should be fixed on the pulse branch and you should be able to just get it built using the provided snippet.

mmallozzi commented 4 years ago

Thank you! It partially works - the container starts and librespot recognizes --backend pulseaudio, but it fails to open the device with either --device or the PULSE_SINK environment variable (or even list devices with --device ?. I think the issue is the user - I'm accessing PulseAudio from containers with the approach in https://github.com/TheBiggerGuy/docker-pulseaudio-example, and my suspicion is that the gap is creating a user inside the container that belongs to the audio group. I have this setup working with a custom build of another container (VLC) outputting to PulseAudio.

When I try to build locally to start making these changes, just starting with a clean checkout from your pulseaudio branch, I'm getting ERROR exporting to image failed to solve: rpc error: code = Unknown desc = server message: insufficient_scope: authorization failed. I would give a paste of the full message, but I'm also dealing with a broken laptop and limited to my GUI-less server and my phone :)

dubo-dubon-duponey commented 4 years ago

Hey there - thanks for the quick feedback!

  1. Did you start the container using the stance provided here?

https://github.com/dubo-dubon-duponey/docker-librespot#run

^ that should take care of the audio group membership + device mounting part without having to do anything else at the build stage.

  1. the error you report likely means you do not have permission to push the image to Docker HUB. Likely you need to do a "docker login" first (and of course use for "VENDOR" that same HUB username.

I'm also dealing with a broken laptop and limited to my GUI-less server and my phone :)

Ha! I guess we are doing "the blind leading the blind" :P.

mmallozzi commented 4 years ago

Ah no, I had this image set up in docker-compose for a couple months with the pipe backend before starting to mess with Pulse, so I was trying to just use my existing setup. Let me see if I can adapt those flags to docker-compose.

As for the push to Docker hub - I didn't realize that was a standard part of the build process. If there's a way for me to disable that (I think I remember seeing a config for that, maybe it was in another image), I can mess around locally, but with the run settings change I may not need to build at all.

I might have to come back to it tomorrow morning, but I'll keep you posted on my progress.

dubo-dubon-duponey commented 4 years ago

Ah no, I had this image set up in docker-compose for a couple months with the pipe backend before starting to mess with Pulse, so I was trying to just use my existing setup. Let me see if I can adapt those flags to docker-compose.

I'm confident that compose does support any of the flags I'm using here (group and device mount are the important ones).

As for the push to Docker hub - I didn't realize that was a standard part of the build process.

It is not part of the default, "old" docker workflow.

Here, the image being built is inherently multi-architecture. As such, the resulting image cannot really be just "used locally by docker" (it is in buildx cache though). Let me see if I can hack something for purely local dev though.

You should not think that what I'm doing here is "standard" or representative of the majority of docker builds out there - multi-arch images and buildx is still considered "experimental": https://docs.docker.com/buildx/working-with-buildx/

dubo-dubon-duponey commented 4 years ago

Ok, here you go. Update the branch pulse.

Now you can just:

IMAGE_TAG=dev-whatever DEBIAN_DATE=2020-02-15 PLATFORMS=linux/amd64 NO_PUSH=true ./build.sh

And the image will just be built locally and made available to docker (and I probably broke Travis, but that's fine for now... let's make this work and get my laptop back, then cleanup ;-)).

mmallozzi commented 4 years ago

Thanks! I'm certainly learning a lot about Docker here as a beginner.

I did get the build working locally – the NO_PUSH variable helped with the build but then I wasn't able to start the image without docker login anyway, so I just created an account and used that.

Due to the docker-compose limitations of not having group_add in v3 (I still don't quite understand why that's not a feature), I ended up modifying the Dockerfile to create a user and add them to the audio group:

-USER          dubo-dubon-duponey
+RUN useradd -m -d /data -s /bin/sh -u 1000 spot && \
+    gpasswd -a spot audio
+
+USER          spot

I didn't end up needing the /dev/snd device, as that's for ALSA, and I'm accessing the host's PulseAudio server through a Unix socket at /run/user/$UID/pulse/native that I mapped into the container as a volume.

So in short – thank you, I got the audio playing through Pulse! The librespot side of my experiment is working well, now I'm on to debugging why VLC is playing my announcements in a choppy way and why Pulse isn't "ducking" the music volume in favor of announcements :)

dubo-dubon-duponey commented 4 years ago
  1. Compose v3 not supporting group_add:

Ping @shin- seriously?? :p

  1. You do not need to create a new user - there is already one (the dubo-dubon-duponey one) - you can just add it to the group (of course your version works fine as well)

  2. I’m surprised you would need the Hub to run your image - compose should be able to reference the local image

  3. I’m happy you got this to work! I’ll merge pulseaudio support into master once I get my rig back (and the rest of the fixes).

  4. I’m curious about your take on pulse (I’m purely a alsa user, mainly because I want to minimize stuff on the host) - what are the upsides in using pulse?

Take care.

dubo-dubon-duponey commented 4 years ago

@shin- any chance this could get fixed: https://github.com/docker/cli/issues/1318

En souvenir du bon vieux temps? :-)

mmallozzi commented 4 years ago
  1. That would be great to fix – I really love the declarative nature of Compose, so it's disappointing to see it missing functionality.
  2. Ah I see, I didn't realize USER also creates the user, I wasn't sure if dubo-dubon-duponey was created by the base image for some special purpose so I didn't want to mess with it much.
  3. Yeah I'm not sure why, I didn't dig in much, just got it working to resume my primary debugging.
  4. Sounds good, thanks!
  5. My main purpose for using Pulse here is to combine my TTS announcements/notifications being played as MP3s through a VLC container simultaneously with multiple different sources of music (librespot, shairport-sync, Mopidy, etc.), where the music would lower its volume to defer to the higher priority of the notification ("ducking"), and then this combined sink would output to a named pipe that Snapcast can then broadcast to clients. PulseAudio is intended for exactly this purpose of combining multiple audio streams, typically in the context of a desktop environment where multiple applications may want to play music and make event noises and things at the same time, but it's also commonly used to redirect the audio output to something other than ALSA like a recording or screen sharing program. I actually did just get this combined ducking thing working, and it's pretty cool, just ironing out a few kinks now with VLC. Once I get the kinks ironed out I'll be able to start using it for Home Assistant home automation announcements while I'm listening to multi-room music, e.g. "the front door is open", and add more of the music sources besides librespot.
shin- commented 4 years ago

Sorry, I haven't been a maintainer on Compose for over a year now, so there's not much I can do to help. But unless you're actually using Swarm, you'll be better served by using a 2.4 Compose file!

AgentT-mo commented 4 years ago

Hey, I'm also interested in using different audio backends with your container. For me especially the Pipe backend to feed into a snapcast server container is what I'm looking for, but I don't really get it to work. Is this already possible with your container, or are there changes that need to be made? Thanks in advance

dubo-dubon-duponey commented 4 years ago

@AgentT-mo ok, let me look like into that this week.

dubo-dubon-duponey commented 4 years ago

@AgentT-mo the pipe backend is always compiled in.

So:

docker run -d --rm \
    --name "spot" \
    --env "NAME=Super Name For Your Spotify Connect Endpoint" \
    --volume /tmp \
    --group-add audio \
    --device /dev/snd \
    --net host \
    --cap-drop ALL \
    --read-only \
    dubodubonduponey/librespot:v1 \
   --backend pipe

^ that's the normal startup statement, plus the extra argument "--backend pipe"

I'm not familiar with the pipe backend, so, maybe other arguments are required? (eg: how does this work? does it need a fifo? or a unix socket?)

Either way, you should be able to pass any additional arguments needed there - and also, mounting /dev/snd is probably not required in that case.

Let me know if/how that works for you (bottom-line: it doesn't seem that any change is required to the image for pipe, but please let me know if I'm mistaken).

mmallozzi commented 4 years ago

The pipe backend does work with the default image, that's what I was using successfully before I switched to PulseAudio. I no longer have that config (and I haven't version controlled my configs yet to go back and see), but I believe it was --backend pipe --device /path/to/fifo. On the Snapcast server container, you'd reference the same pipe, and make sure to set the sample rate to 44100Hz as that's what librespot outputs to the pipe.

AgentT-mo commented 4 years ago

Thank you both. The "--device /path/to/fifo" part is, what I couldn't figure out alone, but you got me on track!

dubo-dubon-duponey commented 3 years ago

Hey good people.

I changed a lot of things recently with this image (in a shell: latest librespot version no longer build with rust from Debian... so I moved to a more recent rust version... which no longer compiles with qemu... so I moved to cross-compiling natively instead)

You can give a try to the new image version using the latest tag (instead of v1).

Changes have been merged on master and can be seen there of course.

Also, I'm going to close this issue since the support for pulse was merged-in.

dubo-dubon-duponey commented 3 years ago

And yeah, if you get a chance to try this, let me know if there is any issue with it.