#!/bin/bash # CHT Sender: muxed video + audio over TCP/mpegts # Source: Wayland (kmsgrab) + desktop audio + webcam mic # Usage: ./stream_av.sh [RECEIVER_IP] [PORT] # # Requires: sudo for kmsgrab, PulseAudio for audio capture # Audio is non-blocking (monitor source = passive tap) set -uo pipefail RECEIVER_IP="${1:-mcrndeb}" PORT="${2:-4444}" # Let root access the user's PulseAudio session REAL_UID="${SUDO_UID:-$(id -u)}" export PULSE_SERVER="unix:/run/user/${REAL_UID}/pulse/native" # Find the default sink's monitor source (desktop audio - what you hear) MONITOR=$(PULSE_SERVER="$PULSE_SERVER" pactl info 2>/dev/null | grep "Default Sink" | awk '{print $3}').monitor # Webcam mic - find by partial match (serial number varies) WEBCAM_MIC=$(PULSE_SERVER="$PULSE_SERVER" pactl list short sources 2>/dev/null | grep -i "C922" | awk '{print $2}' || true) echo "Monitor source: $MONITOR" echo "Webcam mic: ${WEBCAM_MIC:-not found}" echo "Streaming to: ${RECEIVER_IP}:${PORT}" if [ -n "$WEBCAM_MIC" ]; then echo "Webcam mic found, mixing desktop + mic" # Two pulse inputs: desktop monitor + webcam mic, mixed into one audio stream exec ffmpeg \ -init_hw_device drm=drm:/dev/dri/card0 \ -init_hw_device vaapi=va@drm \ -device /dev/dri/card0 -f kmsgrab -framerate 30 -i - \ -f pulse -i "$MONITOR" \ -f pulse -i "$WEBCAM_MIC" \ -filter_complex "[1:a][2:a]amix=inputs=2:duration=longest[aout]" \ -map 0:v -map "[aout]" \ -vf 'hwmap=derive_device=vaapi,scale_vaapi=w=1920:h=1080:format=nv12,fps=30' \ -c:v h264_vaapi -qp 20 -g 30 -keyint_min 30 -bf 0 \ -c:a aac -b:a 128k \ -flush_packets 1 -fflags nobuffer -muxdelay 0 -muxpreload 0 \ -f mpegts "tcp://${RECEIVER_IP}:${PORT}" \ -hide_banner else echo "No webcam mic, desktop audio only" exec ffmpeg \ -init_hw_device drm=drm:/dev/dri/card0 \ -init_hw_device vaapi=va@drm \ -device /dev/dri/card0 -f kmsgrab -framerate 30 -i - \ -f pulse -i "$MONITOR" \ -vf 'hwmap=derive_device=vaapi,scale_vaapi=w=1920:h=1080:format=nv12,fps=30' \ -c:v h264_vaapi -qp 20 -g 30 -keyint_min 30 -bf 0 \ -c:a aac -b:a 128k \ -flush_packets 1 -fflags nobuffer -muxdelay 0 -muxpreload 0 \ -f mpegts "tcp://${RECEIVER_IP}:${PORT}" \ -hide_banner fi