XBMC-Kodi.cz
Oneplay Server - Verze k tisku

+- XBMC-Kodi.cz (https://www.xbmc-kodi.cz)
+-- Fórum: KODI - Doplňky (https://www.xbmc-kodi.cz/forum-kodi-doplnky)
+--- Fórum: Live TV & PVR (https://www.xbmc-kodi.cz/forum-live-tv-pvr)
+--- Téma: Oneplay Server (/prispevek-oneplay-server)

Stran: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18


RE: Oneplay Server - waladir - 24.8.2026

@mmiillaa: to budou různé problémy. Zkontroluj, že v TVheadendu máš správně URL (jestli tam nemáš opravdu "paylist"), případně ho zkus normálně otevřít v prohlížeči, soubor ulož a pak se do něj podívěj, jestli obsahuje korektní playlist. Kdyby byl nějaký problém, tak mi napiš SZ, zkusíme to vyřešit bokem.


RE: Oneplay Server - waladir - 29.8.2026

V prvním příspěvku jsou ke stažení přepracovaný Oneplay Server a TVheadend skripty. Nejsou tam funkční změny, ale snažil jsem se sjednotit kód s doplňkem Oneplay. Dál jsem provedl pomocí AI refaktoring kódu. Měl by být odolnější na různé nestandardní stavy, chybějící data a případné chyby v komunikaci s Oneplay. Z doplňku Oneplay jsem mj. převzal ošetření výběru profilu, které se může objevit při přehrání.

V případě TVheadend skriptů doporučuju instalaci do čistého adresáře. Do config.txt přibily u tři nové proměnné převzaté z Oneplay Serveru. Není nutné je mít vyplněné, doporučuju konfiguraci upravit podle config.txt.sample.

Počítejte prosím s tím, že změn uvnitř bylo relativně hodně Snažil jsem se všechno otestovat, ale neobsáhnu úplně všechno. Zatím jsou nové verze k dispozici jen ke stažení  (Oneplay Server lze nainstalovat i jako doplněk v Kodi) pro případné dobrovolníky. Pokud někdo narazíte na nějakou chybu, dejte vědět, případně i napište, pokud bude všechno v pořádku. Do repozitáře (Kodi, docker) dám nové verze později.


RE: Oneplay Server - directcz - 29.8.2026

@waladir: Řekl bych, že v balíku tvheadend skriptů chybí obsah podadresářů lib, data, resources


RE: Oneplay Server - waladir - 29.8.2026

@directcz: díky za upozornění. Vypadl mi parametr při zipování. Uploadnul jsem opravený soubor.


RE: Oneplay Server - 100karel - 30.8.2026

Bylo by možné opravit v nastavení IPTV odkazy tlačítka na Kopírovat. Nejsou funkční a nic nekopírují.


RE: Oneplay Server - waladir - 30.8.2026

@100karel: to bude spiš nějaký problém v prohlížeči. Tlačítka fungují přes javascript a zkoušel jsem Firefox, Chrome i Edge a kopírování odkazu fungovalo všude. Nevím jestli například javascript nemůže něco blokovat.


RE: Oneplay Server - 100karel - 31.8.2026

Mě to nefunguje v žádném prohlížeči, ikdyž je čerstvě nainstalovaný, bez doplňků, anonymní režim... prostě mě to nikdy nefungovalo


RE: Oneplay Server - waladir - 31.8.2026

@100karel: zkusím se podívat na to, jak by to šlo oddebugovat. JS je ale pro mě španělská vesnice a vůbec mě nenapadá, kde by mohl být problém. Předpokládám, že jde o kopírovaní IPTV odkazů (pro playlist a EPG).


RE: Oneplay Server - waladir - 03.9.2026

Ve verzi 2.0.2 by mělo být funkční kopírování, pokud je blokované prohlížečem (díky @100karel: a @sedlin2: ). Zároveň už je i dostupná v repozitáři.

Bohužel se ještě nevytvořila nová verze v Kodi repozitáři. Je tam 2.0.1 v které je chyba. Pokud by se vám v Kodi udělal update na 2.0.1 a 2.0.2 nebyla ještě dostupná, udělejte downgrade na 1.6.2 nebo si stáhněte zip z prvního příspěvku a nainstalujte Oneplay Server z něj.


RE: Oneplay Server - waladir - 03.9.2026

V prvním příspěvku si můžete stáhnout verzi 2.1.0, v které jsou úpravy od @sedlin2: přidávají podporu timeshiftu a úpravy přetáčení. Díky nim by mělo fungovat přetáčení např. v TiviMate.Protože se tím mění způsob jak funguje přehrávání ve Oneplay Server, do repozitáře dám úpravy už začátkem příštího týdne. Ale co jsem mohl otestovat funguje.


RE: Oneplay Server - waladir - 07.9.2026

Verze 2.1.1, kde je navíc oprava načítání účtů a defaultních hodnot je už i v repozitáři. Stejné změny jsou i v TVheadend skriptech.


RE: Oneplay Server - rasti - 07.9.2026

Dobrý den, bylo by prosím možné přidat podporu Docker Compose secrets pro přihlašovací údaje Oneplay?Aktuální Docker image načítá v Docker režimu hodnoty `USERNAME` a `PASSWORD` z environment variables. Docker Compose secrets jsou ale standardně dostupné jako soubory v `/run/secrets/...`, například: 
 
Kód:
environment:
  USERNAME_FILE: /run/secrets/USERNAME
  PASSWORD_FILE: /run/secrets/PASSWORD

secrets:
  - USERNAME
  - PASSWORD

Aplikace nyní 'USERNAME_FILE' a `PASSWORD_FILE` neinterpretuje, takže musím mít user/pass v config nebo v compose. Navrhuji přidat podporu konvence `<PROMENNA>_FILE` do `get_config_value()` v `resources/lib/utils.py`.

Požadované chování:
1. Pokud je nastavena `USERNAME_FILE`, načíst obsah tohoto souboru jako hodnotu `USERNAME`.
2. Pokud je nastavena `PASSWORD_FILE`, načíst obsah tohoto souboru jako hodnotu `PASSWORD`.
3. Hodnota z `*_FILE` má přednost před přímou proměnnou `USERNAME` / `PASSWORD`.
4. Pokud `*_FILE` není nastaveno, zachovat stávající chování beze změny.
5. Odstranit pouze koncový LF/CRLF ze souboru se secretem.
6. Při nečitelném nebo neexistujícím souboru skončit s jasnou chybou, aby nedošlo k tichému přihlášení s prázdným nebo chybným údajem.

Tím bude image kompatibilní s Docker Compose secrets, Docker Swarm secrets a běžnou `_FILE` konvencí používanou mnoha Docker images.

Níže přikládám návrh minimální změny. Změny jsem otestoval u sebe a fungují jak při použití USERNAME tak i USERNAME_FILE resp. PASSWORD i PASSWORD_FILE. Tento návrh je schválně obecný, nepodporuje jen USERNAME_FILE a PASSWORD_FILE ale i AUTH_PASS_FILE nebo PIN_FILE atp. aniž by se musela stejná logika kopírovat.
 
Kód:
def get_config_value(setting):
     if is_kodi():
         import xbmcaddon

         return xbmcaddon.Addon().getSetting(setting)

     config_file = os.path.join(get_script_path(), 'config.txt')
     defaults = {
         'WEBSERVER_IP': '0.0.0.0',
         'WEBSERVER_PORT': 8082,
         'EPG_DNU_ZPETNE': 1,
         'EPG_DNU_DOPREDU': 1,
         'INTERVAL_STAHOVANI_EPG': 0,
         'ODSTRANIT_HD': 0,
         'POUZIVAT_CISLA_KANALU': 0,
         'PORADI_SLUZBY': -1,
         'PIN': '4321',
         'PROFILE_PIN': '4321',
         'DEBUG': 0,
         'CESTA_FFMPEG': '/usr/bin/ffmpeg',
         'AUTH_USER': '',
         'AUTH_PASS': '',
     }

     if is_docker() and not os.path.exists(config_file):
-        return os.getenv(setting.upper(), defaults.get(setting.upper()))
+        env_name = setting.upper()
+        secret_file = os.getenv(f'{env_name}_FILE')
+
+        if secret_file:
+            try:
+                with open(secret_file, encoding='utf-8') as file:
+                    return file.read().rstrip('\r\n')
+            except OSError as error:
+                raise RuntimeError(
+                    f'Cannot read Docker secret from {env_name}_FILE: {secret_file}'
+                ) from error
+
+        return os.getenv(env_name, defaults.get(env_name))

     with open(config_file, encoding='utf-8') as file:
         return json.load(file).get(setting, defaults.get(setting.upper()))

Jak bude fungovat Compose
 
Kód:
services:
  oneplayserver:
    image: XXXX/oneplayserver:verze-s-podporou-secrets

    environment:
      USERNAME_FILE: /run/secrets/USERNAME
      PASSWORD_FILE: /run/secrets/PASSWORD
      DEVICEID: atv34
      WEBSERVER_IP: 192.168.X.X
      WEBSERVER_PORT: 8082

    secrets:
      - USERNAME
      - PASSWORD

secrets:
  USERNAME:
    file: /share/Docker_data/secrets/O2TV/USERNAME
  PASSWORD:
    file: /share/Docker_data/secrets/O2TV/PASSWORD
  
Aplikace pak při volání najde nejdříve USERNAME_FILE a PASSWORD_FILE, načte obsah těchto souborů a vrátí jej jako hodnotu uživatelského jména a hesla. Současné nasazení s běžnými proměnnými USERNAME a PASSWORD zůstane plně kompatibilní.


RE: Oneplay Server - waladir - 08.9.2026

@rasti: přidám to do další verze jako variantu. Pro jednoduchost nechám docker-compose.yml v repozitáři jak je, ale v kódu bude přidaná podpora načítání ze secrets souborů.


RE: Oneplay Server - waladir - 08.9.2026

Ve verzi 2.1.1 je opravená chyba při volání timeshiftu u živého vysílání a přidaná podpora secrets souburů v dockeru.


RE: Oneplay Server - rasti - 08.9.2026

(08.9.2026, 21:10)waladir Napsal(a): Ve verzi 2.1.1 je opravená chyba při volání timeshiftu u živého vysílání a přidaná podpora secrets souburů v dockeru.

Perfektne, docker secrets funguje, diky za rychlou reakci


RE: Oneplay Server - waladir - 09.9.2026

Bohužel mi včera omylem vypadla oprava timeshiftu. Opravené je to ve verzi 2.1.3.


RE: Oneplay Server - waladir - 13.9.2026

Ve verzi 2.1.4 je opravené disablování při refreshi kanálů


RE: Oneplay Server - andrebas - 16.9.2026

Ahoj, narazil som na problém s /play/ a myslím, že mám aj návrh riešenia.

Problém
Endpoint /play/ mi vracia 500 Internal Server Error pre všetky kanály. /stream_url/ pritom funguje normálne a vráti platnú URL.

Príčina
Server, na ktorom beží doplnok, má výstupnú IP v datacentrovom rozsahu a CDN (CETIN) ju odmieta — pri sťahovaní manifestu dostane HTTP 403. Overil som to: rovnaká URL a rovnaký token v tej istej chvíli dá z tohto stroja 403, ale z inej siete 200. Token na IP viazaný nie je (pole sip je prázdne), takže rozhoduje výhradne to, odkiaľ ide HTTP požiadavka.

Do 2.0.2 to nevadilo, lebo /play/ robil len:

Kód:
return redirect(stream)

Manifest si teda sťahoval klient, ktorý konektivitu na CDN má. Od 2.1.x je tam:

Kód:
return rewrite_manifest(stream, get_base_url())

Manifest sťahuje server sám, urlopen() vyhodí HTTPError 403, tá nie je nikde ošetrená a bottle to vráti ako 500. Rovnako sa správa aj /proxy_hls.

Traceback

Kód:
File "/usr/lib/python3.11/urllib/request.py", line 643, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

Návrh riešenia
Všimol som si, že pri živom vysielaní bez timeshiftu (offset_seconds == 0) robí rewrite_manifest() vlastne len dve veci — prepíše URI na absolútne a pridá #EXT-X-START:TIME-OFFSET=-3. Proxovanie cez /proxy_hls sa zapína až pri use_proxy, teda pri offsete. Pre bežné živé vysielanie teda nie je nutné manifest sťahovať na serveri.

Napadli ma tri možnosti, od najjednoduchšej:

1) Prepisovať manifest len keď treba — pri timeshift == 0 sa vrátiť k redirectu:

Kód:
if timeshift > 0:
    return rewrite_manifest(stream, get_base_url(), timeshift)
return redirect(stream)

Stratí sa tým len tá trojsekundová korekcia štartu, ktorú si vie klient doriešiť sám.

2) Automatický fallback — nechať pokus o prepis, ale pri zlyhaní spadnúť na redirect:

Kód:
try:
    return rewrite_manifest(stream, get_base_url())
except (HTTPError, URLError):
    return redirect(stream)

Toto mi príde najelegantnejšie, lebo to rieši aj iné výpadky CDN a nič netreba konfigurovať.

3) Prepínač v konfigurácii, napr. prepisovat_manifest 0/1, pre tých, čo si chcú vynútiť staré správanie.

