pipi cucu
This commit is contained in:
@@ -6,15 +6,15 @@
|
||||
# Requires: sudo for kmsgrab, PulseAudio for audio capture
|
||||
# Audio is non-blocking (monitor source = passive tap)
|
||||
#
|
||||
# Auto-restarts on stall: a watchdog checks ffmpeg's frame counter
|
||||
# and kills/restarts if video freezes (DRM/VAAPI contention from
|
||||
# other apps using the GPU, e.g. video calls).
|
||||
# Auto-restarts on stall: watchdog checks output bytes + frame counter.
|
||||
# Also restarts immediately on fatal kmsgrab errors (DRM plane format
|
||||
# change from fullscreen / direct-scanout).
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
RECEIVER_IP="${1:-mcrndeb}"
|
||||
PORT="${2:-4444}"
|
||||
STALL_TIMEOUT=10 # seconds with no frame progress before restart
|
||||
STALL_TIMEOUT=10 # seconds with no progress before restart
|
||||
|
||||
# Let root access the user's PulseAudio session
|
||||
REAL_UID="${SUDO_UID:-$(id -u)}"
|
||||
@@ -33,7 +33,14 @@ echo "Streaming to: ${RECEIVER_IP}:${PORT}"
|
||||
ulimit -n 65536
|
||||
|
||||
PROGRESS_FILE=$(mktemp)
|
||||
trap 'rm -f "$PROGRESS_FILE"' EXIT
|
||||
FFLOG=$(mktemp)
|
||||
FFPID=""
|
||||
|
||||
cleanup() {
|
||||
[ -n "$FFPID" ] && kill "$FFPID" 2>/dev/null && wait "$FFPID" 2>/dev/null
|
||||
rm -f "$PROGRESS_FILE" "$FFLOG"
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
start_ffmpeg() {
|
||||
local args=(
|
||||
@@ -60,38 +67,57 @@ start_ffmpeg() {
|
||||
-hide_banner -progress "$PROGRESS_FILE"
|
||||
)
|
||||
|
||||
"${args[@]}" &
|
||||
> "$FFLOG"
|
||||
"${args[@]}" 2>"$FFLOG" &
|
||||
echo $!
|
||||
}
|
||||
|
||||
get_frame_count() {
|
||||
# -progress file writes key=value pairs; frame= is the video frame counter
|
||||
grep -oP '^frame=\K[0-9]+' "$PROGRESS_FILE" 2>/dev/null | tail -1
|
||||
get_progress_val() {
|
||||
grep -oP "^${1}=\K[0-9]+" "$PROGRESS_FILE" 2>/dev/null | tail -1
|
||||
}
|
||||
|
||||
fatal_kmsgrab_error() {
|
||||
grep -q "framebuffer format changed\|Error during demuxing" "$FFLOG" 2>/dev/null
|
||||
}
|
||||
|
||||
while true; do
|
||||
echo "--- Starting sender $(date) ---"
|
||||
> "$PROGRESS_FILE" # reset
|
||||
> "$PROGRESS_FILE"
|
||||
|
||||
FFPID=$(start_ffmpeg)
|
||||
echo "ffmpeg started: pid=$FFPID"
|
||||
|
||||
last_bytes=0
|
||||
last_frame=0
|
||||
stall_since=$SECONDS
|
||||
|
||||
while kill -0 "$FFPID" 2>/dev/null; do
|
||||
sleep 2
|
||||
sleep 1
|
||||
|
||||
cur_frame=$(get_frame_count)
|
||||
# Immediate restart on fatal kmsgrab errors (DRM plane format change)
|
||||
if fatal_kmsgrab_error; then
|
||||
echo "Fatal kmsgrab error — restarting immediately"
|
||||
kill "$FFPID" 2>/dev/null
|
||||
wait "$FFPID" 2>/dev/null
|
||||
break
|
||||
fi
|
||||
|
||||
cur_bytes=$(get_progress_val total_size)
|
||||
cur_bytes=${cur_bytes:-0}
|
||||
cur_frame=$(get_progress_val frame)
|
||||
cur_frame=${cur_frame:-0}
|
||||
|
||||
if (( cur_frame > last_frame )); then
|
||||
# Either metric advancing counts as healthy:
|
||||
# total_size: catches TCP output stalls (muxer blocked)
|
||||
# frame: catches kmsgrab/encoder stalls (audio keeps total_size ticking)
|
||||
if (( cur_bytes > last_bytes || cur_frame > last_frame )); then
|
||||
last_bytes=$cur_bytes
|
||||
last_frame=$cur_frame
|
||||
stall_since=$SECONDS
|
||||
fi
|
||||
|
||||
if (( SECONDS - stall_since > STALL_TIMEOUT )); then
|
||||
echo "Video stalled at frame $last_frame for ${STALL_TIMEOUT}s — killing ffmpeg"
|
||||
echo "Stream stalled at frame ${last_frame} / ${last_bytes}B for ${STALL_TIMEOUT}s — killing ffmpeg"
|
||||
kill "$FFPID" 2>/dev/null
|
||||
wait "$FFPID" 2>/dev/null
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user