Last active
January 15, 2026 23:41
-
-
Save ergolyam/f1b36dfd3c9a3568366ea4674a427323 to your computer and use it in GitHub Desktop.
Script for automated audio capture from Firefox to Telegram Desktop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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