Imagine a standard desktop computer. Connected to this computer is a pair of loudspeakers via common 3.5 mm stereo jack (AUX). Everything works fine so far.

Now we have a further speaker in another room of the building that does support receiving of UPnP-streams.

How can I configure a Debian-based system to keep emitting the sound on the classic stereo jack but additionally also stream it via UPnP, so I can feed both speakers simultaneously?

  • 3
    Now that I tried to look for a target, this is probably a dupe of unix.stackexchange.com/questions/396185/… (and maybe even things like unix.stackexchange.com/questions/143865/…) depending on whether the UPnP part complicates matters. – Andras Deak Oct 31 at 22:20
  • By "simultaneously", do you mean the audio should be in sync? I.e. the system should measure the network latency towards the speaker, account for the encoding and decoding delay as well as any processing delay inside the speaker, and delay the audio output of the AUX jack accordingly? – Jörg W Mittag Nov 1 at 7:09
  • @JörgWMittag: Hmmm, do you think there would be a huge delay between the speakers at the AUX jack and the UPnP stream? – Dave Nov 1 at 20:21
  • There is going to be some encoding and decoding delay, and of course network latency, but the biggest and possibly audible influence is going to be the size of the receive buffer in the network speaker. A small number of milliseconds doesn't matter (just taking one step back from the speaker is already 2ms latency just because the speed of sound), but if there are places in the building, where you can hear both speakers, having more than a couple of ms is definitely going to be annoying. Also, if you e.g. you call someone from the room with one speaker who is in the other room. – Jörg W Mittag Nov 1 at 22:26

I'll post a hacky workaround that I've been using until an expert tells us how to do this right :) Fair warning that most of what I have comes from diligent cargo culting, so chances are high that I'm not following best practices, and don't take this post as a guide to correct terminology. My use case was that I had to find a solution for MS Teams not allowing system audio to be shared, and I'm going to describe my current setup.

I'll assume you have pulseaudio, and that you can find the UPnP-enabled speaker as an output device in your settings, and your only issue is sending audio to two different places. If this is not the case then the below answer will probably not help you.

You can create a virtual device with

pactl load-module module-null-sink sink_name=myduplexsink

This will create a null sink that acts like a box you can direct audio into and out from. The sink name can be used to retain your setup programmatically by setting a few things in ~/.pulse/default.pa but my setup is unreliable enough that I haven't gotten around to making this all automatic.

You will also need two (I think) loopbacks, which act like virtual cables connecting devices:

pactl load-module module-loopback
pactl load-module module-loopback

Loopbacks cannot be named; as I understand you'd specify their source and sink on creation, if you were to automate this.

Now for the interactive solution, (install and) open pavucontrol that is a buffed-up configuration panel for pulseaudio. It has five tabs:

  1. Playback: this is where you should see whatever program is creating the sound you want to share to two places. In my use case this is mplayer, and I want its audio to be directed both into a null sink (together with my microphone's output) and to my headphones. This is also the tab where you specify the sink of every loopback you create.
  2. Recording: this is where programs expecting audio input appear. In my use case this is MS Teams, but I think in your case there's none. But this tab also configures the source of every loopback.
  3. Output devices: you should see your speakers (both kind, I hope) and your null sink named Null Output here.
  4. Input devices: you should see your microphone (if any) here, and every "monitor" device. For every output device you have a "monitor" that you can use as input. If your speakers are booming music then the monitor of your speakers will carry the music as audio signal.
  5. Configuration: this shall be ignored now :P

So what I think you should do:

  1. start the program that provides your audio (e.g. music software). In the Playback tab of pavucontrol find the row that corresponds to this program, and send it to "Null Output". Now you have a virtual device (the null sink) that has the audio you want to split.
  2. still in the Playback tab set one loopback to use your speaker (if my laptop is any indication, called "Built-in Analog Stereo"), and the other loopback to use your UPnP speaker as sink.
  3. In the Recording tab set the source of both loopbacks to your "Monitor of Null Output".

Now you have your input audio enter the null sink, and leave it both toward your local speaker and toward the UPnP speaker. Hopefully this is just what you need.

I've hacked most of this together based on this post. It briefly mentions that once you have manually set up a working configuration you can use pacmd info and excavate the names of the audio devices that you want to use. This would allow you to recreate the configuration automatically when pulseaudio starts, by adding a few commands to ~/.pulse/default.pa. I haven't been able to get this working, but mostly because I have a weird set of headphones that gets recognized under multiple device names depending on the circumstances. This might not be a problem for you. So in this case the new lines in your ~/.pulse/default.pa would look something like this:

load-module module-null-sink sink_name=myduplexsink
load-module module-loopback source=myduplexsink.monitor sink=<device ID of your local speakers>
load-module module-loopback source=myduplexsink.monitor sink=<device ID of your UPnP speakers> 

The device IDs are probably listed in the output of pacmd info under "[n] sink(s) available". In your case n will probably be at least 3: the two speakers and myduplexsink. You can also see a "Default sink name" at the top of the output, which will probably correspond to your local speakers. You will probably still have to direct the software that provides the audio to your "Null Output" in pavucontrol manually.

If your UPnP speaker is fed through some program that shows up in the Recording tab of pavucontrol then it's even easier: you can directly tell it to pull audio from the "Monitor of Null Output", and you'd only need a single loopback to feed the same signal to your local speakers.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.