A nezávisle od toho by som prosil ošetriť výnimku z urlopen() v rewrite_manifest() aj /proxy_hls a vrátiť čitateľnú hlášku (napr. 502 s HTTP kódom od CDN). Holá 500 bez akejkoľvek informácie vedie k tomu, že človek hľadá chybu úplne inde — mňa to stálo dosť času, kým som sa dostal k tracebacku.

Chápem, že blokovaná IP je špecifikum môjho nastavenia a nie chyba doplnku. Ale scenár, keď klient má na CDN prístup a server nie, asi nebudem mať len ja — a do 2.0.2 fungoval bez problémov.

Verzia: 2.1.4, beží priamo na Debiane (nie Docker), Python 3.11, bottle 0.12.23.

Vopred vďaka za pohľad na to.


RE: Oneplay Server - waladir - 16.9.2026

@andrebas: díky za podrobnou analýzu i s návrhy řešení. Asi půjdu cestou fallbacku, ať se nemusí přidávat nějaké další nastavení. Vrácení 500 je standardní chování, resp. důsledek neošetřené výjimky, která by měla být pak v logu. Někdy je i lepší, když ošetřená není, protože je hned na první pohled vidět, kde je problém :-)


RE: Oneplay Server - sedlin2 - 16.9.2026

(16.9.2026, 11:48)andrebas Napsal(a): Ahoj, narazil som na problém s /play/ a myslím, že mám aj návrh riešenia.

