🔧 Where my dotfiles lives in harmony and peace, most of the time
at main 118 lines 2.8 kB view raw
1#!/usr/bin/env bash 2set -euo pipefail 3 4error() { 5 printf "✗ %s\n" "$*" >&2 6 exit 1 7} 8 9usage() { 10 cat <<'EOF' 11Usage: 12 record-audio [options] [output-file] 13 14Records system audio (default sink monitor) and microphone (default source) using ffmpeg (MP3). 15Stops on Ctrl+C. 16 17Options: 18 --system-only Record only system audio (what you hear) 19 --mic-only Record only microphone 20 -o, --out FILE Output file 21 -h, --help Show help 22 23Default output: 24 recording-YYYYmmdd-HHMMSS.mp3 25EOF 26} 27 28require_cmd() { 29 command -v "$1" >/dev/null 2>&1 || error "Missing dependency: $1" 30} 31 32timestamp() { 33 date +%Y%m%d-%H%M%S 34} 35 36main() { 37 local mode="mix" 38 local out="" 39 40 while [[ $# -gt 0 ]]; do 41 case $1 in 42 --system-only) 43 mode="system" 44 shift 45 ;; 46 --mic-only) 47 mode="mic" 48 shift 49 ;; 50 -o|--out) 51 out="${2:-}" 52 [[ -n $out ]] || error "--out requires a file path" 53 shift 2 54 ;; 55 -h|--help) 56 usage 57 exit 0 58 ;; 59 *) 60 if [[ -z $out ]]; then 61 out="$1" 62 shift 63 else 64 error "Unknown argument: $1" 65 fi 66 ;; 67 esac 68 done 69 70 require_cmd pactl 71 require_cmd ffmpeg 72 73 if [[ -z $out ]]; then 74 out="recording-$(timestamp).mp3" 75 fi 76 77 if [[ -e $out ]]; then 78 error "Refusing to overwrite existing file: $out" 79 fi 80 81 local sink 82 local source 83 sink="$(pactl get-default-sink)" 84 source="$(pactl get-default-source)" 85 86 [[ -n $sink ]] || error "No default sink found" 87 [[ -n $source ]] || error "No default source found" 88 89 local monitor="${sink}.monitor" 90 91 printf "Recording mode: %s\n" "$mode" 92 printf "Default sink: %s\n" "$sink" 93 printf "Default source: %s\n" "$source" 94 printf "Output: %s\n" "$out" 95 printf "Stop: Ctrl+C\n" 96 97 case $mode in 98 system) 99 exec ffmpeg -f pulse -i "$monitor" -c:a libmp3lame -q:a 4 "$out" 100 ;; 101 mic) 102 exec ffmpeg -f pulse -i "$source" -c:a libmp3lame -q:a 4 "$out" 103 ;; 104 mix) 105 exec ffmpeg \ 106 -f pulse -i "$monitor" \ 107 -f pulse -i "$source" \ 108 -filter_complex '[0:a]aformat=sample_rates=48000:channel_layouts=stereo[a0];[1:a]aformat=sample_rates=48000:channel_layouts=stereo[a1];[a0][a1]amix=inputs=2:duration=longest:dropout_transition=0' \ 109 -c:a libmp3lame -q:a 4 \ 110 "$out" 111 ;; 112 *) 113 error "Unknown mode: $mode" 114 ;; 115 esac 116} 117 118main "$@"