Mantiene la copertina YouTube se il telefono cade e avvia ffmpeg sul nodo, non via SSH.

Il relay HLS→RTMPS resta sul worker/agent del nodo assegnato, così tre dirette contemporanee restano in onda sul sito e sul canale della società senza schermo nero.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-16 20:41:46 +02:00
co-authored by Cursor
parent bfb3115a64
commit baa6283a15
36 changed files with 1444 additions and 141 deletions
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Installa slate + relay-agent su un CPX già provisionato (una tantum, non per ogni diretta).
# STREAM_NODE_HOST=116.203.217.194 bash scripts/deploy/bootstrap_stream_node.sh
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
HOST="${STREAM_NODE_HOST:?Imposta STREAM_NODE_HOST (IPv4 pubblico del CPX)}"
SSH_KEY="${STREAM_NODE_SSH_KEY_HOST:-$HOME/.ssh/matchlivetv_stream_hetzner}"
SECRET="${STREAM_NODE_AGENT_SECRET:-mediamtx_webhook_dev_secret}"
SSH=(ssh -i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o IdentitiesOnly=yes "root@$HOST")
SCP=(scp -i "$SSH_KEY" -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o IdentitiesOnly=yes)
if [[ ! -f "$ROOT/infra/slates/offline.mp4" ]]; then
(cd "$ROOT/infra" && bash scripts/generate_slate.sh)
fi
"${SSH[@]}" "apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y python3 fonts-dejavu-core ffmpeg >/dev/null"
"${SSH[@]}" "mkdir -p /opt/stream-node /slates /var/log"
"${SCP[@]}" "$ROOT/infra/stream-node/relay-agent.py" "root@$HOST:/opt/stream-node/relay-agent.py"
"${SCP[@]}" "$ROOT/infra/slates/offline.mp4" "root@$HOST:/slates/offline.mp4"
"${SSH[@]}" "chmod 755 /opt/stream-node/relay-agent.py"
"${SSH[@]}" "cat >/opt/stream-node/agent.env <<EOF
STREAM_NODE_AGENT_SECRET=${SECRET}
STREAM_NODE_AGENT_LISTEN=0.0.0.0:9100
STREAM_NODE_LOCAL_HLS_URL=http://127.0.0.1:8888
STREAM_NODE_RELAY_LOG_DIR=/var/log
EOF
chmod 600 /opt/stream-node/agent.env"
"${SSH[@]}" "cat >/etc/systemd/system/mltv-relay-agent.service <<'EOF'
[Unit]
Description=Match Live TV YouTube relay agent
After=network-online.target
[Service]
Type=simple
EnvironmentFile=/opt/stream-node/agent.env
ExecStart=/usr/bin/python3 /opt/stream-node/relay-agent.py
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
EOF
pkill -f 'ffmpeg -nostdin' || true
systemctl daemon-reload
systemctl enable --now mltv-relay-agent.service
systemctl restart mltv-relay-agent.service
curl -fsS http://127.0.0.1:9100/health"
echo "bootstrap ok host=${HOST}"
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Avvia/ferma un worker ffmpeg per un nodo lab, riusando l'immagine Sidekiq di collaudo.
# Uso:
# STREAM_NODE_SLUG=ingest-lab-01 bash scripts/deploy/collaudo_relay_worker.sh up
# STREAM_NODE_SLUG=ingest-lab-01 bash scripts/deploy/collaudo_relay_worker.sh down
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
SLUG="${STREAM_NODE_SLUG:?Imposta STREAM_NODE_SLUG (es. ingest-lab-01)}"
ACTION="${1:-up}"
NAME="infra-sidekiq-relay-${SLUG}"
COMPOSE=(bash "$ROOT/scripts/deploy/collaudo_compose.sh")
case "$ACTION" in
up)
docker rm -f "$NAME" >/dev/null 2>&1 || true
"${COMPOSE[@]}" run -d --name "$NAME" --no-deps \
-e STREAM_NODE_SLUG="$SLUG" \
-e YOUTUBE_RELAY_WORKER=1 \
-e HOSTNAME="$SLUG" \
-e STREAM_NODE_LOCAL_RTMP_URL=rtmp://mediamtx:1935 \
-e STREAM_NODE_LOCAL_HLS_URL=http://mediamtx:8888 \
sidekiq \
bash -lc "bundle exec sidekiq -c \${RELAY_MAX_CONCURRENT:-2} -q youtube_relay_${SLUG} -e production"
echo "relay worker up name=${NAME} queue=youtube_relay_${SLUG}"
;;
down)
docker rm -f "$NAME" >/dev/null 2>&1 || true
echo "relay worker down name=${NAME}"
;;
logs)
docker logs -f --tail=80 "$NAME"
;;
*)
echo "Uso: STREAM_NODE_SLUG=ingest-lab-01 $0 up|down|logs" >&2
exit 1
;;
esac
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
# Worker coda youtube_relay_<slug>: parla con l'agent sul CPX (ffmpeg gira lì).
#
# Lab locale:
# STREAM_NODE_SLUG=ingest-lab-01 bash scripts/dev_sidekiq_relay.sh up
#
# CPX:
# STREAM_NODE_SLUG=ingest-01 STREAM_NODE_RELAY_AGENT_URL=http://1.2.3.4:9100 bash scripts/dev_sidekiq_relay.sh up
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SLUG="${STREAM_NODE_SLUG:-ingest-lab-01}"
ACTION="${1:-up}"
NAME="infra-sidekiq-relay-${SLUG}"
export STREAM_NODE_SLUG="$SLUG"
cd "$ROOT/infra"
case "$ACTION" in
up)
docker rm -f "$NAME" >/dev/null 2>&1 || true
extra=()
if [[ -n "${STREAM_NODE_RELAY_AGENT_URL:-}" ]]; then
extra+=(
-e STREAM_NODE_RELAY_AGENT_URL="$STREAM_NODE_RELAY_AGENT_URL"
-e STREAM_NODE_AGENT_SECRET="${STREAM_NODE_AGENT_SECRET:-mediamtx_webhook_dev_secret}"
-e STREAM_NODE_LOCAL_RTMP_URL=rtmp://127.0.0.1:1935
-e STREAM_NODE_LOCAL_HLS_URL=http://127.0.0.1:8888
)
fi
docker compose --profile stream-node run -d --no-deps --name "$NAME" \
-e STREAM_NODE_SLUG="$SLUG" \
-e HOSTNAME="$SLUG" \
-e YOUTUBE_RELAY_WORKER=1 \
-e RELAY_MAX_CONCURRENT="${RELAY_MAX_CONCURRENT:-1}" \
"${extra[@]}" \
sidekiq_relay
echo "relay worker up name=${NAME} queue=youtube_relay_${SLUG} agent=${STREAM_NODE_RELAY_AGENT_URL:-local}"
;;
down)
docker rm -f "$NAME" >/dev/null 2>&1 || true
echo "relay worker down name=${NAME}"
;;
logs)
docker logs -f --tail=80 "$NAME"
;;
*)
echo "Uso: STREAM_NODE_SLUG=ingest-01 $0 up|down|logs" >&2
exit 1
;;
esac