Přeskočit na obsah

Živá TV z antény do Plexu: Tvheadend + Antennas na Raspberry Pi

Živá TV z antény do Plexu: Tvheadend + Antennas na Raspberry Pi

Proč to celé

Pozemní DVB-T2 vysílání se dá na Raspberry Pi chytat a posílat do Plexu jako plnohodnotná živá TV i s programovým průvodcem. Jádrem je Tvheadend, který obsluhuje tuner, a Plex, který z toho dělá pohodlné rozhraní na televizi, mobilu i v prohlížeči.

Tvheadend má sice vestavěnou emulaci HDHomeRun, ale v praxi je nestabilní. Plex na televizi občas hlásil „Nelze naladit kanál“ a přehrávání prostě nenaběhlo. Řešením se ukázal malý proxy kontejner Antennas a hlavně důkladné vyladění Tvheadendu, který tuner zbytečně vytěžoval skenováním na pozadí.

Navazuju tím na starší článek RasPi – IPTV server z roku 2020. Tam Tvheadend běžel přímo v systému a na televizi se koukalo přes Kodi nebo VLC. Teď běží v Dockeru a všechno jde přes Plex.

V článku projdu celou cestu: od přípravy Raspberry Pi přes Docker, kritická nastavení Tvheadendu, napojení na Plex až po problémy, na které jsem při stavbě narazil. Na konci je bonus o přechodu z RPi 4 na RPi 5.

Co budete potřebovat

Stačí Raspberry Pi s TV HATem, anténa, Docker a Plex Media Server s Plex Pass.

KomponentaCo používám
PočítačRaspberry Pi 5 (funguje i RPi 4)
TunerSony CXD2880 DVB-T/T2 HAT (SPI, 1 tuner)
ÚložištěSD karta 16 GB+
OSRaspberry Pi OS 64-bit, Debian 13 Trixie
KontejneryDocker + Docker Compose
PlexPlex Media Server s Plex Pass (Live TV & DVR)
NahrávkyNAS přes NFS (volitelné)

V příkladech používám tuto síť: Raspberry Pi na 10.100.10.21, NAS s Plexem na 10.100.10.11. Adresy si upravte podle sebe.

Jak to do sebe zapadá

Tuner obsluhuje Tvheadend, Antennas mu dělá tlumočníka a Plex si myslí, že mluví s fyzickým HDHomeRun.

            [ Anténa DVB-T2 ]
                    │
  ┌─────────────────┼──── Raspberry Pi 5 · 10.100.10.21 · Docker ──┐
  │                 ▼                                              │
  │       [ Sony CXD2880 HAT ]                                     │
  │       SPI, 1 tuner, /dev/dvb/adapter0                          │
  │                 │                                              │
  │                 ▼                                              │
  │       [ Tvheadend :9981 ] ──── API ────► [ Antennas :5004 ]    │
  │       ladí multiplexy,                   překládá API          │
  │       profil pass, XMLTV EPG             na HDHomeRun          │
  └─────────────────┼──────────────────────────────┼───────────────┘
                    │ stream MPEG-TS + XMLTV EPG   │ lineup přes HDHR API
                    ▼                              │
       [ Plex Media Server ] ◄─────────────────────┘
       Synology NAS · 10.100.10.11
                    │
                    ▼
             [ Klienti ]
       TV: Direct Play i HEVC
       prohlížeč: HEVC se transkóduje

Antennas Plexu předává jen seznam kanálů. Samotný stream si Plex stahuje přímo z Tvheadendu na portu 9981, proto musí mít uživatel plex právo streamovat.

Příprava Raspberry Pi

Na čistém Raspberry Pi OS stačí aktualizace, statická IP, Docker a ověření, že systém vidí tuner.

Systém a statická IP

OS nahrajte přes Raspberry Pi Imager, kde rovnou nastavíte hostname, uživatele a SSH. Trixie spravuje síť přes NetworkManager:

sudo apt update && sudo apt upgrade -y

# název připojení zjistíte přes: nmcli connection show
sudo nmcli connection modify "Wired connection 1" \
  ipv4.method manual \
  ipv4.addresses 10.100.10.21/24 \
  ipv4.gateway 10.100.10.1 \
  ipv4.dns "10.100.10.1 8.8.8.8"
