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.
| Komponenta | Co používám |
|---|---|
| Počítač | Raspberry Pi 5 (funguje i RPi 4) |
| Tuner | Sony CXD2880 DVB-T/T2 HAT (SPI, 1 tuner) |
| Úložiště | SD karta 16 GB+ |
| OS | Raspberry Pi OS 64-bit, Debian 13 Trixie |
| Kontejnery | Docker + Docker Compose |
| Plex | Plex Media Server s Plex Pass (Live TV & DVR) |
| Nahrávky | NAS 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.
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
| Parametr | Význam |
|---|---|
PUID / PGID | ID uživatele, výstup id -u a id -g |
TVHEADEND_URL | přístup Antennas do Tvheadendu (uživatel plex) |
ANTENNAS_URL | adresa, kterou Antennas hlásí Plexu |
TUNER_COUNT | počet fyzických tunerů, u CXD2880 HATu 1 |
DEVICE_UUID | libovolné 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
| Parametr | Hodnota |
|---|---|
| Network discovery | Disable |
| Skip startup scan | zapnuto |
| Idle scan muxes | vypnuto |
Po prvotním naskenování smažte muxy, které trvale hlásí FAIL. Auto-discovery mi jich nasbíral 80, reálně funguje 7.

TV adaptér
Configuration → DVB Inputs → TV adapters → Sony CXD2880
| Parametr | Hodnota |
|---|---|
| Idle scan | vypnuto |
| Initial scan | vypnuto |
| LNA | zapnuto |
| # tune repeats | 2 |
| Scan grace period | 15 s |
| Streaming priority | 10 |
Pozor: Idle scan na adaptéru je jiné nastavení než Idle scan muxes na síti. Vypnout je nutné obě.

Stream profil pass
Configuration → Stream → Stream Profiles → pass
| Parametr | Hodnota |
|---|---|
| Data start timeout | 15 s |
| Restart on error | zapnuto |
| Default priority | High |
| Rewrite PMT, PAT, SDT, NIT, EIT | zapnuto |
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.

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
| Účet | Admin | Streaming | Web interface | Network prefix |
|---|---|---|---|---|
admin | ano | ano | ano | 0.0.0.0/0 |
plex | ne | ano + advanced | ne | 10.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ů.

Napojení na Plex
Plex přidá Antennas jako tuner HDHomeRun, stačí zadat IP a port ručně.
- Nastavení → Živá TV a DVR → Nastavit Plex DVR
- Automatické hledání v Dockeru často nic nenajde, klikněte na „Nevidíte svůj HDHomeRun?“
- Zadejte
10.100.10.21:5004, Plex najde „Silicondust HDHomeRun (Antennas)“ - Jako průvodce zvolte XMLTV s adresou
http://10.100.10.21:9981/xmltv/channelsa jazykem čeština - 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:
| Parametr | Hodnota |
|---|---|
| Kvalita převodníku | Preferovat vyšší rychlost kódování |
| Hardwarová akcelerace | zapnuto |
| HW dekódování videa | zapnuto |
| 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.
| Klient | HEVC | Výsledek |
|---|---|---|
| Apple TV, Samsung, LG, Android TV | nativní dekodér | Direct Play, bez transkódování |
| Webový prohlížeč | nepodporuje | Plex 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říznak | Příčina | Řešení |
|---|---|---|
| No input detected, Nelze naladit kanál | sken na pozadí drží tuner | vypnout všechny scan vrstvy |
v logu scan ... weight: 2 každých ~10 s | Idle scan na adaptéru nebo síti | Idle scan a Idle scan muxes vypnout |
| chyba poskytovatele u XMLTV v Plexu | Digest autentizace | wildcard přístup pro LAN, URL bez hesla |
| prázdný lineup v Antennas | špatné heslo v TVHEADEND_URL | ověřit uživatele plex |
PPS id out of range v Plexu | HEVC v prohlížeči | sledovat na TV nebo silnější Plex server |
hdhomerun server not enabled | Plex zkouší starou emulaci | ignorovat, 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.
- Na starém Pi zastavit kontejnery a zazálohovat
/opt/dockerna NAS - Na RPi 5 nahrát čistý Trixie, nastavit stejnou statickou IP, Docker a NFS
- Nasadit TV HAT a ověřit
/dev/dvb/adapter0 - 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.