Redirecting Pulseaudio sink to a virtual source

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)


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.


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.