sudo nmcli connection down "Wired connection 1" && sudo nmcli connection up "Wired connection 1"

Po změně IP spadne SSH relace, připojte se na novou adresu.

Ověření TV HATu

Sony CXD2880 je připojený přes SPI. Na kernelu 6.12 se driver načte sám, žádný overlay v config.txt jsem nepotřeboval, a to ani na RPi 5 s novým čipem RP1.

dmesg | grep -iE "cxd2880|dvb"
ls -la /dev/dvb/adapter0/

Ve výpisu musí být Sony CXD2880 has successfully attached a v adresáři zařízení frontend0, demux0 a dvr0.

Docker

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
newgrp docker

NFS mount na NAS (volitelné)

Nahrávky a zálohy ukládám na NAS. Volby nofail a _netdev zajistí, že Pi nabootuje i bez dostupného NASu.

sudo apt install -y nfs-common
sudo mkdir -p /mnt/server
echo "10.100.10.11:/volume1/NAS-DOWNLOAD /mnt/server nfs vers=3,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,nofail,_netdev 0 0" | sudo tee -a /etc/fstab
sudo mount -a

Docker Compose: Tvheadend a Antennas

Oba kontejnery běží v jednom docker-compose.yml v režimu host, aby fungovalo SSDP a porty byly přímo na IP Raspberry Pi.

/opt/docker/docker-compose.yml
services:
  tvheadend:
    image: lscr.io/linuxserver/tvheadend:latest
    container_name: tvheadend
    network_mode: host
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Prague
    volumes:
      - /opt/docker/tvheadend/config:/config
      - /mnt/server:/recordings
    devices:
      - /dev/dvb:/dev/dvb
      - /dev/dri:/dev/dri
    restart: unless-stopped

  antennas:
    image: thejf/antennas:latest
    container_name: antennas
    network_mode: host
    environment:
      - TVHEADEND_URL=http://plex:HESLO@127.0.0.1:9981
      - ANTENNAS_URL=http://10.100.10.21:5004
      - TUNER_COUNT=1
      - DEVICE_UUID=2f70c0d7-90a3-4429-8275-cbeeee9cd605
    restart: unless-stopped
ParametrVýznam
PUID / PGIDID uživatele, výstup id -u a id -g
TVHEADEND_URLpřístup Antennas do Tvheadendu (uživatel plex)
ANTENNAS_URLadresa, kterou Antennas hlásí Plexu
TUNER_COUNTpočet fyzických tunerů, u CXD2880 HATu 1
DEVICE_UUIDlibovolné platné UUID, Plex podle něj zařízení pozná

TUNER_COUNT nenastavujte vyšší, než kolik tunerů opravdu máte. Plex by pak zkoušel sledovat a nahrávat paralelně a druhý požadavek by skončil chybou.

cd /opt/docker
docker compose up -d
docker logs tvheadend --tail 50

Web Tvheadendu najdete na http://10.100.10.21:9981, HDHomeRun API Antennas na http://10.100.10.21:5004/discover.json.

Nastavení Tvheadendu

Klíčem ke stabilitě je vypnout veškeré skenování na pozadí. S jedním tunerem každý sken obsadí tuner právě ve chvíli, kdy si o kanál řekne Plex, a výsledkem je „No input detected“.

U mě skenovaly hned čtyři vrstvy současně a v logu přibýval nový sken každých 10 sekund. Každou je potřeba vypnout zvlášť, protože jsou na různých místech konfigurace.

DVB-T síť

Configuration → DVB Inputs → Networks → DVB-T Network

ParametrHodnota
Network discoveryDisable
Skip startup scanzapnuto
Idle scan muxesvypnuto

Po prvotním naskenování smažte muxy, které trvale hlásí FAIL. Auto-discovery mi jich nasbíral 80, reálně funguje 7.

Seznam muxů v Tvheadendu: sedm frekvencí DVB-T, všechny ve stavu IDLE
Po úklidu zůstalo sedm muxů, skenování je v klidu (IDLE)

