#!/bin/bash # Restreams the Makov webcam (YouTube live "Krmítko") into a local HLS # playlist that never goes stale for the viewer — Jellyfin always points at # this fixed local path, not at YouTube's own signed/expiring URL. # # When ffmpeg dies (the YouTube URL expired, network hiccup, stream briefly # ended, ...) this script simply exits; systemd (Restart=always) starts it # again, which resolves a *fresh* URL via yt-dlp. Nothing needs to be done # by hand. set -euo pipefail YOUTUBE_URL="https://www.youtube.com/watch?v=F0fsV1GGZ3M" OUT_DIR="/var/lib/jellyfin-iptv/hls" OUT_FILE="${OUT_DIR}/makov.m3u8" mkdir -p "$OUT_DIR" # This live stream only serves separate video-only/audio-only HLS renditions # (no combined progressive format), so we resolve both and let ffmpeg mux # them. "bestvideo+bestaudio" makes yt-dlp -g print exactly two URLs, video # then audio; fall back to "best" in case a progressive format reappears. mapfile -t STREAM_URLS < <(yt-dlp -g -f 'bestvideo+bestaudio/best' "$YOUTUBE_URL") VIDEO_URL="${STREAM_URLS[0]:-}" AUDIO_URL="${STREAM_URLS[1]:-}" if [ -z "$VIDEO_URL" ]; then echo "yt-dlp nevrátilo žádnou URL (stream offline, nebo se YouTube brání) — končím, systemd to za chvíli zkusí znovu." >&2 exit 1 fi if [ -z "$AUDIO_URL" ]; then # Progressive fallback matched: single URL carries both video and audio. exec ffmpeg -nostdin -loglevel warning \ -re -i "$VIDEO_URL" \ -c copy \ -f hls -hls_time 4 -hls_list_size 6 \ -hls_flags delete_segments+omit_endlist \ -hls_segment_filename "${OUT_DIR}/makov_%03d.ts" \ "$OUT_FILE" fi exec ffmpeg -nostdin -loglevel warning \ -re -i "$VIDEO_URL" -re -i "$AUDIO_URL" \ -map 0:v -map 1:a \ -c copy \ -f hls -hls_time 4 -hls_list_size 6 \ -hls_flags delete_segments+omit_endlist \ -hls_segment_filename "${OUT_DIR}/makov_%03d.ts" \ "$OUT_FILE"