Record a program's output with PulseAudio

Solution 1:

Try something like this:

In a terminal enter

pacmd

(this is the CLI of the PulseAudio-Server) then use

list-sink-inputs

(where you get the indices of the running inputs) Now find the index of your input. Now referred to as $INDEX

the scriptable part is:

pactl load-module module-null-sink sink_name=steam
pactl move-sink-input $INDEX steam
parec -d steam.monitor | oggenc -b 192 -o steam.ogg --raw -

Explanations:

  • The first command will add a null-sink as you already knew.
  • The second command moves the sink-input from your standard-audio-sink to steam
  • The third command records the monitor of the device steam (-d) and puts the output (raw-wave-stream) into oggenc, which encodes this wave-stream to an oga-file. (for mp3 use lame)

Solution 2:

Improving Waschtl answer of this thread so you can BOTH LISTEN AND RECORD the app sound:

First, we look for our default output and put its sink name in $DEFAULT_OUTPUT:

$ pacmd list-sinks | grep -A1 "* index"
  * index: 1
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
$ DEFAULT_OUTPUT=$(pacmd list-sinks | grep -A1 "* index" | grep -oP "<\K[^ >]+")
$ echo $DEFAULT_OUTPUT
alsa_output.pci-0000_00_1b.0.analog-stereo

Then, we create a combined sink that has only one slave: $DEFAULT_OUTPUT. The sound generated by the app (source) will be forwarded to the slave sink (ie. real output), and we'll also record it. It is different than a null sink where the source sound is not forwarded.

$ pactl load-module module-combine-sink \
  sink_name=record-n-play slaves=$DEFAULT_OUTPUT \
  sink_properties=device.description="Record-and-Play"

sink_properties is optional and may bug if you use spaces in the description name.

Then, we could use pactl move-sink-input ... command of Waschtl answer (with record-n-play instead of steam) but GUI pavucontrol is more simple (and great for checking/troubleshooting):

$ sudo apt-get install pavucontrol
$ pavucontrol &

Then, we play some sound in the app we want to record. In pavucontrol Playback tab, we select in the app dropdown list: "Record-and-Play".

Finally, we're good to record and listen at the same time! (lame mp3 example, run in foreground)

$ parec --format=s16le -d record-n-play.monitor | \
  lame -r --quiet -q 3 --lowpass 17 --abr 192 - "temp.mp3"

Or we can record in background and stop at any time:

$ parec --format=s16le -d record-n-play.monitor | \
  lame -r --quiet -q 3 --lowpass 17 --abr 192 - "temp.mp3" \
   > /dev/null &1>/dev/null
$ killall -q parec lame

NB:

  • To unmess everything or retry the procedure: Delete or reset the sinks by using this answer. pulseaudio -k works great to reset everything to session's defaults.
  • If we change the default output in the System Sound Settings, the custom app Playback setting will be overwritten and we will have to go back in pavucontrol to set it back to the combined interface.
  • To be able to listen to the sound from several "real" interfaces (eg headphones, HDMI output, etc...), we should include all "real" outputs that we may use to listen, as record-n-play slink slaves, like: pactl load-module module-combine-sink sink_name=record-n-play slaves=real-output-1,real-output-2.

EDIT: Beware, since Ubuntu 18 (maybe 17 too), the combined sink tends to become the default system output device, instead of the real output device. So when you change the volume using the sound icon in the system tray it impacts your record sound. Workaround: After creating the combined sink, open pavucontrol in Output tab. Select "View: Virtual Output Devices" and reset the sound volume of the combined sink to 100%. Then select "View: Hardware Output Devices" and press the green icon "Define as alternative" on the real output device.

Solution 3:

@Waschtl's answer is fantastic. @ixtmixilix asked about restoring regular audio after the recording is finished. Here's the easiest way I know of:

Install and run the pavucontrol GUI. You should see your audio-outputting application and it's volume meter under the Playback tab in there. There will be a button next to it showing that it's playing on Null Output. Click on that and change it to your ordinary audio output, Built-in Audio Analog Stereo in my case.

Here's a screenshot of what you're looking for:

screenshot

You can also use this approach to set up your recording in the future, after you've run the load-module command in @Waschtl's answer to create the sink.