diff --git a/fedac/nixos/configuration.nix b/fedac/nixos/configuration.nix index 28de987aa2..b1b4b42445 100644 --- a/fedac/nixos/configuration.nix +++ b/fedac/nixos/configuration.nix @@ -175,20 +175,24 @@ in } ''; - # SRT streamer: pushes notepat framebuffer over WiFi to OBS on Windows, - # which then forwards to TikTok Live. + # SRT streamer: pushes notepat video + audio to silo.aesthetic.computer + # via MediaMTX relay. Viewers pull RTMP/SRT/HLS from silo. # # Opt-in: only starts if /mnt/stream.conf exists on the USB config partition. - # Create /mnt/stream.conf with: - # HOST=192.168.1.100 # Windows host IP on LAN - # PORT=9000 # SRT port (OBS Media Source listens here) - # BITRATE=6M # encode bitrate - # FRAMERATE=60 # capture fps - # SRT_LATENCY=40 # ms — lower = less latency, more fragile on bad WiFi - # WIDTH=1280 # output width (scale from native) - # HEIGHT=720 # output height + # Minimal stream.conf (just enable with defaults): + # CHANNEL=my-device + # + # Optional overrides in stream.conf: + # HOST=silo.aesthetic.computer # relay server (default: silo) + # PORT=9000 # SRT port + # BITRATE=6M # encode bitrate + # FRAMERATE=60 # capture fps + # SRT_LATENCY=120 # ms — tuned for internet (not LAN) + # WIDTH=1280 # output width + # HEIGHT=720 # output height + # AUDIO_BITRATE=128k # audio encode bitrate systemd.services.ac-native-stream = { - description = "AC Native SRT streamer (to OBS → TikTok)"; + description = "AC Native SRT streamer (to silo relay)"; after = [ "ac-native-kiosk.service" "mount-usb-config.service" ]; wants = [ "ac-native-kiosk.service" ]; wantedBy = [ "multi-user.target" ]; @@ -206,12 +210,12 @@ in serviceConfig = { Type = "simple"; Restart = "on-failure"; - RestartSec = 3; + RestartSec = 5; EnvironmentFile = "/mnt/stream.conf"; ExecStartPre = pkgs.writeShellScript "ac-native-stream-wait" '' # Give the kiosk a moment to grab DRM master and start rendering - sleep 2 + sleep 3 for _ in $(seq 1 40); do ls /dev/dri/card* >/dev/null 2>&1 && break @@ -227,22 +231,26 @@ in ExecStart = pkgs.writeShellScript "ac-native-stream" '' set -u - HOST="''${HOST:?HOST not set in /mnt/stream.conf}" + # Defaults tuned for internet relay via silo + HOST="''${HOST:-silo.aesthetic.computer}" PORT="''${PORT:-9000}" + CHANNEL="''${CHANNEL:-$(hostname)}" BITRATE="''${BITRATE:-6M}" FRAMERATE="''${FRAMERATE:-60}" - SRT_LATENCY="''${SRT_LATENCY:-40}" + SRT_LATENCY="''${SRT_LATENCY:-120}" WIDTH="''${WIDTH:-1280}" HEIGHT="''${HEIGHT:-720}" + AUDIO_BITRATE="''${AUDIO_BITRATE:-128k}" CARD="$(ls /dev/dri/card* 2>/dev/null | head -n1)" [ -n "$CARD" ] || { echo "[stream] no DRM card"; exit 1; } - URL="srt://''${HOST}:''${PORT}?mode=caller&latency=''${SRT_LATENCY}&pkt_size=1316&tlpktdrop=1" - echo "[stream] capturing $CARD at ''${FRAMERATE}fps → $URL" + STREAMID="publish:/''${CHANNEL}" + URL="srt://''${HOST}:''${PORT}?mode=caller&streamid=''${STREAMID}&latency=''${SRT_LATENCY}&pkt_size=1316&tlpktdrop=1" + echo "[stream] channel: ''${CHANNEL}" + echo "[stream] capturing $CARD at ''${FRAMERATE}fps" echo "[stream] encode: h264_vaapi ''${WIDTH}x''${HEIGHT} @ ''${BITRATE}" - - AUDIO_BITRATE="''${AUDIO_BITRATE:-128k}" + echo "[stream] → $URL" exec ${pkgs.ffmpeg-full}/bin/ffmpeg \ -hide_banner -loglevel warning \ diff --git a/silo/stream/deploy.fish b/silo/stream/deploy.fish new file mode 100755 index 0000000000..e5b41792ad --- /dev/null +++ b/silo/stream/deploy.fish @@ -0,0 +1,125 @@ +#!/usr/bin/env fish +# Deploy MediaMTX streaming relay to silo.aesthetic.computer +# +# Usage: +# fish deploy.fish # Full deploy (download binary + config + systemd) +# fish deploy.fish --config # Config-only update (no restart unless binary changed) + +set RED '\033[0;31m' +set GREEN '\033[0;32m' +set YELLOW '\033[1;33m' +set NC '\033[0m' + +set SCRIPT_DIR (dirname (status --current-filename)) +set VAULT_DIR "$SCRIPT_DIR/../../aesthetic-computer-vault" +set SSH_KEY "$VAULT_DIR/home/.ssh/id_rsa" +set SILO_HOST "silo.aesthetic.computer" +set SILO_USER "root" +set REMOTE_DIR "/opt/mediamtx" +set MEDIAMTX_VERSION "1.12.2" +set MEDIAMTX_URL "https://github.com/bluenviron/mediamtx/releases/download/v$MEDIAMTX_VERSION/mediamtx_v{$MEDIAMTX_VERSION}_linux_amd64.tar.gz" + +set CONFIG_ONLY false +if contains -- --config $argv + set CONFIG_ONLY true +end + +if not test -f $SSH_KEY + echo -e "$RED x SSH key not found: $SSH_KEY$NC" + exit 1 +end + +echo -e "$GREEN-> Testing SSH connection to $SILO_HOST...$NC" +if not ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o ConnectTimeout=10 $SILO_USER@$SILO_HOST "echo ok" &>/dev/null + echo -e "$RED x Cannot connect to $SILO_HOST$NC" + exit 1 +end + +# Upload config +echo -e "$GREEN-> Uploading mediamtx.yml...$NC" +ssh -i $SSH_KEY $SILO_USER@$SILO_HOST "mkdir -p $REMOTE_DIR" +scp -i $SSH_KEY -o StrictHostKeyChecking=no \ + $SCRIPT_DIR/mediamtx.yml \ + $SILO_USER@$SILO_HOST:$REMOTE_DIR/ + +if test $CONFIG_ONLY = true + echo -e "$GREEN-> Config-only: reloading mediamtx...$NC" + ssh -i $SSH_KEY $SILO_USER@$SILO_HOST "systemctl reload mediamtx 2>/dev/null || systemctl restart mediamtx" + echo -e "$GREEN Done.$NC" + exit 0 +end + +# Download + install binary on remote +echo -e "$GREEN-> Installing MediaMTX v$MEDIAMTX_VERSION on $SILO_HOST...$NC" +ssh -i $SSH_KEY $SILO_USER@$SILO_HOST " + cd $REMOTE_DIR + if test -f mediamtx && ./mediamtx --version 2>&1 | grep -q '$MEDIAMTX_VERSION'; then + echo 'Already at v$MEDIAMTX_VERSION, skipping download' + else + curl -fsSL '$MEDIAMTX_URL' -o /tmp/mediamtx.tar.gz + tar -xzf /tmp/mediamtx.tar.gz -C $REMOTE_DIR mediamtx + rm /tmp/mediamtx.tar.gz + chmod +x $REMOTE_DIR/mediamtx + echo 'Installed MediaMTX v$MEDIAMTX_VERSION' + fi +" + +# Create systemd service +echo -e "$GREEN-> Setting up systemd service...$NC" +ssh -i $SSH_KEY $SILO_USER@$SILO_HOST " +cat > /etc/systemd/system/mediamtx.service << 'UNIT' +[Unit] +Description=MediaMTX streaming relay (AC Native) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/opt/mediamtx/mediamtx /opt/mediamtx/mediamtx.yml +ExecReload=/bin/kill -HUP \$MAINPID +Restart=on-failure +RestartSec=5 +LimitNOFILE=65536 + +[Install] +WantedBy=multi-user.target +UNIT + +systemctl daemon-reload +systemctl enable mediamtx +systemctl restart mediamtx +sleep 2 +systemctl is-active mediamtx +" + +set STATUS $status +if test $STATUS -eq 0 + echo -e "$GREEN MediaMTX is running.$NC" +else + echo -e "$RED x MediaMTX failed to start. Check logs:$NC" + echo -e "$YELLOW ssh -i $SSH_KEY $SILO_USER@$SILO_HOST journalctl -u mediamtx -n 30$NC" + exit 1 +end + +# Open firewall ports +echo -e "$GREEN-> Opening firewall ports (9000/udp SRT, 1935/tcp RTMP, 8888/tcp HLS)...$NC" +ssh -i $SSH_KEY $SILO_USER@$SILO_HOST " + if command -v ufw >/dev/null 2>&1; then + ufw allow 9000/udp comment 'MediaMTX SRT' + ufw allow 1935/tcp comment 'MediaMTX RTMP' + ufw allow 8888/tcp comment 'MediaMTX HLS' + elif command -v firewall-cmd >/dev/null 2>&1; then + firewall-cmd --permanent --add-port=9000/udp + firewall-cmd --permanent --add-port=1935/tcp + firewall-cmd --permanent --add-port=8888/tcp + firewall-cmd --reload + else + echo 'No firewall tool found — ports may already be open' + fi +" + +echo "" +echo -e "$GREEN Done. MediaMTX relay deployed to $SILO_HOST$NC" +echo -e "$GREEN SRT push: srt://$SILO_HOST:9000?streamid=publish:/$NC" +echo -e "$GREEN RTMP pull: rtmp://$SILO_HOST:1935/$NC" +echo -e "$GREEN HLS view: http://$SILO_HOST:8888/$NC" diff --git a/silo/stream/mediamtx.yml b/silo/stream/mediamtx.yml new file mode 100644 index 0000000000..d841a271d5 --- /dev/null +++ b/silo/stream/mediamtx.yml @@ -0,0 +1,33 @@ +# MediaMTX relay config for AC Native live streaming. +# Accepts SRT push from ac-native devices, serves RTMP/HLS for viewers. +# +# Stream paths are channel names (e.g. /jeffrey, /notepat-001). +# Push: srt://silo.aesthetic.computer:9000?streamid=publish:/ +# Pull: rtmp://silo.aesthetic.computer:1935/ +# srt://silo.aesthetic.computer:9000?streamid=read:/ +# HLS: http://silo.aesthetic.computer:8888/ + +logLevel: info +logDestinations: [stdout] + +# Allow any path — each ac-native device picks its own channel name. +paths: + all_others: + +# SRT: ac-native devices push here +srt: yes +srtAddress: :9000 + +# RTMP: OBS / TikTok Studio pulls from here +rtmp: yes +rtmpAddress: :1935 + +# HLS: browser preview +hls: yes +hlsAddress: :8888 +hlsAlwaysRemux: yes + +# Disable unused protocols +rtsp: no +webrtc: no +srtpEnabled: no