Úvodem
Tvheadend má/může mít k dispozici několik metod přepínání záložních zdrojů příjmu TV kanálů. Na nejvyšší úrovni to může být například existence několika serverů Tvheadend a různých strategií a mechanismů jejich přepínání. Naopak na druhé druhé straně spektra možností to pak může být přepínání DVB zdrojů, které umožní efektivně řadit využívání jednotlivých DVB přijímačů tak, aby byl vždy k dispozici odpovídající (či spíše co největší) počet muxů pro současný příjem více kanálů. Někde uprostřed toho je mechanismus přepínání služeb (services) v případech, kdy jich pro daný TV kanál existuje více.
Posledně jmenovaný mechanismus je často využíván i v případech, kdy máme k dispozici více OTT/IPTV služeb a chceme jejich prostřednictvím zajisti příjem více různých kanálů současně. Vlastní strategie přepínání využívá systém priorit a funguje podle očekávání. Co je však problematické, to je, jaký mechanismus pro přepnutí na službu s nižsí prioritou Tvheadend používá. Zatímco přepnutí na jinou službu s nižší prioritou v případě, že by byl pro daný zdroj typu IPTV Automatic Network překročen počet Maximum # input streams:, proběhne správně, ani po dlouhé době pokusů a různých kombinací nastavení se mi nepodařilo dosáhnotu toho, aby Tvheadend přepnul na jinou službu cíleně. Používám v playlistech vesměs metodu pipe://, takže mám to chování volaných scriptů plně pod kontrolou, ale všechny pokusy donutit Tvheadend vybrat jinou službu, skončily neúspěšně. Pátral jsme po tom i u autorů, ale i tam mi (zatím) bylo potvrzeno, že tohle jednoduše (a hlavně rychle) možné není.
Řešení?
Šel jsem na to cestou: "Když to nefunguje tak, jak potřebuji, udělám to jinak". Mám k dispozici sadu playlistů z různých zdrojů. Nebudu tu popisovat jakých a jak jsme k nim přišel (tohle obsahem tohoto tématu nikdy nebude!), ale jejich obah je poměrně zajímavý a pro mne důležitý. To je první východisko. To druhé je, že ta sada se, čas od času, mění. Nějaké playlisty přestanou trvale fungovat, jiné se objeví. A aby toho nebylo málo, je tu ještě východisko třetí, že někdy nějaký playlist, nebo jen některý jeho stream, přestane, ale jen na nějakou omezenou dobu, fungovat.
Z těchto východisek vyplynul basic design toho, jak by řešení mělo vypadat. Popíšu ho stručně v pár bodech:
Databáze serveru je jednoduchá struktura, kterou si server načítá z json souboru po svém startu. Server má jednoduchý algoritmus, kde podle definovaného pořadí providerů (to lze měnit) postupně pro danou služby vybere všechny url adresy, které má v databázi k diposzici a testuje, zda jsou dostupné. Uživatelsky je možné si typ testu pro každého providera vybrat. V drtivé většině případů stačí jen jednoduchý test pomocí curl, ale je možné, použít test pomocí ffprobe (který ale trvá déle). Test probíhá v části kódu, který je zpracováván vícevláknově, tzn. všechny streamy se testují paralelně. Vzhledek k tomu, že podstatnou dobou při vykonávání těchto testů je komunikace ze servery příslušné OTT/IPTV služby, tak i když to běží paralelně, odezva je velmi rychlá. Vybrán je ten stream, který se podaří pozitivně otestovat nejdříve.
Pro praktické urychlení algoritmu je vybraná adresa streamu, současně s odeslání na klienta, uložena do cache a při dalším výběru je otestována jako první.
Veškeré postupy jsou ukládány do statistické databáze, která bude v následujcícíh verzí připravena jako zdroj infromací pro algoritmy adaptivního výběru streamu. Cílem je celý proces urychlit a příliš velkou dobu spuštění kanálu zkrátit. V současné době trvá tento výběru streamu (při použití curl testu) průměrně cca 0,3 - 0,5 vteřin. Dá se předpokládat, že by se to mohlo minimálně udržet, případně ještě nepatrně zlepšit. Co je podstatné, že je tady vytvořený prostor jak pro nasazení i sofistikovaných algoritmů, tak případně pro to, aby testy streamů byly prováděny předem, periodicky a asynchronně na pozadí.
Databáze streamů a její správa
Celé řešení je opřeno o existenci databáze streamů. Její správa je oddělena od vlastní funkce serveru jednoduchým způsobem. Po startu si server načte aktuální databázi z json souboru, uloží její obsah do paměti a server pak pracuje už jen ní. Umožňuje to kdykoliv obsah databáze v json souboru změnit a pak jen poslat serveru požadavek na reload databáze.
Správa databáze se provádí pomocí jednochého scriptu playlist, který má několik funkcí definovaných jeho pametry zadanými při spuštění. Např.
playlist -p oneplay1 playlistoneplay.m3u8
Tento příkaz vloží do databáze playlist uložený v souboru playlistoneplay.m3u8 a přiřadí ho k provideru označeného v databázi jako oneplay1. Zpracování příkazu probíhá ve dvou průchodech, nejdříve se normalizují názvy kanálů pomocí slovníku kanálů a přiřazují k service pomocí slovníku mapování service. V druhém průchodu je každá adresa streamu doplněná identifikací providera a přidá se k dalším steramům v databázi pod příslušnou service. Pokud service v databázi ještě neexistuje, vytvoří se.
playlist -d oneplay1
Tento příkaz provede přesně opačný postup, jak ten předchozí. Vyjme z databáze všechny záznamy týkající se daného providera.
Kromě toho existuje ještě celá řada dalších příkazů a postupů, včetně občasné ruční editace slovníků kanálů a slovníku mapování service. Tenhle ruční postup je nutný, protože v řadě případů se kanály se stejnýcm obsahem v různých playlistech u různých providerů jmenují dost odlišně. Řadu těch odlišností se snažím vyřešit algoritmicky, ale ne vždy se to podaří. Proto je možné si v případě vkládání obsahu playlistu do databáze nastavit kontrolu, zda se v obsahu neobjevilo jméno kanálu nebo service, které nelze jednoznačně přiřadit. Pokud k tomu dojde, script se po prvním průchodu ukončí, a vypíše se seznam kanálů a service, které je třeba do příslušných slovníků zadat ručně. Poté se script spustí znova a nechá se proběhnout včetně druhého průchodu.
Okrajové stavy
Server umí specificky řešit i tyto okrajové stavy:
Použití popsaného konceptu
Použití popsaného konceptu má smysl v případech, kdy máte k dispozici něolik playlistů z různých zdrojů, které obsahují adresy streamů +/- stejných (i po částech) TV kanálů. Vychází se při tom z předpokladu, že ne všechny zdroje a ne vždy musí fungovat. Server tak při požadavku na spuštění steramu dané service/kanálu vybere co nejrychleji ten, který je dostupný, a TVheadend ho může začít přijímat.
V Tvheadend tedy stačí vytvořit další IPTV Automatick Network, zadat do ní playlist, jehož obsahem jsou všechny unikátní (myšleno unikátní po normalizaci) kanály, které jsou obsaženy v dílčích playlistech, které byly vloženy do databáze serveru. V adresní části jednotlivých položek plalyisu pak bude volání scriptu client s parametrem obsahujícím název service, odpovídající danému kanálu.
Obsahem scriptu je samozřejmě volání ffmpeg s odpovídajícími parametry, díky kterému se jednak spustí příjem a na vstup Tvheadend začně odesílat i obsah, steramu, zároveň se ale přenesou další údaje. Jako např. název providera, kterého stream byl pro příjem aktuálně vybrán. Název providera i název service je pak možné vidět např. i v Kodi.
To-Do
Zvolený koncept má v sobě poměrně velký potenciál dalšího rozšiřování. Z dnešního phledu se dá tento potenciál rozdělit do oblastí:
U mně doma teď běží první verze serveru, pro kterou jsem zatím databázi plnil ručně. Základní algoritmus a celý řetězec výběru, klient - server - klient, funguje podle očekávání. Nyní pracuji na scriptech pro správu databáze. Nejsem schopen ale teď říci, kdy bude hotovo, ale rád bych to měl co možná nejdříve. Co ale mohu říci hned, že až ten koncept zveřejním, tak ale s prázdnou databází. Tu si do něj bude muset každý opatřit sám.
Tvheadend má/může mít k dispozici několik metod přepínání záložních zdrojů příjmu TV kanálů. Na nejvyšší úrovni to může být například existence několika serverů Tvheadend a různých strategií a mechanismů jejich přepínání. Naopak na druhé druhé straně spektra možností to pak může být přepínání DVB zdrojů, které umožní efektivně řadit využívání jednotlivých DVB přijímačů tak, aby byl vždy k dispozici odpovídající (či spíše co největší) počet muxů pro současný příjem více kanálů. Někde uprostřed toho je mechanismus přepínání služeb (services) v případech, kdy jich pro daný TV kanál existuje více.
Posledně jmenovaný mechanismus je často využíván i v případech, kdy máme k dispozici více OTT/IPTV služeb a chceme jejich prostřednictvím zajisti příjem více různých kanálů současně. Vlastní strategie přepínání využívá systém priorit a funguje podle očekávání. Co je však problematické, to je, jaký mechanismus pro přepnutí na službu s nižsí prioritou Tvheadend používá. Zatímco přepnutí na jinou službu s nižší prioritou v případě, že by byl pro daný zdroj typu IPTV Automatic Network překročen počet Maximum # input streams:, proběhne správně, ani po dlouhé době pokusů a různých kombinací nastavení se mi nepodařilo dosáhnotu toho, aby Tvheadend přepnul na jinou službu cíleně. Používám v playlistech vesměs metodu pipe://, takže mám to chování volaných scriptů plně pod kontrolou, ale všechny pokusy donutit Tvheadend vybrat jinou službu, skončily neúspěšně. Pátral jsme po tom i u autorů, ale i tam mi (zatím) bylo potvrzeno, že tohle jednoduše (a hlavně rychle) možné není.
Řešení?
Šel jsem na to cestou: "Když to nefunguje tak, jak potřebuji, udělám to jinak". Mám k dispozici sadu playlistů z různých zdrojů. Nebudu tu popisovat jakých a jak jsme k nim přišel (tohle obsahem tohoto tématu nikdy nebude!), ale jejich obah je poměrně zajímavý a pro mne důležitý. To je první východisko. To druhé je, že ta sada se, čas od času, mění. Nějaké playlisty přestanou trvale fungovat, jiné se objeví. A aby toho nebylo málo, je tu ještě východisko třetí, že někdy nějaký playlist, nebo jen některý jeho stream, přestane, ale jen na nějakou omezenou dobu, fungovat.
Z těchto východisek vyplynul basic design toho, jak by řešení mělo vypadat. Popíšu ho stručně v pár bodech:
- Zpracovaný obsah všech playlistů vložím do jedné databáze
- klíčem k této databázi bude tzv. service - vytvořená jednotným způsobem z názvu kanálů. Ten jednotný způsob je odvozený od toho, jak Tvheaend může z názvu kanálů vytvářet název souboru pro logo kanálu (jen malá písmen, žádná diakritika, ...), doplněný o další obvyklé manipulace - např. odstranění HD z názvu kanálu, apod.). Například "ČT 1 HD" má service "ct1", "CANAL+ Sport" má service "canalplusport" atd.
- obsahem záznamu jsou pak seznamy dvojic "provider":"url", kde provider odpovídá jednomu plalylistu, url obsahuje adresu streamu tohoto providera pro kanál s odpovídající hodnotou service.
- klíčem k této databázi bude tzv. service - vytvořená jednotným způsobem z názvu kanálů. Ten jednotný způsob je odvozený od toho, jak Tvheaend může z názvu kanálů vytvářet název souboru pro logo kanálu (jen malá písmen, žádná diakritika, ...), doplněný o další obvyklé manipulace - např. odstranění HD z názvu kanálu, apod.). Například "ČT 1 HD" má service "ct1", "CANAL+ Sport" má service "canalplusport" atd.
- Nad databází běží serverová aplikace (daemon), s funkcí socket serveru
- V Tvheadend mám vytvořenou IPTV Automatic Network s playlistem, kde v části adresy je metodou pipe volán script, který obsahuje funkci socket client. Ten na server pošle request obsahující název service, která odpovídá danému kanálu, a server vybere a vrátí název providera a funkční adresu streamu s Live TV vysílání daného kanálu.
Databáze serveru je jednoduchá struktura, kterou si server načítá z json souboru po svém startu. Server má jednoduchý algoritmus, kde podle definovaného pořadí providerů (to lze měnit) postupně pro danou služby vybere všechny url adresy, které má v databázi k diposzici a testuje, zda jsou dostupné. Uživatelsky je možné si typ testu pro každého providera vybrat. V drtivé většině případů stačí jen jednoduchý test pomocí curl, ale je možné, použít test pomocí ffprobe (který ale trvá déle). Test probíhá v části kódu, který je zpracováván vícevláknově, tzn. všechny streamy se testují paralelně. Vzhledek k tomu, že podstatnou dobou při vykonávání těchto testů je komunikace ze servery příslušné OTT/IPTV služby, tak i když to běží paralelně, odezva je velmi rychlá. Vybrán je ten stream, který se podaří pozitivně otestovat nejdříve.
Pro praktické urychlení algoritmu je vybraná adresa streamu, současně s odeslání na klienta, uložena do cache a při dalším výběru je otestována jako první.
Veškeré postupy jsou ukládány do statistické databáze, která bude v následujcícíh verzí připravena jako zdroj infromací pro algoritmy adaptivního výběru streamu. Cílem je celý proces urychlit a příliš velkou dobu spuštění kanálu zkrátit. V současné době trvá tento výběru streamu (při použití curl testu) průměrně cca 0,3 - 0,5 vteřin. Dá se předpokládat, že by se to mohlo minimálně udržet, případně ještě nepatrně zlepšit. Co je podstatné, že je tady vytvořený prostor jak pro nasazení i sofistikovaných algoritmů, tak případně pro to, aby testy streamů byly prováděny předem, periodicky a asynchronně na pozadí.
Databáze streamů a její správa
Celé řešení je opřeno o existenci databáze streamů. Její správa je oddělena od vlastní funkce serveru jednoduchým způsobem. Po startu si server načte aktuální databázi z json souboru, uloží její obsah do paměti a server pak pracuje už jen ní. Umožňuje to kdykoliv obsah databáze v json souboru změnit a pak jen poslat serveru požadavek na reload databáze.
Správa databáze se provádí pomocí jednochého scriptu playlist, který má několik funkcí definovaných jeho pametry zadanými při spuštění. Např.
playlist -p oneplay1 playlistoneplay.m3u8
Tento příkaz vloží do databáze playlist uložený v souboru playlistoneplay.m3u8 a přiřadí ho k provideru označeného v databázi jako oneplay1. Zpracování příkazu probíhá ve dvou průchodech, nejdříve se normalizují názvy kanálů pomocí slovníku kanálů a přiřazují k service pomocí slovníku mapování service. V druhém průchodu je každá adresa streamu doplněná identifikací providera a přidá se k dalším steramům v databázi pod příslušnou service. Pokud service v databázi ještě neexistuje, vytvoří se.
playlist -d oneplay1
Tento příkaz provede přesně opačný postup, jak ten předchozí. Vyjme z databáze všechny záznamy týkající se daného providera.
Kromě toho existuje ještě celá řada dalších příkazů a postupů, včetně občasné ruční editace slovníků kanálů a slovníku mapování service. Tenhle ruční postup je nutný, protože v řadě případů se kanály se stejnýcm obsahem v různých playlistech u různých providerů jmenují dost odlišně. Řadu těch odlišností se snažím vyřešit algoritmicky, ale ne vždy se to podaří. Proto je možné si v případě vkládání obsahu playlistu do databáze nastavit kontrolu, zda se v obsahu neobjevilo jméno kanálu nebo service, které nelze jednoznačně přiřadit. Pokud k tomu dojde, script se po prvním průchodu ukončí, a vypíše se seznam kanálů a service, které je třeba do příslušných slovníků zadat ručně. Poté se script spustí znova a nechá se proběhnout včetně druhého průchodu.
Okrajové stavy
Server umí specificky řešit i tyto okrajové stavy:
- scanování sítě - pro skenování sítě je zbytečné testovat dostupné streamy. V parametrech serveru je přepínač označený jako scan_mode, který když se nastaví na True, tak server vrací klientovi adresu lokálního souboru .ts ve který obsauje nekonečnou smyčku statického obrázku. Skenování celé sítě pak probíhá velmi rychle a co je důležité, na zdrojové servery není navaleno najednou velké množství reqestů. To může být v některých případech a u nekterých serverů problém, který server např. vyřeší tím, že se danou ip adrese, třeba i dočasně, blokne.
- nexistující stream - může se stát, že v dané chvíli nebude pro požadovanou službu dostupný žádný stream. Server v takovém případě vrátí klientovi opět adresu lokálního souboru .ts ve který obsahuje nekonečnou smyčku statického obrázku.
Použití popsaného konceptu
Použití popsaného konceptu má smysl v případech, kdy máte k dispozici něolik playlistů z různých zdrojů, které obsahují adresy streamů +/- stejných (i po částech) TV kanálů. Vychází se při tom z předpokladu, že ne všechny zdroje a ne vždy musí fungovat. Server tak při požadavku na spuštění steramu dané service/kanálu vybere co nejrychleji ten, který je dostupný, a TVheadend ho může začít přijímat.
V Tvheadend tedy stačí vytvořit další IPTV Automatick Network, zadat do ní playlist, jehož obsahem jsou všechny unikátní (myšleno unikátní po normalizaci) kanály, které jsou obsaženy v dílčích playlistech, které byly vloženy do databáze serveru. V adresní části jednotlivých položek plalyisu pak bude volání scriptu client s parametrem obsahujícím název service, odpovídající danému kanálu.
Obsahem scriptu je samozřejmě volání ffmpeg s odpovídajícími parametry, díky kterému se jednak spustí příjem a na vstup Tvheadend začně odesílat i obsah, steramu, zároveň se ale přenesou další údaje. Jako např. název providera, kterého stream byl pro příjem aktuálně vybrán. Název providera i název service je pak možné vidět např. i v Kodi.
To-Do
Zvolený koncept má v sobě poměrně velký potenciál dalšího rozšiřování. Z dnešního phledu se dá tento potenciál rozdělit do oblastí:
- Navýšení adaptivity algoritmů výběru streamů, jednak díky statistice, která se o provozu serveru bude sbírat a ukládat, jednak díky novým nápadům a aplikacím, které mohou být do konceptu postupně integrovány
- Zrychlení doby do spuštění funkčního steramu, které může být, zejména při zvyšování adaptivity algoritmů, často neúnosně dlouhé. Například při výběru steramů podle dalších kritérií (kvality, audo stopy, ...). Tady může přijít vhod například asynchronní průběžné tetsování dostupnosti steramů, které poběží na pozadí.
- Zapojení konceptu do systému automatického nebo poloautomatického získávání streamů z různých zdrojů. Možnost změny v databázi, bez nutnosti skenování nového zdroje, kdy je možná databázi kdykoliv upravit/doplnit/rozšířit a poté ji v běžícím serveru "vyměnit", dává tomuto konceptu další možnosti využití.
U mně doma teď běží první verze serveru, pro kterou jsem zatím databázi plnil ručně. Základní algoritmus a celý řetězec výběru, klient - server - klient, funguje podle očekávání. Nyní pracuji na scriptech pro správu databáze. Nejsem schopen ale teď říci, kdy bude hotovo, ale rád bych to měl co možná nejdříve. Co ale mohu říci hned, že až ten koncept zveřejním, tak ale s prázdnou databází. Tu si do něj bude muset každý opatřit sám.
Jsem (až na výjimky) pouhým čtenářem fóra.
Nepokračuji tedy ani v tématech, která jsem založil.
To platí i pro doplňky Kodi a další aplikace, které jsou s takovými tématy spojené.
Nepokračuji tedy ani v tématech, která jsem založil.
To platí i pro doplňky Kodi a další aplikace, které jsou s takovými tématy spojené.

