lilith-platform.live/scripts/hotel-srt-push.sh
Natalie f49b7df43d feat(broadcast): LLM-controlled remote OBS + SRT relay for low-upload hotel streams with high-bitrate multi-RTMP from DO
- New scripts/provision-stream-droplet.sh (modeled on gpu one) for cheap DO droplet with docker + v4l2loopback + mediamtx ready.
- scripts/hotel-srt-push.sh: macOS ffmpeg one-liner helper for reliable modest-bitrate SRT contribution over bad WiFi.
- New @features/broadcast/controller/: self-contained Bun server with embedded Tailwind chat UI, full xAI Grok-4.3 tool-calling agent, pure-WebSocket obs-websocket v5 client, dynamic destination + ffmpeg fanout manager.
- Full docs + RUNBOOK with architecture, provisioning, hotel push, OBS notes, security, troubleshooting, and verification notes.
- Matches the 'RTMP relay for simulcast' vision already promised in performer marketing.

The hotel side sends ~3 Mbps SRT. All compute, final encode, and broadcast bitrate (to Twitch/YouTube/etc.) happens on the DO network. Control is natural language chat to the LLM.
2026-06-28 13:30:39 -04:00

95 lines
3 KiB
Bash
Executable file

#!/usr/bin/env bash
# Hotel / weak-WiFi SRT contribution push to a quinn.cast relay droplet.
#
# This is the "just a video stream from my hotel wifi" side.
# Everything heavy (final encode, bitrate, multi-platform fanout, OBS production) happens on DO.
#
# Usage:
# ./scripts/hotel-srt-push.sh --help
# ./scripts/hotel-srt-push.sh --target 203.0.113.77:8890 --streamid publish:live --bitrate 3500
#
# macOS only (avfoundation). Linux/Windows users: adapt the -f and -i lines.
#
# Tips for terrible hotel WiFi:
# - Keep bitrate modest (2500-5000k). Let the droplet do the heavy lifting.
# - Use a wired connection to the hotel router if possible.
# - Close everything else using upload.
# - The SRT protocol + mediamtx gives you packet recovery that plain RTMP does not.
set -euo pipefail
TARGET=""
STREAMID="publish:live"
BITRATE_K=3500
FRAMERATE=30
RES="1280x720"
AUDIO_DEV=":0" # default; list devices with ffmpeg -f avfoundation -list_devices true -i ""
VIDEO_DEV="0" # usually the first camera
while [[ $# -gt 0 ]]; do
case "$1" in
--target) TARGET="$2"; shift 2 ;;
--streamid) STREAMID="$2"; shift 2 ;;
--bitrate) BITRATE_K="$2"; shift 2 ;;
--res) RES="$2"; shift 2 ;;
--framerate) FRAMERATE="$2"; shift 2 ;;
--video) VIDEO_DEV="$2"; shift 2 ;;
--audio) AUDIO_DEV="$2"; shift 2 ;;
--list-devices)
ffmpeg -f avfoundation -list_devices true -i "" || true
exit 0
;;
-h|--help)
cat <<EOF
Hotel SRT push helper
Required:
--target IP:PORT e.g. 203.0.113.77:8890 (the droplet's public SRT listener)
Optional:
--streamid STR default: publish:live
--bitrate K default 3500 (keep low on hotel WiFi)
--res WxH default 1280x720
--framerate N default 30
--video INDEX avfoundation video device (default 0)
--audio INDEX avfoundation audio device (default :0 for default mic)
--list-devices show available cameras/mics then exit
Example (most common):
./scripts/hotel-srt-push.sh --target 203.0.113.77:8890 --bitrate 3000
Once running, open the LLM controller on the droplet and say "start broadcast".
EOF
exit 0
;;
*) echo "Unknown arg $1"; exit 1 ;;
esac
done
if [[ -z "$TARGET" ]]; then
echo "ERROR: --target is required (droplet public IP + SRT port)"
exit 1
fi
MAXRATE=$(( BITRATE_K + 500 ))
BUFSIZE=$(( BITRATE_K * 2 ))
echo "==> Hotel SRT push"
echo " target: srt://${TARGET}?streamid=${STREAMID}"
echo " bitrate: ${BITRATE_K}k (max ${MAXRATE}k)"
echo " resolution:${RES} @ ${FRAMERATE}fps"
echo " devices: video=${VIDEO_DEV} audio=${AUDIO_DEV}"
echo
echo "Hit Ctrl-C to stop. The droplet will keep the last good frame if packets are lost."
exec ffmpeg \
-f avfoundation \
-framerate "${FRAMERATE}" \
-video_size "${RES}" \
-i "${VIDEO_DEV}:${AUDIO_DEV}" \
-c:v libx264 -preset veryfast -tune zerolatency \
-b:v "${BITRATE_K}k" -maxrate "${MAXRATE}k" -bufsize "${BUFSIZE}k" \
-g $(( FRAMERATE * 2 )) \
-c:a aac -b:a 128k -ar 48000 \
-f mpegts \
"srt://${TARGET}?streamid=${STREAMID}"