TV adaptér

Configuration → DVB Inputs → TV adapters → Sony CXD2880

ParametrHodnota
Idle scanvypnuto
Initial scanvypnuto
LNAzapnuto
# tune repeats2
Scan grace period15 s
Streaming priority10

Pozor: Idle scan na adaptéru je jiné nastavení než Idle scan muxes na síti. Vypnout je nutné obě.

Nastavení TV adaptéru Sony CXD2880 v Tvheadendu
Adaptér CXD2880: LNA zapnuté, Initial scan a Idle scan vypnuté, streaming priority 10

Stream profil pass

Configuration → Stream → Stream Profiles → pass

ParametrHodnota
Data start timeout15 s
Restart on errorzapnuto
Default priorityHigh
Rewrite PMT, PAT, SDT, NIT, EITzapnuto

Profil pass posílá MPEG-TS beze změny a přesně ten chce Plex. Profily webtv-* a matroska transkódují na Raspberry Pi, pro Plex je nepotřebujete a můžete je vypnout.

Stream profil pass v Tvheadendu
Profil pass: start timeout 15 s, priorita High, restart při chybě a přepis tabulek

EPG

Configuration → Channel / EPG → EPG Grabber

  • OTA cron stačí jednou denně v noci: 4 3 * * *
  • Vypněte „Force initial EPG grab at start-up“ u OTA i interních grabberů
  • Interní grabber cron nechte prázdný, pokud nepoužíváte externí XMLTV

Uživatelé a EPG pro Plex

Potřebujete dva účty: admin pro správu a plex jen pro streaming, který používá Antennas.

Configuration → Users → Access Entries a Passwords

ÚčetAdminStreamingWeb interfaceNetwork prefix
adminanoanoano0.0.0.0/0
plexneano + advancedne10.100.0.0/16

Nejdřív vytvořte admin a ověřte přihlášení v anonymním okně. Teprve pak omezte výchozí přístup, jinak se snadno zamknete.

Programový průvodce přes XMLTV

Tvheadend vystavuje EPG na adrese http://10.100.10.21:9981/xmltv/channels. Plex ji umí načíst jako vlastní průvodce.

Zádrhel: Tvheadend standardně vyžaduje Digest autentizaci a Plex umí v URL jen Basic (user:heslo@host). Výsledkem je obecná chyba „Při komunikaci s poskytovatelem nastala chyba“.

Řešením je wildcard přístup (uživatel ) jen s právem *Web interface, omezený na lokální síť. EPG pak Plex načte z URL bez hesla. Ověřit to jde jednoduše:

curl -s http://10.100.10.21:9981/xmltv/channels | head -20

Má vrátit XML začínající <?xml se seznamem kanálů.

Programový průvodce v Tvheadendu se seznamem pořadů
Programový průvodce v Tvheadendu, odtud si ho přes XMLTV bere Plex

Napojení na Plex

Plex přidá Antennas jako tuner HDHomeRun, stačí zadat IP a port ručně.

  1. Nastavení → Živá TV a DVR → Nastavit Plex DVR
  2. Automatické hledání v Dockeru často nic nenajde, klikněte na „Nevidíte svůj HDHomeRun?“
  3. Zadejte 10.100.10.21:5004, Plex najde „Silicondust HDHomeRun (Antennas)“
  4. Jako průvodce zvolte XMLTV s adresou http://10.100.10.21:9981/xmltv/channels a jazykem čeština
  5. Vyberte kanály, které chcete mít v Plexu

Kvalita překódování

Nastavení → Živá TV a DVR → zařízení → Nastavení

Kvalitu překódování nastavte na Původní formát. Při volbě „Nejvyšší kvalita“ Plex transkóduje každý stream a na slabším serveru to selže.

V nastavení transkodéru Plex serveru doporučuji:

ParametrHodnota
Kvalita převodníkuPreferovat vyšší rychlost kódování
Hardwarová akceleracezapnuto
HW dekódování videazapnuto
Dočasná složka pro překódovánísložka, do které má Plex právo zápisu

U poslední položky jsem na Synology narazil na Permission denied. Plex v takovém případě tiše padá na software a transkódování nestíhá.

