codeblog code is freedom — patching my itch

April 19, 2009

recording from PulseAudio

Filed under: Blogging,Debian,General,Multimedia,Ubuntu — kees @ 11:42 am

Every PulseAudio “Sink” has a “Source” named “monitor”. This lets you attach to a given Sink and chain more stuff to it, for example, recording the audio that is playing through PulseAudio at any given moment. This is very handy for creating, for example, PubQuiz-style clips of songs, movies, etc.

Here is a script to find the monitor for the most recently added Sink, record from it, and shove it through “sox” to get a WAV instead of raw sound data (requires recent sox, Pulse, etc):

#!/bin/bash
WAV="$1"
if [ -z "$WAV" ]; then
    echo "Usage: $0 OUTPUT.WAV" >&2
    exit 1
fi
rm -f "$WAV"

# Get sink monitor:
MONITOR=$(pactl list | egrep -A2 '^(\*\*\* )?Source #' | \
    grep 'Name: .*\.monitor$' | awk '{print $NF}' | tail -n1)
echo "set-source-mute ${MONITOR} false" | pacmd >/dev/null

# Record it raw, and convert to a wav
echo "Recording to $WAV ..."
echo "Close this window to stop"
parec -d "$MONITOR" | sox -t raw -r 44k -sLb 16 -c 2 - "$WAV"

© 2009 – 2011, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

19 Comments

  1. Hehe: sox sox: Rate value `44k’ is not a positive number

    Full info here: http://paste.pocoo.org/show/113298/

    Comment by Vadim P. — April 19, 2009 @ 5:05 pm

  2. Right, you need a newer sox for that command line.

    Comment by kees — April 19, 2009 @ 8:14 pm

  3. Would you provide a link for an updated sox? The latest version in the Ubuntu repositories still causes this problem. Thanks.

    Comment by 3pipe — April 20, 2009 @ 1:50 am

  4. The sox from Ubuntu Jaunty (9.04) works for this example. If you can’t use sox, just record to the raw file, and import it manually into audacity or something to save it.

    Comment by kees — April 20, 2009 @ 7:17 am

  5. The GStreamer version :)

    $ gst-launch-0.10 pulsesrc device=$(pactl list | grep -A1 ‘^\*\*\* Source #’ | \
    grep ‘^Name: .*\.monitor$’ | cut -d” ” -f2 | tail -n1) \
    ! queue ! audio/x-raw-int,rate=44100,channels=2 \
    ! audioconvert ! lame vbr=4 vbr-quality=2 \
    ! filesink location=dump.mp3

    Comment by xuzo — April 20, 2009 @ 7:35 am

  6. Thanks xuzo! Your script worked great.

    Comment by Vadim P. — April 20, 2009 @ 3:07 pm

  7. Thanks for the quick and easy solution to ‘loop back’ recording. I like this variation, for outputting an ogg file:
    parec –format=s16le –device=”$MONITOR” | oggenc –raw –quiet –quality=4 -o $WAV –

    Comment by Ben B — May 15, 2009 @ 7:41 pm

  8. Excellent, thanks for that: works a treat!

    Comment by the_phoenix — September 24, 2009 @ 11:47 pm

  9. Thanks, works great!

    I replaced “44k” by “44100”. This avoids the SOX problem pointed out by vadim, kees and 3pipe and, at the same time, gets you 44.1khz files, not 44khz ones.

    (44.1khz is what you’d want for burning on CDs or converting to MP3)

    Comment by hacklschorsch — October 26, 2009 @ 4:39 am

  10. Update the script for more recent PulseAudio (as found in Karmic):
    http://outflux.net/software/pa-clone

    Comment by kees — November 18, 2009 @ 7:39 am

  11. Thanks so much. I just wasted a bunch of time trying to do this the wrong way and it is such a relief to have found your solution.

    Comment by Ben Smith — January 14, 2010 @ 8:24 am

  12. Thank you for this script !
    I added the ability to start when a sound occurs and to split in multiple files after 2s of silence. Just replace the line begining with “parec -d “$MONITOR” | sox…” with this one :
    parec -d “$MONITOR” | sox -t raw -r 44100 -sLb 16 -c 2 – “$WAV” silence 1 0.50 0.1% 1 2.0 0.1% : newfile : restart

    Comment by Youch — August 15, 2010 @ 7:17 am

  13. Can we do same thing with ffmpeg?

    Comment by Jahil — August 17, 2010 @ 11:53 pm

  14. pactl is a localised application so you should call it with LANG=C.

    Comment by josef — October 10, 2010 @ 2:11 am

  15. pactl found in Ubuntu 10.10 (Maverick) has slightly different output. Change lines 10 and 11 to:

    MONITOR=$(pactl list | grep -A2 ‘^\Source ‘ | \
    grep ‘Name: .*\.monitor$’ | cut -d” ” -f2)

    Comment by kaapstorm — January 16, 2011 @ 12:36 pm

  16. (Sorry about that. That regex should be “^Source”, not “^\Source”. The “\” will be ignored, so it doesn’t really matter. But I’m picky.)

    Comment by kaapstorm — January 16, 2011 @ 12:38 pm

  17. Very useful script.
    On my machine I had to insert these lines before recording:

    # Unmute monitor :
    echo “set-source-mute ${MONITOR} false” | pacmd

    Without them I was just recording silence..

    Comment by eric — March 6, 2011 @ 2:05 pm

  18. Thanks for the updates! I’ve adjusted the script for new “pactl list” output and added the unmuting.

    Comment by kees — April 6, 2011 @ 12:01 pm

  19. Just what I was looking for. I did make a slight change:

    #!/bin/bash
    WAV=”$1″
    if [ -z “$WAV” ]; then
    echo 1>&2 Usage: pa-rec wavefile
    exit 1
    fi
    rm -f “$WAV”
    # Get sink monitor:
    MONITORS=$(pactl list | egrep -A2 ‘^(\*\*\* )?Source #’ | grep ‘Name: .*\.monitor$’ | awk ‘{print $NF ” ” $NF }’)
    MONITOR=$(kdialog –menu “Select Monitor:” $MONITORS)
    echo “set-source-mute ${MONITOR} false” | pacmd >/dev/null
    # Record it raw, and convert to a wav
    echo “Recording $MONITOR to $WAV …”
    echo “^C to stop”
    parec -d $MONITOR | sox -t raw -r 44k -sLb 16 -c 2 – $WAV

    Obviously I use KDE.

    Comment by Al Williams — July 12, 2011 @ 12:24 pm

Powered by WordPress