Blog | About | Hire Me

Recording Audio From the Terminal

by Philippe Olivier
Created 2021-04-30

This simple script records the sound input and output of your computer to a file. This can be useful for recording Zoom meetings and the like.

The required software for this is:

The name of the recordings are a simple timestamp, and they are saved in a directory of your choice (in this example, ~/recordings):

  FILENAME=`date +'%Y-%m-%d-%H:%M:%S'`
  TARGET="$HOME/recordings/"
  mkdir -p $TARGET

We now need to find the names of our input (microphone) and output (speaker/headphones) devices. In my case:

  $ pactl list | grep Name | grep input
Name: alsa_input.pci-0000_00_1f.3.analog-stereo
  $ pactl list | grep Name | grep output
Name: alsa_output.pci-0000_00_1f.3.analog-stereo
Name: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor

My input device is alsa_input.pci-0000_00_1f.3.analog-stereo, and my output device is alsa_output.pci-0000_00_1f.3.analog-stereo:

  INPUT_DEVICE="alsa_input.pci-0000_00_1f.3.analog-stereo"
  OUTPUT_DEVICE="alsa_output.pci-0000_00_1f.3.analog-stereo"

The device/sink/loopback configuration is simple:

Microphone ----------------\
 (device)                   \ (loopback)
                             \
                              \
                               \
                              Sink -----------> parec
                               /
                              /
                             /
     (device)               / (loopback)
Speaker/headphones --------/

We must create the modules and load them, and capture their id to unload them later:

  SINK_NAME="mysink"
  SINK1=$(pactl load-module module-null-sink sink_name=$SINK_NAME)
  LOOPBACK1=$(pactl load-module module-loopback source=$OUTPUT_DEVICE.monitor sink=$SINK_NAME)
  LOOPBACK2=$(pactl load-module module-loopback source=$INPUT_DEVICE sink=$SINK_NAME)

Now the command to record:

  parec -d $SINK_NAME.monitor | oggenc -b 192 -o $TARGET$FILENAME.ogg --raw -

We use Ctrl-C to stop the recording. We must trap the signal to make sure that we unload the modules, and revert pulseaudio to its initial state:

  function unload_modules() {
      pactl unload-module $LOOPBACK2
      pactl unload-module $LOOPBACK1
      pactl unload-module $SINK1
      echo
      echo "Recording saved to $TARGET$FILENAME.ogg."
      exit
  }

  trap unload_modules EXIT

Here is the whole script:

  FILENAME=`date +'%Y-%m-%d-%H:%M:%S'`
  TARGET="$HOME/recordings/"
  mkdir -p $TARGET

  INPUT_DEVICE="alsa_input.pci-0000_00_1f.3.analog-stereo"
  OUTPUT_DEVICE="alsa_output.pci-0000_00_1f.3.analog-stereo"

  SINK_NAME="mysink"
  SINK1=$(pactl load-module module-null-sink sink_name=$SINK_NAME)
  LOOPBACK1=$(pactl load-module module-loopback source=$OUTPUT_DEVICE.monitor sink=$SINK_NAME)
  LOOPBACK2=$(pactl load-module module-loopback source=$INPUT_DEVICE sink=$SINK_NAME)

  parec -d $SINK_NAME.monitor | oggenc -b 192 -o $TARGET$FILENAME.ogg --raw -

  function unload_modules() {
      pactl unload-module $LOOPBACK2
      pactl unload-module $LOOPBACK1
      pactl unload-module $SINK1
      echo
      echo "Recording saved to $TARGET$FILENAME.ogg."
      exit
  }

  trap unload_modules EXIT
This website is generated by Emacs.