Record system audio output with ALSA

This was written & tested on an Archlinux system, but I believe it applies to most Linux/ALSA systems.

ALSA loopback device

We assume a single run-of-the-mill Intel sound card, mapped as card 0. We will create a virtual loopback card 1.

#> modprobe snd-aloop
aplay -l

The loopback device works, but we won't be able to hear anything because sound goes only there, and not to the main output anymore.

Duplicate master output to loopback device

It is possible to duplicate the main output to the loopback device.

Unfortunately my nerd-fu starts to run thin here and I simply scoured the web until I found an ~/.asoundrc that works for my setup (source):

pcm.!default {
  type asym
  playback.pcm "LoopAndReal"
  capture.pcm "hw:0,0"
}
pcm.LoopAndReal {
  type plug
  slave.pcm mdev
  route_policy "duplicate"
}
pcm.mdev {
  type multi
  slaves.a.pcm pcm.MixReale
  slaves.a.channels 2
  slaves.b.pcm pcm.MixLoopback
  slaves.b.channels 2
  bindings.0.slave a
  bindings.0.channel 0
  bindings.1.slave a
  bindings.1.channel 1
  bindings.2.slave b
  bindings.2.channel 0
  bindings.3.slave b
  bindings.3.channel 1
}
pcm.MixReale {
  type dmix
  ipc_key 1024
  slave {
    pcm "hw:0,0"
    rate 48000
    #rate 44100
    periods 128
    period_time 0
    period_size 1024 # must be power of 2
    buffer_size 8192
  }
}
pcm.MixLoopback {
  type dmix
  ipc_key 1025
  slave {
    pcm "hw:Loopback,0,0"
    rate 48000
    #rate 44100
    periods 128
    period_time 0
    period_size 1024 # must be power of 2
    buffer_size 8192
  }
}

Just restart your audio playback, there's no thing like restarting ALSA. Archlinux uses dmix by default "for soundcards which do not support hardware mixing", and it continues to work as expected after these changes.

Record something

The rest is easy.

ffmpeg

ffmpeg -f alsa -i hw:1,1 -c:a flac output.flac

So why hw:1,1?

  • snd-aloop created a virtual sound card, which is "card 1" (after the default "card 0").
  • This card has two devices: 1 and 0.
  • We told ALSA to send the master output to card 1, device 0.
  • The loopback device loops this sound back to card 1, device 1, from where we can grab it.

Only one application can record at a time.

Make it permanent

I had to create two files:

$> cat /etc/modules-load.d/alsa-aloop.conf
snd_aloop

This just loads the module.

$> cat /etc/modprobe.d/alsa.conf 
options snd_hda_intel index=0
options snd-aloop index=1 enable=1

This makes sure the two "devices" stay in order: first the sound card, then the loopback.