Problém
Endpoint /play/ mi vracia 500 Internal Server Error pre všetky kanály. /stream_url/ pritom funguje normálne a vráti platnú URL.

Príčina
Server, na ktorom beží doplnok, má výstupnú IP v datacentrovom rozsahu a CDN (CETIN) ju odmieta — pri sťahovaní manifestu dostane HTTP 403. Overil som to: rovnaká URL a rovnaký token v tej istej chvíli dá z tohto stroja 403, ale z inej siete 200. Token na IP viazaný nie je (pole sip je prázdne), takže rozhoduje výhradne to, odkiaľ ide HTTP požiadavka.

Do 2.0.2 to nevadilo, lebo /play/ robil len:
 
Kód:
return redirect(stream)

Manifest si teda sťahoval klient, ktorý konektivitu na CDN má. Od 2.1.x je tam:
 
Kód:
return rewrite_manifest(stream, get_base_url())

Manifest sťahuje server sám, urlopen() vyhodí HTTPError 403, tá nie je nikde ošetrená a bottle to vráti ako 500. Rovnako sa správa aj /proxy_hls.

Traceback
 
Kód:
File "/usr/lib/python3.11/urllib/request.py", line 643, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

Návrh riešenia
Všimol som si, že pri živom vysielaní bez timeshiftu (offset_seconds == 0) robí rewrite_manifest() vlastne len dve veci — prepíše URI na absolútne a pridá #EXT-X-START:TIME-OFFSET=-3. Proxovanie cez /proxy_hls sa zapína až pri use_proxy, teda pri offsete. Pre bežné živé vysielanie teda nie je nutné manifest sťahovať na serveri.

