7.2 KiB
Makov webkamera → Jellyfin (Live TV)
Restreamuje YouTube live přenos ("Krmítko", https://www.youtube.com/watch?v=F0fsV1GGZ3M) do lokálního HLS, na který se Jellyfin dívá přes stabilní adresu. Když YouTube odkaz vyprší nebo spadne, systemd proces sám restartuje a natáhne novou URL — divák/Jellyfin si ničeho nevšimne.
0) Kam skript patří
Toto musí běžet na stejném stroji (resp. za stejnou veřejnou IP), jako
Jellyfin — YouTube vrací streamovací URL svázanou s IP adresou, ze které
byla vyžádána (yt-dlp -g). Pokud poběží jinde než Jellyfin, ffmpeg dostane
403 a nikdy se nerozjede.
1) Závislosti
sudo apt install -y ffmpeg python3
sudo pip install -U yt-dlp # nebo pipx install yt-dlp — apt verze bývá stará
# a YouTube ji rád rozbije
Ověř, že yt-dlp a ffmpeg jedou z shellu bez chyby:
yt-dlp --version
ffmpeg -version
2) Uživatel a oprávnění
Vlastní, neprivilegovaný systémový účet — obě služby pod ním běží:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin makov-cam
sudo mkdir -p /var/lib/jellyfin-iptv/hls
sudo chown -R makov-cam:makov-cam /var/lib/jellyfin-iptv
Pokud je yt-dlp nainstalované přes snap (which yt-dlp ukazuje
/snap/bin/yt-dlp), potřebuje při startu zapisovatelný domovský adresář —
a to i přes --no-create-home, protože domov si zjišťuje přímo z
/etc/passwd, ne z proměnné $HOME (tu přenastavenou v service souboru
ignoruje). Bez toho skončí na Permission denied: mkdir /home/makov-cam.
Vytvoř mu ho ručně:
sudo mkdir -p /home/makov-cam
sudo chown makov-cam:makov-cam /home/makov-cam
sudo chmod 750 /home/makov-cam
(Pokud yt-dlp instaluješ přes pip/pipx dle kroku 1, tenhle problém
nenastává a krok lze přeskočit.)
3) Nasazení souborů
sudo install -m 755 makov-cam.sh /usr/local/bin/makov-cam.sh
sudo install -m 644 makov-cam.service /etc/systemd/system/
sudo install -m 644 makov-cam-http.service /etc/systemd/system/
sudo systemctl daemon-reload
4) Spuštění
sudo systemctl enable --now makov-cam.service
sudo systemctl enable --now makov-cam-http.service
Ověření:
systemctl status makov-cam.service makov-cam-http.service
journalctl -u makov-cam.service -f # živě sleduj log ffmpeg/yt-dlp
# do pár vteřin by se měl objevit playlist a segmenty:
ls -la /var/lib/jellyfin-iptv/hls/
# a mělo by jít stáhnout přes HTTP:
curl -sI http://127.0.0.1:8888/hls/makov.m3u8
makov-cam-http.service je svázaná (BindsTo=) na makov-cam.service — když
restream spadne/restartuje, HTTP server padne/naskočí s ním, ať nikdy
neservíruje mrtvý/prázdný playlist. Pozor: BindsTo= jen zajišťuje, že HTTP
server spadne, když spadne hlavní služba — nezajišťuje, že se s ní i sám
nastartuje. Po enable --now obou služeb to není problém (obě se spustí),
ale pokud jen restartuješ makov-cam.service ručně, zkontroluj/restartuj i
makov-cam-http.service.
HTTP server poslouchá jen na jedné IP (--bind), ne na 0.0.0.0 — nemá cenu
ho vystavovat celé síti, stačí odkud se na něj bude dívat Jellyfin:
- Jellyfin běží přímo na hostu (ne v kontejneru):
--bind 127.0.0.1stačí. - Jellyfin běží v Docker kontejneru na tomtéž hostu (běžný případ) —
127.0.0.1uvnitř kontejneru je jeho vlastní loopback, ne hostitelův, takže na hostitelův HTTP server se tak nedostane. Zjisti gateway IP té docker sítě, na které kontejner běží, a naviaž se na ni:a použijdocker inspect <jellyfin-container> --format '{{.HostConfig.NetworkMode}}' docker inspect <jellyfin-container> --format '{{json .NetworkSettings.Networks}}' # z výstupu vezmi "Gateway", např. 172.19.0.1 — tam se z kontejneru dostaneš--bind <ta-gateway-IP>(vizmakov-cam-http.service). Pokud by Jellyfin běžel v jiné VM, změň--bindna IP, na které je pro ni dosažitelný, a případně otevři firewall jen pro tenhle port a jen z její IP.
5) Playlist pro Jellyfin
WorkingDirectory HTTP služby je /var/lib/jellyfin-iptv (rodič hls/), aby
šel přes stejný server servírovat i samotný .m3u playlist — to se hodí,
pokud Jellyfin (typicky v kontejneru) nevidí souborový systém hostitele a
tuner tak musí načíst playlist přes HTTP URL, ne lokální cestou.
Vytvoř /var/lib/jellyfin-iptv/makov.m3u:
#EXTM3U
#EXTINF:-1 tvg-id="makov-krmitko" tvg-name="Makov - Krmítko",Makov - Krmítko
http://<BIND_IP>:8888/hls/makov.m3u8
kde <BIND_IP> je stejná adresa, na kterou je navázaný makov-cam-http.service
(viz krok 4).
6) Nastavení v Jellyfinu
- Dashboard → Live TV → Tuner Devices → + (Add)
- Typ: M3U Tuner
- File or URL:
- Jellyfin na hostu s přístupem k souborovému systému: lokální cesta
/var/lib/jellyfin-iptv/makov.m3u. - Jellyfin v kontejneru (nevidí hostitelův FS): HTTP URL
http://<BIND_IP>:8888/makov.m3u(viz krok 5).
- Jellyfin na hostu s přístupem k souborovému systému: lokální cesta
- Save → Jellyfin načte kanál "Makov - Krmítko" do Live TV
- Doporučeno: Dashboard → Live TV → Guide Providers — pro tenhle kanál žádného není třeba (žádný EPG), Jellyfin ho ukáže jako kanál bez programu, což nevadí.
- Zkontroluj přehrávání v Live TV sekci hlavního rozhraní.
Protože kanál pořád ukazuje na stejnou lokální adresu, odpadá starost o
obnovování guide dat nebo expiraci URL na Jellyfin straně — o to se stará jen
makov-cam.service na pozadí.
7) Autostart po restartu serveru
enable v kroku 4 už zajistil start při bootu. Rychlá kontrola:
systemctl is-enabled makov-cam.service makov-cam-http.service
Řešení problémů
ffmpegpořád padá / v logu 403 od googlevideo.com — nejčastěji IP mismatch (viz bod 0): stroj, co spouštíyt-dlp -g/ffmpeg, musí mít stejnou veřejnou IP jako to, odkud by se stream normálně přehrával. Zkontrolujjournalctl -u makov-cam.service -n 50.yt-dlp: command not foundv service logu — systemd nepoužívá tvůj interaktivní$PATH; ověřwhich yt-dlpa případně upravExecStartvmakov-cam.sh/skriptu na plnou cestu (/usr/local/bin/yt-dlpapod.), nebo nainstaluj přessudo pip install, aby šel do/usr/local/bin.- Playlist v Jellyfinu jede, ale sekundy/minuty výpadku při refreshi —
normální,
hls_list_size 6×hls_time 4sdrží ~24s okno; při restartu streamu je pár vteřin díra, než naběhnou nové segmenty. Jde zkrátit/prodloužit úpravou těch dvou hodnot ve skriptu. - YouTube někdy dočasně rozbije
yt-dlpnovou verzí přehrávače — držyt-dlpaktuální (sudo pip install -U yt-dlp, klidně jako týdenní cron). ERROR: Requested format is not available— stream v tu chvíli nenabízí žádný kombinovaný (progresivní) formát, jen oddělené video-only/audio-only HLS řady (ověř přesyt-dlp -F <url>). Skript proto primárně používá-f 'bestvideo+bestaudio/best'a při dvou vrácených URL pustíffmpegse dvěma-ivstupy (-map 0:v -map 1:a); jedna URL = fallback na progresivní formát, pokud se zase objeví.