Redirecting Pulseaudio sink to a virtual source

15,704

Solution 1

Found another way to do it: module-pipe-source.

pactl load-module module-pipe-source source_name=virtualmic file=/tmp/virtualmic format=s16le rate=44100 channels=1

Then:

ffmpeg -re -i movie.mkv -f v4l2 /dev/video2 -f s16le -ar 44100 -ac 1 - > /tmp/virtualmic

(Note that this also fakes a webcam, using the module v412loopback)

Solution 2

The following setup works for me to share application audio with Zoom on Linux. The setup as is, feeds your microphone and application audio into Zoom. But, as described at the end, it can be changed to only use either of the two as well.

Create a sink where we will mix the microphone and some application audio:

pactl load-module module-null-sink sink_name=mix-for-virtual-mic \
sink_properties=device.description=Mix-for-Virtual-Microphone

Create a sink which takes application audio and sends it to our speakers and the special mixing sink we just created (replace alsa_output….analog-stereo with your sink's name, see pactl list sinks short.)

pactl load-module module-combine-sink sink_name=virtual-microphone-and-speakers \
slaves=mix-for-virtual-mic,alsa_output.pci-0000_00_1b.0.analog-stereo

Loopback our actual microphone to our mixing sink (replace alsa_input…analog-stereo with your source's name, see pactl list sources short.)

pactl load-module module-loopback source=alsa_input.pci-0000_00_1b.0.analog-stereo \
sink=mix-for-virtual-mic latency_msec=20

It's unclear to me how Zoom determines what's actually a microphone. We cannot tell it to use a monitor but it will listen to an echo-cancel (as Paul described.) Since there's no echo we actually mean to cancel, we create a fake sink to cancel against:

pactl load-module module-null-sink sink_name=silence \
sink_properties=device.description=silent-sink-for-echo-cancel

Finally, we create the echo-cancel source that will serve as the microphone that Zoom detects:

pactl load-module module-echo-cancel \
sink_name=virtual-microphone source_name=virtual-microphone \
source_master=mix-for-virtual-mic.monitor sink_master=silence aec_method=null \
source_properties=device.description=Virtual-Microphone \
sink_properties=device.description=Virtual-Microphone

Now, Zoom should show a Virtual-Microphone in the Microphone section.

To send application audio to your Virtual-Microphone, in pavucontrol, set your application's sink to Mix-for-Virtual-Microphone (to only send it to the virtual microphone) or to "Simultaneous output for Mix-for-Virtual-Microphone, …" to send it to the microphone and your speakers.

Note that you can also mute or change the volume of the application audio on the virtual microphone and the speakers independently of the actual volume of your microphone by changing the volume of "Simultaneous output on …" in pavucontrol.

Naturally, you can mute your microphone in the "Input Devices" section to only share application audio.

Solution 3

I wanted to just route OBS to Zoom. I used V4l2loopback to connect the video (see https://www.eigenmagic.com/2020/04/22/how-to-use-obs-studio-with-zoom/). To connect the audio, the following works:

#!/bin/sh

# This created something I could see in OBS.  Set it as the monitor device in Settings->Audio.  Then
# turn on monitoring for the microphone and the video.

pactl load-module module-null-sink sink_name=Virtual-Speaker sink_properties=device.description=Virtual-Speaker

# Now I need to take the monitor stream from the Virtual-Speaker and turn it into a source that Zoom can use
# as a microphone.

pactl load-module module-remap-source source_name=Remap-Source master=Virtual-Speaker.monitor

While playing videos from OBS have the audio/video aligned, if you try to add commentary over the video, it is not correctly sync'd.

UPDATE:

Having used this for a while now, here's my flow:

  1. Boot computer,
  2. Run Script,
  3. Start OBS (which takes control of camera and starts virtual video feed),
  4. Start Zoom (grabs the virtual feeds, but sometimes has audio lag),
  5. Exit OBS,
  6. Start OBS (audio has no lag now).
  7. teach class.

If I have to teach another class:

  1. Exit Zoom,
  2. Start New Zoom Meeting,
  3. Exit OBS,
  4. Start OBS.
  5. teach 2nd class

This process has been reliable for me for a while now. I have not tried to add any additional automation to the process. THEORY (with no actual evidence): I have to start OBS before ZOOM so that the programs grab the right devices. OBS starts putting stuff in the audio pipeline, so I have to then stop and restart OBS to let the pipeline flush.

Solution 4

I ran into the same issue with Zoom. An alternative could be the module-echo-cancel. This can create an new source, from an existing monitor source. I believe with the default settings, it does little processing.

pactl load-module module-echo-cancel \
   sink_name="echo_cancel" \
   source_master="YourSink.monitor" \
   sink_master="DefaultSink" \
   aec_method="webrtc"

Set DefaultSink to whatever is your default output device and YourSink.monitor to the monitor of the sink (in our case the stream sink).

I got this solution from ipwebcam-gst script.

Solution 5

I have the same situation. I tried some solutions with echo canceling module, they work but the quality of the sound for the receiving part is not so good. There are distortions. Fortunately, I found a very simple solution which creates a source from another source (including any monitor), which is seen in Zoom as a normal microphone.

The following code creates a "normal microphone" named "Computer-sound" from the "Monitor of Built-in Audio Analog Stereo".

pactl load-module module-remap-source \
master=alsa_output.pci-0000_00_1f.3.analog-stereo.monitor \
source_properties=device.description=Computer-sound

Replace alsa_output….analog-stereo with your sink's name, see pactl list sinks short. And don't forget .monitor after your sink's name! There is no need to do other adjustments.

Share:
15,704
Biganon
Author by

Biganon

Updated on September 18, 2022

Comments

  • Biganon
    Biganon over 1 year

    I'm trying to redirect the sound of a program (in my case, ffmpeg) to a source, so I can play the sound in question in Zoom (video conference software). The classic way of doing this would be to select, as a sound source in Zoom, the SinkName.monitor source, since every sink comes with a monitor. But :

    1) Zoom doesn't list the monitor sources in its microphone dropdown. I've tried setting the monitor's device.class property to "sound" (instead of "monitor") to trick Zoom into accepting it, to no avail.

    2) Zoom seems to refuse to let you set the source yourself from pavucontrol. In the Recording tab, when I try to set myself another source to be listened to by Zoom, no matter what I choose, my choice is ignored. The dropdown option doesn't even change. I've read somewhere that creating ~/.alsoftrc and writing "[pulse]" (new line) "allow-moves=yes" could help, but it didn't do anything for me.

    Therefore, I'm trying to set my own source, and "redirect sound to it". I created a null sink, a null source, and a loopback, but upon opening pavucontrol, I understood that I probably got it backwards; a loopback appears to be used to redirect a source to a sink, not the other way round (pavucontrol says, under Playing: "Loopback of MySource on [...] MySink", MySink being the value of the dropdown list on the right).

    Is there a way to achieve what I'm trying to do? Either:

    a) Modify a monitor so as to make it look like a normal microphone, or

    b) Redirect the sound of a sink to a source ?

    Thanks.

  • T W
    T W over 3 years
    To remove the audio delay, do the above, then install pagraphcontrol ( github.com/futpib/pagraphcontrol ) launch pagraphcontrol before running OBS. In OBS, set monitor to default, then use pagrapcontrol to route OBS-Monitor to Virtual-Speaker. This should have exactly the same effect, but OBS clearly does something different with the Default monitor. (There is no doubt a way to do this on the command line but I don't know pulseaudio well enough)
  • T W
    T W over 3 years
    In addition to my previous comment, this also works: 1. Open OBS before running your script. 2. Leave OBS set to the default monitor. 3. Run Christopher Donham's script. OBS detects the new monitor and automatically switches to it.
  • kalle
    kalle over 3 years
    @TomB Could you maybe elaborate a bit on your second solution? What are your settings in OBS to have it working without delay or echo? What are your audio settings? What are your advanced audio settings? Thank you very much in advance!
  • Christopher Donham
    Christopher Donham over 3 years
    Having used this for a while, what I am currently doing is: Start OBS. Start Zoom, Exit OBS and restart OBS. With this, my audio and video seem to be aligned reasonably. My feeling (unsupported by any deep knowledge of things) is that by exiting OBS I'm allowing the pipe to flush which aligns things. Recap: start OBS before Zoom so that Zoom gets the right video feed; stop and restart OBS after Zoom to flush the audio pipe so that the audio and video are sync'd.
  • kalle
    kalle over 3 years
    @ChristopherDonham Do you have to run the second command (the one that creates the virtual microphone for Zoom/Skype/...) after every reboot? Mine is gone after each shutdown. I also cannot only run the second command after a fresh start - I always have to run both commands, even though the virtual speaker would still be selected in OBS. Or do you have your script automatically run during boot?
  • Christopher Donham
    Christopher Donham over 3 years
    I've updated my answer with a copy of my current process.
  • T W
    T W over 3 years
    after testing this myself a little more, it seems that with any of the solutions above, the audio goes out of sync over time. Sometimes very quickly sometimes it takes a few hours. I'd assume you have the same problem but you're opening/closing OBS frequently enough that it's not a problem.
  • Christopher Donham
    Christopher Donham over 3 years
    Interesting. I teach two 3 hour classes twice a week (4 classes total) and have not had it go out of sync if it was in sync at the beginning of the class.
  • Jon
    Jon over 3 years
    Thank you very much! It works perfectly!
  • Ian
    Ian over 3 years
    I keep getting an error Failure: Module initialisation failed trying to create the loopback. Wondering if you can offer any suggestions? pactl load-module module-loopback source=alsa_input.usb-Microsoft_Microsoft___LifeCam_HD-3000-‌​02.mono-fallback=mix‌​-for-virtual-mic latency_msec=20
  • Ian
    Ian over 3 years
    Ok, I think I was accidentally using a source instead of a sink in the 2nd step. I seem to have got it all working. I'd be interested to know if there's a way to turn off the microphone auto adjusting sensitivity or not?