19.04.2009 22:04

Recording sound from ALSA with JACK

Few months ago I wanted to record some music from a flash widget. It was supposed to be simple as per ALSA wiki. You just need to copy the PCM channel:

# ~/.asoundrc
# Recording sound going trough the card, capture with: 
#   $ arecord -t wav -D copy test.wav
pcm.copy {
    type plug
    slave {
        pcm hw
    route_policy copy
Well guess what it didn't work, no surprise there as Linux sound state is a complete mess. You can also try setting one of your channels as a capture source and then record from it... boring and unreliable, but let's mention it:
Try with this first:
$ amixer set 'Mix' cap

Or if you don't have a 'Mix' channel:
$ amixer set 'Capture' cap
$ amixer set 'Capture' 10%

Record with:
$ arecord -t wav -f cd test.wav
After I while I did get some results but they were terrible. After a few more web searches I saw that just about everyone recommends using Audacity for this. Well it turns out that Audacity tries to do the same thing, hence does it terribly. Interesting enough it was also one of the popular solutions for doing this on Windows too, I even tried it in moments of desperation and results were terrible even there. But all was not lost as there are numerous apps for Windows that can do it. I tried a few and to my surprise they were all more or less crap, those that did record something recorded it badly, sound was full of static, too low or too high etc.

But I didn't give up and ultimately I found a perfect solution. Resulting recordings were perfect - an exact copy of the original source. I did it with a little help from JACK and jack_capture. I won't cover the installation and setup of jackd but there is a nice graphical frontend called qjackctl that will get you started in no time. Many applications support JACK, and have audio output drivers for it (i.e. Mplayer). Once jackd is running and your application is using it you can start jack_capture and play the audio.

But what about applications that don't support JACK? To make it worse I needed to record sound from a flash widget and Adobe's flash plugin doesn't have JACK support. Here comes the tricky part, you have to route the sound from ALSA to JACK and then capture it using jack_capture. To do this you will need the ALSA plugins package which has a jack plugin. Once installed you can setup routing in your "~/.asoundrc":
# ~/.asoundrc
# Connect ALSA only applications to JACKD
#  - alsa-plugins package needs to be installed
pcm.!default {
        type plug
        slave { pcm "jack" }
pcm.jack {
        type jack
        playback_ports {
               0 alsa_pcm:playback_1
               1 alsa_pcm:playback_2
       	capture_ports {
               0 alsa_pcm:capture_1
               1 alsa_pcm:capture_2
When you visit the web page; flash plugin will send the audio to ALSA which will route it to the jack daemon to which you connected jack_capture which is by this point recording sound - a perfect and exact copy of the source (in "wav" format) which you can later convert to a high quality "ogg" with:
$ oggenc -q 10 file.wav -o file.ogg

Written by anrxc | Permalink | Filed under media