136 lines
3.4 KiB
Bash
136 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
RECORDINGS_DIR="$SCRIPT_DIR/recordings"
|
||
|
|
mkdir -p "$RECORDINGS_DIR"
|
||
|
|
|
||
|
|
OUTPUT="$RECORDINGS_DIR/call_$(date +%Y%m%d_%H%M%S).mp3"
|
||
|
|
|
||
|
|
# Argument parsing
|
||
|
|
SHOW_INPUTS=false
|
||
|
|
for arg in "$@"; do
|
||
|
|
[[ "$arg" == "--show-inputs" ]] && SHOW_INPUTS=true
|
||
|
|
done
|
||
|
|
|
||
|
|
# Detect the default audio sink via PipeWire metadata
|
||
|
|
DEFAULT_SINK=$(pw-metadata 0 2>/dev/null \
|
||
|
|
| awk -F"'" '/default\.audio\.sink/ { print $4 }' \
|
||
|
|
| grep -o '"name":"[^"]*"' \
|
||
|
|
| cut -d'"' -f4)
|
||
|
|
|
||
|
|
if [[ -z "$DEFAULT_SINK" ]]; then
|
||
|
|
echo "ERROR: Could not detect default audio sink." >&2
|
||
|
|
echo "Run ./list-sources.sh to see available devices." >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
MONITOR_SOURCE="${DEFAULT_SINK}.monitor"
|
||
|
|
|
||
|
|
# --- show-inputs mode ---
|
||
|
|
if $SHOW_INPUTS; then
|
||
|
|
BAR_WIDTH=30
|
||
|
|
DB_MIN=-60
|
||
|
|
DB_MAX=0
|
||
|
|
|
||
|
|
render_bar() {
|
||
|
|
local label="$1"
|
||
|
|
local db="$2"
|
||
|
|
local bar=""
|
||
|
|
local filled=0
|
||
|
|
|
||
|
|
if [[ -n "$db" ]]; then
|
||
|
|
# Clamp to range
|
||
|
|
local clamped
|
||
|
|
clamped=$(awk -v v="$db" -v lo="$DB_MIN" -v hi="$DB_MAX" \
|
||
|
|
'BEGIN { if (v < lo) v=lo; if (v > hi) v=hi; print v }')
|
||
|
|
filled=$(awk -v v="$clamped" -v lo="$DB_MIN" -v hi="$DB_MAX" -v w="$BAR_WIDTH" \
|
||
|
|
'BEGIN { printf "%d", (v - lo) / (hi - lo) * w }')
|
||
|
|
fi
|
||
|
|
|
||
|
|
local empty=$(( BAR_WIDTH - filled ))
|
||
|
|
|
||
|
|
# Color based on level
|
||
|
|
local color="\033[32m" # green
|
||
|
|
if [[ -n "$db" ]]; then
|
||
|
|
color=$(awk -v v="$db" 'BEGIN {
|
||
|
|
if (v >= -3) { print "\033[31m" }
|
||
|
|
else if (v >= -12) { print "\033[33m" }
|
||
|
|
else { print "\033[32m" }
|
||
|
|
}')
|
||
|
|
fi
|
||
|
|
|
||
|
|
bar="${color}"
|
||
|
|
local i
|
||
|
|
for (( i=0; i<filled; i++ )); do bar+="█"; done
|
||
|
|
for (( i=0; i<empty; i++ )); do bar+="░"; done
|
||
|
|
bar+="\033[0m"
|
||
|
|
|
||
|
|
local db_str="${db:- ---}"
|
||
|
|
printf " %-13s: [%b] %6s dB\n" "$label" "$bar" "$db_str"
|
||
|
|
}
|
||
|
|
|
||
|
|
echo "=========================================="
|
||
|
|
echo " Input Monitor (Ctrl+C to exit)"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
TMP_MIC=$(mktemp)
|
||
|
|
TMP_SYS=$(mktemp)
|
||
|
|
|
||
|
|
ffmpeg -loglevel info -f pulse -i default \
|
||
|
|
-af ebur128 -f null - 2>"$TMP_MIC" &
|
||
|
|
PID_MIC=$!
|
||
|
|
|
||
|
|
ffmpeg -loglevel info -f pulse -i "$MONITOR_SOURCE" \
|
||
|
|
-af ebur128 -f null - 2>"$TMP_SYS" &
|
||
|
|
PID_SYS=$!
|
||
|
|
|
||
|
|
cleanup() {
|
||
|
|
kill "$PID_MIC" "$PID_SYS" 2>/dev/null || true
|
||
|
|
rm -f "$TMP_MIC" "$TMP_SYS"
|
||
|
|
tput cnorm
|
||
|
|
echo ""
|
||
|
|
exit 0
|
||
|
|
}
|
||
|
|
trap cleanup INT TERM
|
||
|
|
|
||
|
|
tput civis # hide cursor
|
||
|
|
|
||
|
|
# Reserve two lines
|
||
|
|
printf "\n\n"
|
||
|
|
|
||
|
|
while true; do
|
||
|
|
MIC_DB=$(grep -oP 'M:\s*\K[-0-9.]+' "$TMP_MIC" 2>/dev/null | tail -1 || true)
|
||
|
|
SYS_DB=$(grep -oP 'M:\s*\K[-0-9.]+' "$TMP_SYS" 2>/dev/null | tail -1 || true)
|
||
|
|
|
||
|
|
printf "\033[2A" # move up 2 lines
|
||
|
|
render_bar "Mikrofon" "$MIC_DB"
|
||
|
|
render_bar "System Audio" "$SYS_DB"
|
||
|
|
|
||
|
|
sleep 0.1
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- Recording mode ---
|
||
|
|
echo "=========================================="
|
||
|
|
echo " Call Recorder"
|
||
|
|
echo "=========================================="
|
||
|
|
echo " Microphone : default"
|
||
|
|
echo " System audio: $MONITOR_SOURCE"
|
||
|
|
echo " Output file : $OUTPUT"
|
||
|
|
echo "------------------------------------------"
|
||
|
|
echo " Press Ctrl+C to stop recording."
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
ffmpeg -loglevel warning \
|
||
|
|
-f pulse -i default \
|
||
|
|
-f pulse -i "$MONITOR_SOURCE" \
|
||
|
|
-filter_complex "amix=inputs=2:duration=longest:normalize=0" \
|
||
|
|
-c:a libmp3lame -b:a 128k \
|
||
|
|
"$OUTPUT"
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "Recording saved to: $OUTPUT"
|