#!/usr/bin/env bash ### CONFIG ### # Name of the virtual sink SINK_NAME="discord_sink" # Name of your real output device (auto-detected later) REAL_OUTPUT="" ################ set -e echo "=== Discord App-Audio Routing Script ===" echo "This will route ONLY one chosen application's audio to Discord." echo SINK_INPUTS=$(pactl list short sink-inputs | awk '{print $1}') if [[ -z "$SINK_INPUTS" ]]; then echo "No audio streams detected. Make sure the target app is playing audio!" exit 1 fi i=1 declare -A ID_MAP for ID in $SINK_INPUTS; do CLIENT_ID=$(pactl list short sink-inputs | awk -v id="$ID" '$1 == id {print $3}') CLIENT_NAME=$(pactl list short clients | awk -v cid="$CLIENT_ID" '$1 == cid {print $3}') # Remove quotes around client names, if any CLIENT_NAME=${CLIENT_NAME//\"/} echo "$i) $CLIENT_NAME (sink-input $ID)" ID_MAP[$i]=$ID i=$((i+1)) done echo read -p "Select the number of the app to route to Discord: " CHOICE echo TARGET_ID=${ID_MAP[$CHOICE]} if [[ -z "$TARGET_ID" ]]; then echo "Invalid choice." exit 1 fi echo $TARGET_ID # --- Detect real output device --- echo "[*] Detecting your real output device..." REAL_OUTPUT=$(pactl list short sinks | grep -E "RUNNING|IDLE" | head -n1 | awk '{print $2}') if [[ -z "$REAL_OUTPUT" ]]; then echo "Could not automatically detect real output device! Exiting." exit 1 fi echo " -> Real output device: $REAL_OUTPUT" echo # --- Create virtual sink --- echo "[*] Creating virtual sink '$SINK_NAME'..." pactl load-module module-null-sink sink_name=$SINK_NAME sink_properties=device.description="Discord_Share_Audio" >/dev/null # Virtual monitor name MONITOR="${SINK_NAME}.monitor" # --- Make virtual sink default --- echo "[*] Setting virtual sink as default output..." pactl set-default-sink $SINK_NAME # --- Create loopback so you can hear things --- echo "[*] Creating loopback so you hear the audio normally..." LOOPBACK_ID=$(pactl load-module module-loopback source=$MONITOR sink=$REAL_OUTPUT latency_msec=1) echo " -> Loopback module: $LOOPBACK_ID" echo echo "[*] Routing selected app (${TARGET_ID}) to $SINK_NAME..." pactl move-sink-input "$TARGET_ID" "$SINK_NAME" echo echo "===========================================================" echo "✔ Routing complete." echo "Start Discord screen share now — it will capture ONLY this app." echo echo "When you're done, press ENTER to restore normal audio." echo "===========================================================" read -p "" # --- Cleanup --- echo "[*] Restoring your real default output..." pactl set-default-sink $REAL_OUTPUT echo "[*] Removing loopback..." pactl unload-module "$LOOPBACK_ID" echo "[*] Removing virtual sink..." pactl unload-module module-null-sink echo "✔ Done. Audio restored."