EPG-Server (XMLTV)¶
Ein separater integrierter HTTP-Server in Perfect Streamer liefert das vollständige XMLTV für einen vorgegebenen Kanalsatz. Der Endpunkt ist für Middleware und Player gedacht, die das Programm lokal vorhalten und es selten aktualisieren — als ganze Datei, typischerweise ein- bis zweimal täglich.
Der Server und seine Clients werden unter Configuration/EPG/EPG Server konfiguriert.
URL und Authentifizierung¶
Der Dienst wird von einem separaten HTTP-Server epg-server bereitgestellt (nicht von dem für /data/*). Standardmäßig lauscht er auf den Ports 10444 (HTTP) und 10445 (HTTPS); Ports und SSL werden unter /config/epg-server konfiguriert.
Routen:
URL |
Content-Type |
Verhalten |
|---|---|---|
|
|
Bei |
|
|
Liefert stets einen Gzip-Stream mit |
Drei Authentifizierungsmethoden werden unterstützt:
HTTP Digest (bevorzugt) — Konto aus
/config/epg-server/login.URL-Parameter —
?l=<login>&p=<password>(Synonyme:login=…,password=…).Loopback — eine Anfrage von
127.0.0.1wird anonym behandelt. Praktisch für Skripte, die auf derselben Maschine laufen.
Warnung
Login und Passwort in der URL landen in den Access-Logs des Reverse-Proxys und im Browserverlauf. Für die öffentliche XMLTV-Verteilung verwenden Sie HTTP Digest oder lassen Sie Anfragen nur von privaten Adressen zu.
Zugriff per channel-set¶
Jedes epg-server/login-Konto ist an ein channel-set aus /config/epg-channel-set gebunden. Das EPG in der Antwort enthält nur die Kanäle des angegebenen Sets. So kann eine einzige PSS-Installation unterschiedlichen Betreibern/Middleware unterschiedliches XMLTV ausliefern.
Grundeinrichtung in der UI:
Erstellen Sie unter Configuration/EPG/EPG Channel Sets eine Kanalgruppe und weisen Sie die gewünschten Kanäle bei den EPG-Quellen zu.
Legen Sie unter Configuration/EPG/EPG Server Clients ein Konto an und binden Sie die erstellte Gruppe daran. Ohne
channel-set-Bindung erhält der Client ein leeres XMLTV.
Zusätzliche Einschränkungen für einen Login:
ip-addr— wenn gesetzt und kein Platzhalter, erhält eine Anfrage von einer anderen IP403 Forbidden.limit-day— Unix-Epoche-Sek., nach der das Konto nicht mehr bedient wird (403 Forbidden). Praktisch für ein Abonnementmodell.pause— einen Login vorübergehend deaktivieren, ohne ihn zu löschen.
Antwortformat¶
Der Antwortkörper ist ein XMLTV-Dokument mit der Wurzel <tv>. Die Struktur folgt dem gängigen XMLTV DTD-Schema:
<?xml version="1.0" encoding="utf-8"?>
<tv source-info-name="..." source-info-url="...">
<channel id="channel.one">
<display-name lang="en">Channel One</display-name>
<icon src="https://.../channel-one.png"/>
</channel>
...
<programme start="20260504060000 +0300"
stop ="20260504070000 +0300"
channel="channel.one">
<title lang="en">Morning News</title>
<desc lang="en">Overview of the day's events</desc>
<rating system="MPAA"><value>PG</value></rating>
</programme>
...
</tv>
Hinweise zu Feldern:
Die Attribute
source-info-nameundsource-info-urlder<tv>-Wurzel werden aus den Feldern EPG Source Name und EPG Source URL unter Configuration/EPG/EPG Server gefüllt.Die Attribute
startundstopwerden im FormatYYYYMMDDhhmmss ±zoneangegeben (die Zeitzone stammt aus dem Feldtime_zonedes Kanals).Ein
<programme>darf mehrere<title>/<desc>für verschiedene Sprachen enthalten. Das Attributlangist leer, wenn die Sprach-ID aus den EPG-Quelldaten nicht im Wörterbuch zugeordnet werden konnte (der Eintrag erscheint dennoch in der Ausgabe).Kanäle mit einem konfliktbehafteten
channel_id(wenn dieselbe ID aus mehreren Quellen kommt) werden einmal angezeigt, die übrigen Quellen werden mit einer Warnung im Serverlog übersprungen.Nur Ereignisse mit
stop_time >= nowwerden in die Ausgabe aufgenommen.
HTTP-Header¶
Der Server sendet immer:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Connection: close
Für /xmltv zusätzlich — Content-Encoding: gzip bei vorhandenem Accept-Encoding: gzip in der Anfrage. Für /xmltv.gz — Content-Disposition: inline; filename="xmltv.xml.gz".
Das Verbot des clientseitigen Cachens ist beabsichtigt: XMLTV ändert sich bei jedem EIT-Import oder Refresh externer XMLTV-Quellen, und der Player darf veraltete Daten nicht unbegrenzt vorhalten. Ein Edge-Cache (nginx) ist hingegen voll akzeptabel — siehe Abschnitt zur Leistung weiter unten.
Server-Cache und sein Zurücksetzen¶
Das fertige XMLTV wird im Speicher des PSS-Prozesses gecacht:
Ein Eintrag pro
channel-set; intern werden beide Körpervarianten (raw und gzip) vorgehalten — wiederholte Anfragen mitAccept-Encoding: gzipoder/xmltv.gzkomprimieren die Daten nicht erneut.Jeder Eintrag erhält einen
update-time-Zähler. Jede EPG-Aktualisierung (EIT-Import, XMLTV-Quellen-Refresh) erhöht den Zähler, und der Cache wird bei der nächsten Anfrage neu aufgebaut.
Cache erzwungen leeren:
POST /xmltv/reset-cache
Die Route wird vom Admin-Server (Port 43971/43981) bedient, nicht vom epg-server. Der Anfragekörper ist leer; die Antwort ist 200 OK mit einem JSON-Umschlag.
HTTP-Antwortcodes¶
Code |
Bedingung |
|---|---|
|
Anfrage verarbeitet. Der Körper ist ein XMLTV-Dokument (eventuell ein leeres |
|
Weder Digest noch |
|
Der Login existiert, aber die Anfrage kommt nicht von einer erlaubten IP, oder |
|
Jede URL außer |
|
Methode ist nicht GET. |
Der Fehlerkörper ist ein JSON-Umschlag mit festem Format:
{"status": 401, "message": "Unauthorized"}
Leistung und Skalierung¶
Server-Cache¶
Der Server-Cache bedient wiederholte Anfragen an dasselbe channel-set ohne SQLite-Zugriff — durch Kopieren des fertigen Körpers.
Der XMLTV-Aufbau „von Grund auf“ (Cache-Miss) ist teurer: pro Kanal ein eigenes SELECT über channel_name, pro Ereignis eines über event_text und event_rating. Anhaltspunkte zur Bauzeit:
Ausgabegröße |
Cache hit |
Cache miss (build) |
|---|---|---|
100 Kanäle / Tag |
einige Dutzend ms |
~0,5–1 s |
500 Kanäle / Tag |
~50 ms |
2–5 s |
1000+ Kanäle / Woche |
~100–300 ms |
5–15 s |
Für die meiste Middleware ist es akzeptabel, XMLTV alle paar Stunden oder einmal täglich abzufragen.
Wann ein externer Reverse-Proxy (nginx) nötig ist¶
Im Gegensatz zu /data/epg/channel (kurze JSON-Antworten) ist XMLTV ein einziges großes Dokument pro channel-set und damit ideal für einen Edge-Cache:
Zehn bis Hunderte Clients pro channel-set — der interne PSS-Cache reicht meist aus, wenn sie XMLTV stündlich bis täglich abfragen.
Tausende gleichzeitige Clients — ein cachender Reverse-Proxy wird empfohlen. Das Ausliefern einer XMLTV-Datei an Hunderte/Tausende Anfragen ist in erster Linie eine Netzwerklast (Hunderte KB – einige MB pro Antwort), die man besser von PSS fernhält.
Geografisch verteilte Auslieferung — ohne CDN/Edge-Cache geht es nicht, unabhängig von der Clientzahl.
PSS sendet Cache-Control: no-cache, daher muss nginx explizit angewiesen werden, den Upstream-Header zu ignorieren und einen eigenen TTL zu führen.
Beispielkonfiguration für nginx¶
# /etc/nginx/conf.d/pss-xmltv.conf
proxy_cache_path /var/cache/nginx/pss-xmltv
levels=1:2
keys_zone=pss_xmltv:8m
max_size=4g
inactive=2h
use_temp_path=off;
upstream pss_epg {
server 127.0.0.1:10444;
keepalive 16;
}
server {
listen 80;
# listen 443 ssl http2; # SSL termination makes sense here
server_name epg-files.example.com;
# Do not enable gzip on: /xmltv.gz is already compressed, and /xmltv
# arrives gzip-encoded from PSS — re-compressing is pointless.
location ~ ^/xmltv(\.gz)?$ {
proxy_pass http://pss_epg;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# PSS returns no-cache; force-cache it at the edge.
proxy_ignore_headers Cache-Control Expires Set-Cookie;
proxy_hide_header Cache-Control;
proxy_hide_header Pragma;
proxy_hide_header Expires;
# Cache key = full URL including query (login/password in /xmltv?l=...&p=...)
# produce distinct keys for different accounts with different channel-sets.
proxy_cache_key "$scheme$host$request_uri";
proxy_cache pss_xmltv;
proxy_cache_valid 200 30m; # XMLTV changes infrequently
proxy_cache_valid 401 403 1m;
proxy_cache_lock on; # coalesce cache misses
proxy_cache_lock_timeout 60s; # XMLTV build may take seconds
proxy_cache_use_stale error timeout updating
http_500 http_502 http_503;
# Large buffer: XMLTV for a big channel-set can reach
# several megabytes.
proxy_buffering on;
proxy_buffers 16 256k;
proxy_buffer_size 256k;
proxy_busy_buffers_size 1m;
# Let the client cache for a short period.
add_header Cache-Control "public, max-age=600";
add_header X-Cache-Status $upstream_cache_status always;
}
}
Erläuterungen und Empfehlungen¶
TTL ``proxy_cache_valid 200 30m`` — XMLTV ändert sich selten häufiger als alle halbe Stunde. Erfolgt die Synchronisation mit den Quellen stündlich oder seltener, kann der Wert auf 1 Stunde und mehr angehoben werden; ist Frische nach
POST /xmltv/reset-cachewichtig, senken Sie ihn.``proxy_cache_lock_timeout 60s`` — gegenüber
/data/epg/channelerhöht (dort üblich sind 5 Sekunden), weil der Aufbau eines XMLTV für ein großes channel-set länger dauert.Eine dedizierte ``keys_zone`` — selbst bei einer großen Installation sind eindeutige XMLTV-Schlüssel rar (Anzahl Logins ×
channel-set), 8 MB reichen mit Reserve.max_sizewird nach dem XMLTV-Volumen, nicht nach der Schlüsselanzahl bemessen.gzip auf nginx-Seite ist unnötig: Für
/xmltv.gzist die Antwort bereits komprimiert, für/xmltvantwortet PSS selbst gzip-encoded bei vorhandenemAccept-Encoding: gzip.HTTPS-Terminierung auf nginx liefert bessere Leistung bei vielen gleichzeitigen TLS-Handshakes.