Paste
Bash
whip-printer-stream.sh (command line WHIP on raspi)
Created 49d ago · 11 views
Language
Bash
Lines
178
Characters
4574
Bash · teal-dock-83
#!/usr/bin/env bash
set -euo pipefail
CAM=/dev/video0
KEY_FILE=/opt/ai/conf/whip-key
START_DELAY=20
CHECK_URL=https://whip.hobostreamer.com/
BACKOFF=5
MAX_BACKOFF=300
choose_video_size() {
if ! command -v v4l2-ctl >/dev/null 2>&1; then
printf '%s\n' '640x480'
return
fi
local size
size=$(v4l2-ctl -d "$CAM" --list-formats-ext 2>/dev/null | awk '
/Size: Discrete/ {
sz = $3;
split(sz, dims, "x");
width = dims[1] + 0;
height = dims[2] + 0;
area = width * height;
if (width <= 640 && height <= 480) {
candidate = area "|" sz;
} else {
candidate = "";
}
next
}
/Interval: Discrete .*30(\.000)? fps/ && candidate {
print candidate;
candidate = "";
}
' | sort -t'|' -k1,1nr | head -n 1 | cut -d'|' -f2)
if [[ -z "$size" ]]; then
printf '%s\n' '640x480'
else
printf '%s\n' "$size"
fi
}
choose_video_bitrate() {
case "$1" in
1280x720) printf '%s\n' '1500k' ;;
1024x576|960x720) printf '%s\n' '1200k' ;;
640x480) printf '%s\n' '900k' ;;
640x360) printf '%s\n' '900k' ;;
*) printf '%s\n' '900k' ;;
esac
}
choose_buffer_size() {
case "$1" in
1500k) printf '%s\n' '3000k' ;;
1200k) printf '%s\n' '2400k' ;;
900k) printf '%s\n' '1800k' ;;
*) printf '%s\n' '1800k' ;;
esac
}
choose_frame_rate() {
case "$1" in
1280x720) printf '%s\n' '15' ;;
640x480) printf '%s\n' '20' ;;
*) printf '%s\n' '30' ;;
esac
}
choose_input_format() {
local target="$1"
if ! command -v v4l2-ctl >/dev/null 2>&1; then
printf '%s\n' 'mjpeg'
return
fi
local format
format=$(v4l2-ctl -d "$CAM" --list-formats-ext 2>/dev/null | awk -v target="$target" '
/^[[:space:]]*\[[0-9]+\]:/ {
line = $0;
gsub(/^[[:space:]]*\[[0-9]+\]:[[:space:]]*\x27/, "", line);
gsub(/\x27.*$/, "", line);
curfmt = line;
next
}
/^[[:space:]]*Size: Discrete/ {
if ($3 == target) {
size_ok = 1;
} else {
size_ok = 0;
}
next
}
/^[[:space:]]*Interval: Discrete .*30(\.000)? fps/ && size_ok {
if (curfmt == "YUYV") {
print "yuyv422";
exit
}
if (curfmt == "MJPG") {
print "mjpeg";
exit
}
}
')
if [[ -z "$format" ]]; then
printf '%s\n' 'mjpeg'
else
printf '%s\n' "$format"
fi
}
check_connectivity() {
if command -v curl >/dev/null 2>&1; then
curl -fsS --connect-timeout 10 "$CHECK_URL" >/dev/null 2>&1 && return 0
elif command -v ping >/dev/null 2>&1; then
ping -c 1 -W 2 8.8.8.8 >/dev/null 2>&1 && return 0
fi
return 1
}
if [[ "$START_DELAY" -gt 0 ]]; then
echo "$(date) startup delay: waiting $START_DELAY seconds for network"
sleep "$START_DELAY"
fi
while true; do
if [[ ! -c "$CAM" ]]; then
echo "$(date) camera missing: $CAM"
sleep 10
continue
fi
if [[ ! -f "$KEY_FILE" ]]; then
echo "$(date) key file missing: $KEY_FILE"
sleep "$BACKOFF"
BACKOFF=$(( BACKOFF * 2 ))
if (( BACKOFF > MAX_BACKOFF )); then BACKOFF=$MAX_BACKOFF; fi
continue
fi
STREAM_KEY="$(tr -d '\r\n ' < "$KEY_FILE")"
URL="https://whip.hobostreamer.com/whip/50?key=$STREAM_KEY"
if ! check_connectivity; then
echo "$(date) network/HoboStreamer unreachable, waiting $BACKOFF seconds"
sleep "$BACKOFF"
BACKOFF=$(( BACKOFF * 2 ))
if (( BACKOFF > MAX_BACKOFF )); then BACKOFF=$MAX_BACKOFF; fi
continue
fi
VIDEO_SIZE="$(choose_video_size)"
VIDEO_BITRATE="$(choose_video_bitrate "$VIDEO_SIZE")"
VIDEO_BUFSIZE="$(choose_buffer_size "$VIDEO_BITRATE")"
VIDEO_FPS="$(choose_frame_rate "$VIDEO_SIZE")"
VIDEO_FORMAT="$(choose_input_format "$VIDEO_SIZE")"
echo "$(date) using camera resolution $VIDEO_SIZE at $VIDEO_BITRATE (bufsize=$VIDEO_BUFSIZE) fps=$VIDEO_FPS format=$VIDEO_FORMAT"
ffmpeg -hide_banner -loglevel info \
-f v4l2 -input_format "$VIDEO_FORMAT" -video_size "$VIDEO_SIZE" -framerate "$VIDEO_FPS" -i "$CAM" \
-f alsa -i default \
-vf format=yuv420p \
-c:v libx264 -preset ultrafast -tune zerolatency \
-profile:v baseline -level 3.0 \
-x264-params "keyint=30:min-keyint=30:scenecut=0:force-cfr=1:repeat-headers=1" \
-b:v "$VIDEO_BITRATE" -maxrate "$VIDEO_BITRATE" -bufsize "$VIDEO_BUFSIZE" \
-c:a libopus -b:a 64k -ar 48000 \
-ts_buffer_size 20M \
-f whip "$URL"
echo "$(date) FFmpeg exited. retrying in $BACKOFF seconds."
sleep "$BACKOFF"
BACKOFF=$(( BACKOFF * 2 ))
if (( BACKOFF > MAX_BACKOFF )); then BACKOFF=$MAX_BACKOFF; fi
done
More pastes
Browse all →
TEXT
27 views · 27d ago
TEXT
25 views · 27d ago
TEXT
14 views · 28d ago
TEXT
13 views · 28d ago
TEXT
15 views · 30d ago
TEXT
12 views · 30d ago
TEXT
12 views · 30d ago
TEXT
19 views · 31d ago
TEXT
15 views · 31d ago
TEXT
19 views · 31d ago
TEXT
11 views · 31d ago
TEXT
13 views · 32d ago
TEXT
8 views · 33d ago
TEXT
8 views · 33d ago
TEXT
13 views · 33d ago
TEXT
9 views · 33d ago