HEVC: proč to na televizi jede a v prohlížeči ne

Kanály skupiny Nova na MUX 24 vysílají v HEVC (H.265). Televize je přehraje přímo, prohlížeč je musí nechat transkódovat a to je pro starší server těžké sousto.

KlientHEVCVýsledek
Apple TV, Samsung, LG, Android TVnativní dekodérDirect Play, bez transkódování
Webový prohlížečnepodporujePlex transkóduje HEVC → H.264

V logu Plexu se problém pozná podle hlášek PPS id out of range a podle fallback to software decoding. Můj Synology DS918+ má Intel Celeron J3455, jehož Quick Sync neumí dekódovat HEVC Main 10. Transkódování pak běží softwarově a v reálném čase nestíhá.

Pro živou TV na televizi to nevadí. Kdo chce sledovat i v prohlížeči, potřebuje Plex server s novějším Intel GPU (zhruba 10. generace a výš) nebo Apple Silicon. Výměna Raspberry Pi tady nepomůže, transkódování dělá Plex server, ne Pi.

Časté problémy

Většinu potíží odhalí log Tvheadendu: docker logs tvheadend -f --tail 50.

PříznakPříčinaŘešení
No input detected, Nelze naladit kanálsken na pozadí drží tunervypnout všechny scan vrstvy
v logu scan ... weight: 2 každých ~10 sIdle scan na adaptéru nebo sítiIdle scan a Idle scan muxes vypnout
chyba poskytovatele u XMLTV v PlexuDigest autentizacewildcard přístup pro LAN, URL bez hesla
prázdný lineup v Antennasšpatné heslo v TVHEADEND_URLověřit uživatele plex
PPS id out of range v PlexuHEVC v prohlížečisledovat na TV nebo silnější Plex server
hdhomerun server not enabledPlex zkouší starou emulaciignorovat, nebo HDHR zařízení v Plexu přidat znovu

Užitečné příkazy pro diagnostiku:

# Je tuner vidět?
dmesg | grep -iE "cxd2880|dvb"

# Co Antennas posílá Plexu
curl -s http://10.100.10.21:5004/lineup.json | python3 -m json.tool | head -30

# Jaké stream profily klienti skutečně používají
docker logs tvheadend 2>&1 | grep -oP 'profile="[^"]+"' | sort | uniq -c

Bonus: přechod z RPi 4 na RPi 5

Celá migrace zabrala zhruba hodinu a Plex si nového hardwaru ani nevšiml. Pomohlo, že nové Pi dostalo stejnou IP adresu i stejný config.

  1. Na starém Pi zastavit kontejnery a zazálohovat /opt/docker na NAS
  2. Na RPi 5 nahrát čistý Trixie, nastavit stejnou statickou IP, Docker a NFS
  3. Nasadit TV HAT a ověřit /dev/dvb/adapter0
  4. Rozbalit zálohu a spustit docker compose up -d
# záloha (na starém Pi)
cd /opt/docker && docker compose down
sudo tar -czf /mnt/server/backup/opt-docker-$(date +%F).tar.gz \
  --exclude='tvheadend/config/epgdb*' \
  --exclude='tvheadend/config/imagecache' \
  --exclude='tvheadend/config/backup' \
  -C /opt docker

# obnova (na novém Pi)
sudo tar -xzf /mnt/server/backup/opt-docker-DATUM.tar.gz -C /opt
cd /opt/docker && docker compose up -d

Obával jsem se, že SPI HAT bude na RPi 5 kvůli novému čipu RP1 potřebovat vlastní overlay. Nepotřeboval, kernel 6.12 ho rozpoznal sám.

Závěr

Výsledkem je stabilní živá TV v Plexu: kanál naběhne do dvou sekund a přepínání mezi multiplexy funguje bez výpadků. Největší ponaučení: problém nebyl v Plexu ani v hardwaru, ale ve skenování, které Tvheadend tiše provozoval na pozadí. Pokud vám živá TV „občas nejede“, začněte právě tam.

Sdílet článek LinkedIn Facebook

Napsat komentář

E-mail nebude zveřejněn.