Napadli ma tri možnosti, od najjednoduchšej:

1) Prepisovať manifest len keď treba — pri timeshift == 0 sa vrátiť k redirectu:
 
Kód:
if timeshift > 0:
    return rewrite_manifest(stream, get_base_url(), timeshift)
return redirect(stream)

Stratí sa tým len tá trojsekundová korekcia štartu, ktorú si vie klient doriešiť sám.

2) Automatický fallback — nechať pokus o prepis, ale pri zlyhaní spadnúť na redirect:
 
Kód:
try:
    return rewrite_manifest(stream, get_base_url())
except (HTTPError, URLError):
    return redirect(stream)

Toto mi príde najelegantnejšie, lebo to rieši aj iné výpadky CDN a nič netreba konfigurovať.

3) Prepínač v konfigurácii, napr. prepisovat_manifest 0/1, pre tých, čo si chcú vynútiť staré správanie.

A nezávisle od toho by som prosil ošetriť výnimku z urlopen() v rewrite_manifest() aj /proxy_hls a vrátiť čitateľnú hlášku (napr. 502 s HTTP kódom od CDN). Holá 500 bez akejkoľvek informácie vedie k tomu, že človek hľadá chybu úplne inde — mňa to stálo dosť času, kým som sa dostal k tracebacku.

Chápem, že blokovaná IP je špecifikum môjho nastavenia a nie chyba doplnku. Ale scenár, keď klient má na CDN prístup a server nie, asi nebudem mať len ja — a do 2.0.2 fungoval bez problémov.

Verzia: 2.1.4, beží priamo na Debiane (nie Docker), Python 3.11, bottle 0.12.23.

Vopred vďaka za pohľad na to.

Ahoj,
proxování manifestu má své výhody.
Každopádně řešení č.2 je super nápad - jen bych kód trochu rozšířil - napřiklad takto:
 
Kód:
from urllib.error import HTTPError, URLError

try:
  return rewrite_manifest(stream, get_base_url())
except HTTPError as e:
  if e.code == 403:
    return redirect(stream)
  # Vrátí konkrétní HTTP chybu (např. 404, 500 atd.) s chybovou zprávou
  return HTTPResponse(body=str(e), status=e.code)
except URLError as e:
  # Problémy se sítí (Internal Server Error)
  return HTTPResponse(body=str(e), status=500)


Sedlin2