Skip to content

Instantly share code, notes, and snippets.

@ergolyam
Last active January 15, 2026 23:41
Show Gist options
  • Select an option

  • Save ergolyam/f1b36dfd3c9a3568366ea4674a427323 to your computer and use it in GitHub Desktop.

Select an option

Save ergolyam/f1b36dfd3c9a3568366ea4674a427323 to your computer and use it in GitHub Desktop.
Script for automated audio capture from Firefox to Telegram Desktop
#!/usr/bin/env bash
set -euo pipefail
SLEEP_SEC=2
OUTPUT_APP=""
INPUT_APP=""
declare -A LINKS_DONE=()
usage() {
cat <<EOF
Usage:
$0 --output "Output App Name" --input "Input App Name" [--sleep SECONDS]
EOF
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--output) OUTPUT_APP="$2"; shift 2 ;;
--input) INPUT_APP="$2"; shift 2 ;;
--sleep) SLEEP_SEC="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Unknown argument: $1"; usage ;;
esac
done
if [[ -z "$INPUT_APP" || -z "$OUTPUT_APP" ]]; then
echo "ERROR: --input and --output are required"
usage
fi
cleanup() {
echo
echo "Resetting – removing PipeWire links ..."
for key in "${!LINKS_DONE[@]}"; do
out="${key%%|*}"
in="${key#*|}"
pw-link -d "$out" "$in" 2>/dev/null || true
done
exit 0
}
trap cleanup INT TERM
prune_links() {
declare -A PORTS=()
while read -r p; do
[[ -n "$p" ]] && PORTS["$p"]=1
done < <(pw-link -o -I | awk '{print $1}')
while read -r p; do
[[ -n "$p" ]] && PORTS["$p"]=1
done < <(pw-link -i -I | awk '{print $1}')
for key in "${!LINKS_DONE[@]}"; do
out="${key%%|*}"
in="${key#*|}"
if [[ -z "${PORTS[$out]+x}" || -z "${PORTS[$in]+x}" ]]; then
unset 'LINKS_DONE[$key]'
fi
done
}
echo "Intercepting audio:"
echo " OUTPUT: $OUTPUT_APP"
echo " INPUT : $INPUT_APP"
echo " SLEEP : $SLEEP_SEC sec"
echo
last_sig=""
while true; do
mapfile -t FL_IDS < <(pw-link -o -I | awk -v app="$OUTPUT_APP" '$0 ~ app ":output_FL" {print $1}')
mapfile -t FR_IDS < <(pw-link -o -I | awk -v app="$OUTPUT_APP" '$0 ~ app ":output_FR" {print $1}')
IN_FL="$(pw-link -i -I | awk -v app="$INPUT_APP" '$0 ~ app ":input_FL" {print $1; exit}')"
IN_FR="$(pw-link -i -I | awk -v app="$INPUT_APP" '$0 ~ app ":input_FR" {print $1; exit}')"
if [[ -z "${IN_FL:-}" || -z "${IN_FR:-}" || "${#FL_IDS[@]}" -eq 0 || "${#FR_IDS[@]}" -eq 0 ]]; then
echo "One of the devices is missing – waiting..."
last_sig=""
prune_links
sleep "$SLEEP_SEC"
continue
fi
sig="IN_FL=$IN_FL IN_FR=$IN_FR FL=${FL_IDS[*]} FR=${FR_IDS[*]}"
if [[ "$sig" != "$last_sig" ]]; then
echo "Ports changed or appeared – ensuring links..."
last_sig="$sig"
fi
for out in "${FL_IDS[@]}"; do
pw-link "$out" "$IN_FL" 2>/dev/null || true
LINKS_DONE["$out|$IN_FL"]=1
done
for out in "${FR_IDS[@]}"; do
pw-link "$out" "$IN_FR" 2>/dev/null || true
LINKS_DONE["$out|$IN_FR"]=1
done
prune_links
sleep "$SLEEP_SEC"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment