Files
Curator/makov-cam/setup.md
T

7.2 KiB
Raw Blame History

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.1 stačí.
  • Jellyfin běží v Docker kontejneru na tomtéž hostu (běžný případ) — 127.0.0.1 uvnitř 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:
    docker 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š
    
    a použij --bind <ta-gateway-IP> (viz makov-cam-http.service). Pokud by Jellyfin běžel v jiné VM, změň --bind na 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

  1. Dashboard → Live TV → Tuner Devices → + (Add)
  2. Typ: M3U Tuner
  3. 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).
  4. Save → Jellyfin načte kanál "Makov - Krmítko" do Live TV
  5. 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í.
  6. 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ů

  • ffmpeg pořá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. Zkontroluj journalctl -u makov-cam.service -n 50.
  • yt-dlp: command not found v service logu — systemd nepoužívá tvůj interaktivní $PATH; ověř which yt-dlp a případně uprav ExecStart v makov-cam.sh/skriptu na plnou cestu (/usr/local/bin/yt-dlp apod.), nebo nainstaluj přes sudo 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 4s drží ~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-dlp novou verzí přehrávače — drž yt-dlp aktuá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řes yt-dlp -F <url>). Skript proto primárně používá -f 'bestvideo+bestaudio/best' a při dvou vrácených URL pustí ffmpeg se dvěma -i vstupy (-map 0:v -map 1:a); jedna URL = fallback na progresivní formát, pokud se zase objeví.