DVR / Archiv¶
Ab Version 1.13 bietet Perfect Streamer einen integrierten DVR — ein persistentes Stream-Archiv auf der Platte, das parallel zur normalen OTT-Ausgabe (HLS / DASH) läuft. Das Archiv wird automatisch geschrieben, ohne separaten Prozess, und über dieselben OTT-URLs wie Live wiedergegeben — Unterschied ist nur der Query-Parameter.
Funktionen:
Aufzeichnung jedes OTT-Streams ins Archiv auf dem gewählten Speicher.
HLS-, DASH- und Low-Latency-HLS-Wiedergabe des Archivs (VOD) über dieselben URLs wie live (DASH und LL-HLS — über CMAF, im OTT/HLS/LL-HLS/LL-Dash).
Untertitel-Unterstützung (WebVTT) — neben TS-Chunks geschrieben.
Mehrere Speicher — ein Stream wird an einen gebunden; verschiedene Streams können auf verschiedene Platten schreiben.
Automatische Bereinigung nach Aufbewahrungszeit und Speicherauslastung.
EPG-aligned VOD — Archivausgabe per EPG-Ereignis-Bezug.
Adaptives VOD — wird für adaptive Gruppen unterstützt.
DVR erfordert keine separate Lizenz. Aktivierung pro Stream durch Hinzufügen einer Speicherbindung.
DVR ersetzt das Live-Broadcasting nicht. Hat ein Stream ein Archiv, erhält der Client eine Live-Playlist mit identischem Verhalten wie ohne DVR. Das Archiv beginnt erst dann zu spielen, wenn der Client den VOD-Modus explizit über einen URL-Query-Parameter anfordert (siehe unten).
Speicher-Konfiguration¶
Ein Speicher ist ein Eintrag im Abschnitt Configuration / DVR Storage. Jeder Eintrag beschreibt ein Verzeichnis auf der Platte, in das PSS Archivdateien schreibt. Ein Stream nutzt einen Speicher.
Beim Hinzufügen eines Speichers werden konfiguriert:
Name — Anzeigename.
Dir Path — Pfad zum Verzeichnis auf der Platte. Nach Erstellung des Eintrags ist der Pfad nicht änderbar — um das Archiv zu verschieben, Eintrag löschen und neuen mit neuem Pfad anlegen. Bestehende Dateien werden beim Löschen auf der Platte nicht angerührt.
Max Usage, % — Schwellenwert der Auslastung (Standard 90 %). Bei Überschreitung startet die size-based Bereinigung (siehe unten). Minimum 1 %, Maximum 100 %.
Cleanup Interval, Sek — Periode der Bereinigungsaufgabe (Standard 10 Sek). Bei jedem Tick wird zunächst alles älter als die Aufbewahrungstiefe entfernt; danach — bei Max Usage-Überschreitung — alte Chunks.
Disk Pressure Grace, Sek — wie lange Used % Max Usage durchgehend überschreiten muss, bevor Size-based cleanup startet (Standard 60 Sek). Filtert kurze Spitzen.
Disk Pressure Cut, Sek — Obergrenze pro Bereinigungs-Tick: wie viele Videosekunden pro Stream auf einmal gelöscht werden dürfen (Standard 300 Sek). Der Rest geht in den nächsten Tick.
Disk Emergency Bytes — Schwellenwert für freien Speicher, unter dem der Speicher in Error übergeht und Aufzeichnung stoppt (Standard 2 GiB). Auto-Wiederherstellung bei freiem Platz ≥ 2 × diesem Wert.
Alarm Disk-Full Hysteresis, % — der Abstand unterhalb von Max Usage, bis zu dem die größenbasierte Bereinigung den Füllstand absenkt, damit Used % nicht direkt an der Schwelle schwankt (standardmäßig 2 %).
Die meisten Standardwerte passen für typische Installationen; Anpassungen sind meist nur für Max Usage und Dir Path nötig.
Pro Platte ist es sinnvoll, einen Speicher anzulegen. Werden auf derselben Platte mehrere Einträge mit verschiedenen Unterordnern angegeben, konkurrieren sie um freien Platz — die Platte ist gemeinsam, die Bereinigung läuft jedoch je Speicher.
Stream an Speicher binden¶
In den Stream / OTT-Einstellungen erscheint ein DVR-Abschnitt:
Storage — Dropdown verfügbarer Speicher; 0 bedeutet „Archiv für diesen Stream deaktiviert“.
Storage Hours — Archivtiefe für diesen Stream, in Stunden, von 1 bis 2160 (bis zu 90 Tage). Chunks, die älter als dieser Wert sind, werden bei jedem Tick der Bereinigungsaufgabe (Rolling cleanup) gelöscht.
Storage Min Hour — untere Schutzschwelle (Stunden). Die Bereinigung löscht nie Chunks jünger als dieser Wert, auch nicht unter Max Usage-Druck. Verwenden, wenn die Geschäftslogik eine garantierte frische Aufzeichnung verlangt, z. B. „letzte 2 Stunden immer vorhanden“.
Storage zur Laufzeit ändern:
0 setzen — deaktiviert das Archiv; vorhandene Chunks bleiben erhalten, neue werden nicht geschrieben. VOD-Sitzungen liefern fortan 404;
Auswahl eines anderen Speichers — der Stream wird vom alten gelöst und schreibt in den neuen. Dateien vom alten Speicher werden nicht migriert.
Änderungen an Storage Hours und Storage Min Hour wirken sofort — beim nächsten Tick verwendet die Bereinigung den neuen Wert.
Nach Konfiguration schreibt der Stream automatisch das Archiv, sobald er in den Zustand Running wechselt.
VOD: Archivwiedergabe¶
Das Archiv wird über dieselben URLs wie Live HLS / DASH wiedergegeben (siehe Abschnitt OTT-Service) — nur der Query-Parameter unterscheidet sich.
URLs und Parameter¶
URLs für HLS, DASH und Low-Latency HLS (DASH und LL-HLS — über CMAF, erfordern den Modus OTT/HLS/LL-HLS/LL-Dash):
Ohne Query-Parameter — normales Live mit Sliding Window. Mit t-Parameter — VOD-Modus.
Parameter |
Zweck |
|---|---|
|
VOD-Startzeit (Unix epoch, Sek). t=0 — ab Archivanfang. Das Vorhandensein von t (auch t=0) aktiviert den VOD-Modus. |
|
VOD-Fensterdauer, Sek. d=0 oder Parameter fehlt — „bis zum aktuellen Moment“. Nur sinnvoll zusammen mit t. |
|
EPG-aligned VOD: Der Server findet selbst das zum angegebenen Moment aktive EPG-Ereignis und nimmt dessen start und duration als Fenstergrenzen. Inkompatibel mit t und d (server-seitige Ersetzung). Siehe unten. |
|
Standardparameter für Live (siehe OTT-Service); |
Verhalten nach t und d:
t |
d |
Fenster |
404-Bedingung |
|---|---|---|---|
keiner |
— |
live (Sliding Window) |
— |
0 |
keiner / 0 |
[Archivanfang, jetzt] |
DVR nicht gebunden |
0 |
> 0 |
[Archivanfang, +d] |
DVR nicht gebunden |
> 0 |
keiner / 0 |
[t, jetzt] |
DVR nicht gebunden |
> 0 |
> 0 |
[t, t+d] |
DVR nicht gebunden |
Grenzen-Normalisierung:
t vor Archivanfang — start wird automatisch auf den ersten verfügbaren Chunk gezogen (Cleanup könnte schon getrimmt haben). Das ist kein 404 — der Rest wird ausgeliefert.
t in der Zukunft oder Fenster komplett vor dem Archiv — leere, aber gültige Playlist (HLS: nur Header +
EXT-X-ENDLIST; DASH:@type="static",mediaPresentationDuration="PT0S").Chunks werden strikt anhand des Chunk-Startzeitpunkts ausgewählt, der in das halboffene Intervall [t, t+d) fällt — es gibt keine Teilsegmente.
VOD auf einem Stream ohne Archiv (oder dessen Speicher in Error ist) — 404 sofort auf Master-Playlist / MPD. Keine Sitzung wird angelegt.
Fehlertexte im 404-Body (in Server-Logs und HTTP-Body sichtbar):
VOD: stream not running— Stream ist im Konfig, aber nicht in Running.VOD: no DVR archive— kein Speicher am Stream eingestellt oder Speicher in Error.VOD: DVR detached— Stream wurde zwischen Anfragen vom Speicher gelöst.VOD: EPG event not found— kein Ereignis für?epg=gefunden.
VOD-HLS-Playlist — geschlossen (Player sieht Dauer und kann spulen):
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:5.000,
...
#EXT-X-ENDLIST
In der Live-Playlist fehlen diese Marker — das ist der einzige Unterschied.
VOD-DASH-MPD — statisch: @type="static", festes mediaPresentationDuration, explizite <SegmentURL>. Live-DASH bleibt @type="dynamic".
Hat das gewählte Intervall Lücken im Archiv (z. B. durch Aufzeichnungs-Neustart oder mittendrin getrimmten Cleanup), wird das DASH-MPD automatisch in mehrere <Period> aufgeteilt — eines pro durchgehende Spur. Player (VLC, dashjs, Shaka) spulen über die Periodengrenze ohne Sonderkonfiguration.
EPG-aligned VOD¶
Ist der Stream mit einer EPG-Quelle verbunden (Felder EPG Source und EPG Channel in den Stream-Einstellungen), kann der Client das Archiv anhand eines Zeitpunkts innerhalb eines EPG-Ereignisses anfordern:
http://host:port/hls/stream/login/password/index.m3u8?epg=1778500000
http://host:port/dash/stream/login/password/index.mpd?epg=1778500000
Der Server findet das beim angegebenen epoch aktive EPG-Ereignis und setzt dessen start und duration als VOD-Fenstergrenzen ein. Nützlich für Programmkataloge: Die UI kennt die Ereigniszeit, muss aber keine genauen Sek-/ms-Grenzen berechnen.
Ist der Stream nicht an EPG gebunden oder gibt es zu diesem Moment kein Ereignis — 404 ``VOD: EPG event not found``. t und d werden bei vorhandenem epg ignoriert.
Adaptive Streams¶
Adaptive Gruppen (siehe HLS Adaptive Multistream) unterstützen dieselben VOD-Parameter:
http://host:port/hls/adaptive/group/login/password/index.m3u8?t=0
http://host:port/dash/adaptive/group/login/password/index.mpd?t=0
In die Master-Playlist (HLS) gelangen nur Varianten mit konfiguriertem DVR-Speicher. Varianten ohne DVR werden übersprungen (im Log VOD: variant N has no DVR); der Aufbau aus den verbleibenden Varianten läuft weiter.
In der DASH-Variante wird jede Qualität zu einem eigenen <Representation> innerhalb gemeinsamer <Period>; der Player kann zwischen Qualitäten ohne Manifest-Reopen wechseln.
Player-Verhalten¶
VOD-HLS / DASH aus dem Archiv läuft in Standard-Playern: VLC, hls.js, dashjs, Shaka, ffmpeg. Timeline-Spulen funktioniert.
Fordert der Player ein Segment an, das der Cleanup bereits entfernt hat, gibt der Server 404 für dieses Segment zurück (nicht 500). VLC, hls.js, dashjs überspringen das Segment und spielen vom nächsten weiter.
Zusätzliche Möglichkeiten:
Schutz aktiver Sitzungen: Solange eine VOD-Sitzung offen ist, löscht der Cleanup keine Chunks im Fenster (siehe unten).
Live-edge bridge: Fordert ein Client in einer VOD-Sitzung ein Segment jenseits der rechten Grenze des VOD-Fensters an — z. B. nach Erreichen des Archivendes vorwärts in der Timeline — liefert der Server das Segment automatisch aus dem Live-Speicher. Keine Weiterleitungen und keine erneute Autorisierung.
Playlist-Cache: Auf wiederholte Anfragen derselben VOD
index.m3u8/index.mpdliefert der Server eine byteidentische Antwort — ohne Neuaufbau. Geeignet für CDN vor PSS.
Untertitel im Archiv¶
Trägt der Stream Untertitel (DVB Subtitling, Teletext oder WebVTT) und ist die Option OTT WebVTT aktiviert, werden Untertitel parallel zu den TS-Chunks archiviert — als .vtt-Dateien neben .ts.
Im Live-Modus enthält die Master-Playlist EXT-X-MEDIA:TYPE=SUBTITLES; im VOD-Modus liefert der Server eine VOD-Untertitel-Playlist (mit ENDLIST) und .vtt-Segmente unter denselben URLs.
Hinweise:
HLS: Der
X-TIMESTAMP-MAP-Header bleibt am Anfang jeder.vtt(per HLS-Spezifikation erforderlich).DASH: Der
X-TIMESTAMP-MAP-Header wird im Flug entfernt (an absolute PCR gebunden, kollidiert mit dem DASH-Anker; sonst zeigt VLC leere Untertitel).In adaptiver Gruppe: Schreibt der aktive Sub-Stream keine Untertitel, liefern VTT-Segmente 404. Auf der nächsten Variante kann der Player wieder Untertitel erhalten.
Untertitel lassen sich entweder per OTT WebVTT-Option am Stream deaktivieren oder indem HLS im Modus OTT/HLS gar nicht aktiviert wird.
Bereinigung und Retention¶
PSS verwendet vier Bereinigungsstrategien, die bei jedem Tick der Bereinigungsaufgabe laufen (Standard alle 10 Sek):
Rolling cleanup (pro Stream): Pro Stream werden Chunks älter als Storage Hours gelöscht. Läuft immer, auch bei halbleerer Platte.
Size-based cleanup (speicherweit): Wenn Used % durchgehend für Disk Pressure Grace Sek Max Usage überschreitet, werden die ältesten Chunks proportional über alle Streams des Speichers getrimmt. Pro Tick Disk Pressure Cut Sek Video je Stream. Nie Chunks jünger als Storage Min Hour.
Emergency disk-full cut: Fällt der freie Speicher unter Disk Emergency Bytes, läuft die Bereinigung aggressiv und kann auch sitzungsgeschützte Chunks löschen. Aufzeichnung stoppt, bis der freie Platz mit Hysterese × 2 wiederhergestellt ist.
Orphan scan: Auf der Platte können Dateien verbleiben, die nicht im Index erfasst sind (nach einem plötzlichen Stopp von PSS). Der Collector durchläuft die Stream-Unterverzeichnisse und löscht solche „vergessenen“ Dateien — der erste Lauf kurz nach dem Start des Dienstes, danach einmal pro Stunde und bei Auslösen von Disk Pressure. Als Schutz vor einem Race mit dem Schreiben werden Dateien jünger als 60 Sek. übersprungen.
Hinweis. Bereinigungsaufgaben laufen im Hintergrund; in der Regel ist kein Eingreifen nötig. Wächst das Archiv schneller als es getrimmt wird, Storage Hours auf den Streams senken oder Disk Pressure Cut erhöhen.
Schutz aktiver VOD-Sitzungen¶
Wenn ein Client eine VOD-Sitzung öffnet, wird auf jedem beteiligten Speicher ein „Schutzslot“ mit Fenster-Startzeit registriert. Rolling- und size-based-Cleanup berühren Chunks im Fenster offener Sitzung nicht. Der Slot wird beim Schließen (FIN, Timeout) automatisch freigegeben.
Das heißt:
Hält ein Client eine VOD-Sitzung lange, kann er garantiert zu jedem Moment im Fenster spulen — Chunks „verschwinden nicht unter ihm“.
Die Bereinigung per Max Usage kann Used % vorübergehend nicht auf die Schwelle drücken, solange eine Sitzung aktiv ist; verlässt der Client den Stream, holt die Bereinigung auf.
Emergency disk-full cut und Storage Min Hour umgehen den Schutz: Ist die Platte fast leer, werden Chunks gelöscht und der Client erhält 404 für die betroffenen Segmente (der Player überspringt).
Nach PSS-Neustart verschwinden Schutzslots — Bereinigung läuft sofort weiter.
Mehrere Speicher¶
Beliebig viele DVR Storage-Einträge sind möglich — je Verzeichnis / Platte einer. Streams werden unabhängig an verschiedene Speicher gebunden. Bereinigung und Schwellen (Max Usage, Disk Pressure) wirken per-storage.
Anwendungsfälle:
Tiering nach Wert: SSD-Speicher für Premium-Kanäle mit großer Tiefe, HDD-Speicher hoher Kapazität für den Rest.
Eigene Platte für das Archiv: damit die DVR-Aufzeichnung nicht mit Systemplatte oder Temp-Dateien konkurriert.
Projekttrennung: eine Platte für Kanalpaket Nr. 1, eine andere für Nr. 2 — vereinfacht Migration und Audit.
Das Ändern der Stream-Bindung (Feld Storage in Stream / OTT) schaltet die Aufzeichnung im Betrieb um. Alte Dateien bleiben auf der bisherigen Platte unangetastet — sie lassen sich manuell löschen oder durch Rückumstellung wieder anbinden.
Speicherzustand und Monitoring¶
Im Abschnitt Data / DVR Storage List (sowie über API GET /data/dvr-storage-list) werden pro Speicher angezeigt:
State — Ready / Error (plus den Zwischenzustand Not Ready bei einem gerade hinzugefügten Storage).
Total / Free / Used Bytes — freier und belegter Speicherplatz auf der Platte.
Used % — aktueller Auslastungsanteil.
Archived Bytes — Gesamtgröße der im Index aller gebundenen Streams erfassten Chunks (ohne Orphan-Dateien).
Pressure Since Sec — Moment (epoch), zu dem Used % im aktuellen Druckepisode erstmals Max Usage überschritten hat; 0 heißt „kein Druck jetzt“.
Active Task — die gerade laufende Wartungs-Hintergrundoperation: gc-orphans (Entfernen verwaister Dateien), disk-pressure-trim (Kürzen unter Plattendruck) oder none, sowie wie viele Sekunden sie bereits läuft. Kurzlebige (< 2 s) Operationen flackern in der UI nicht.
Last cleanup — eine Zusammenfassung der letzten Bereinigungsläufe: wie lange der vorherige Einsammelvorgang verwaister Dateien zurückliegt (und wie viele davon gelöscht wurden) sowie das letzte Kürzen unter Speicherplatzdruck (wie viel Platz freigegeben wurde).
Attached streams — die Liste der angebundenen Streams; für jeden werden der Name, der Indikator einer laufenden Aufzeichnung (active), die konfigurierte Archivtiefe (retention-hours) und der tatsächliche Füllstand (archived-sec und archived-bytes) angezeigt. Die Summe der archived-bytes über alle Streams entspricht den Archived Bytes des gesamten Speichers.
Zustände:
Ready — das Verzeichnis ist verfügbar, Aufzeichnung und Bereinigung laufen normal.
Error — das Speicherverzeichnis ist nicht verfügbar (ausgehängt, fehlende Rechte, Dateisystemfehler) oder es ist kritisch wenig freier Platz auf der Platte; die Aufzeichnung ist gestoppt. Die Wiederherstellung erfolgt automatisch — sobald das Verzeichnis wieder verfügbar ist und genügend freier Platz vorhanden ist.
Ist der Speicher in Error gegangen, prüfen Sie, ob das Archivverzeichnis eingehängt ist und ob auf der Platte freier Speicher vorhanden ist — PSS verlässt diesen Zustand nicht von selbst, solange das Problem nicht physisch behoben ist.
Archivfüllstand im Zeitverlauf:
Auf Stream-Ebene (Data / Stream) steht die Metrik storage-gap-percent zur Verfügung — der Anteil zeitlicher Lücken im angesammelten Archiv: 0 % bedeutet durchgehende Aufzeichnung, höhere Werte bedeuten, dass es Lücken im Archiv gibt (Neustarts der Quelle, durch die Bereinigung gekürzte Abschnitte).
Der Endpoint
GET /data/dvrstatliefert ein Histogramm der Archivfüllung nach Zeitintervallen mit Markierung von Aufnahmeereignissen (Start/Stopp der Quelle, PMT-Wechsel, Scrambling-Umschaltungen, Index-Neuaufbau, Bereinigungslauf) und Untertitel-Aktivität — zur Darstellung der DVR-Archiv-Zeitleiste in der Admin-Oberfläche.
Schutz vor versehentlichem Datenverlust¶
Mehrere Operationen der Admin-Oberfläche führen zum Verlust des aufgezeichneten Archivs oder Ende der VOD-Auslieferung. Vor der Ausführung zeigt die Admin-UI eine modale Bestätigung:
DVR-Storage löschen — alle gebundenen Streams verlieren VOD-Zugriff; Dateien bleiben auf der Platte, sind aber ohne Eintrag über PSS nicht erreichbar.
Stream auf anderen Speicher umstellen — VOD über das alte Archiv funktioniert nicht mehr.
Stream vom Speicher lösen (Storage = 0) — gleicher Effekt.
Max Usage senken — kann size-based Bereinigung auslösen und alte Chunks löschen.
Storage Hours / Storage Min Hour senken — kann Teile des Archivs aus dem Rolling-Fenster drängen.
Dies ist eine bewusste Produktentscheidung: Die Operation ist möglich, aber mit Bestätigung, und gelöschte Dateien bleiben auf der Platte (Restore aus Backup möglich). Das Archiv auf separatem Fileserver / RAID senkt das Risiko irreversiblen Verlusts deutlich.
Einschränkungen der aktuellen Version¶
Eine vom Client geöffnete VOD-Sitzung verfolgt die Live-Edge nicht — wenn während der Sitzung neue Chunks ins Archiv kamen, muss der Client die Playlist neu anfordern (Standard aller HLS / DASH Player).
Pro Platte ist ein Speicher sinnvoll — mehrere Einträge mit verschiedenen Unterordnern konkurrieren um freien Platz.
Segmente werden per Hash adressiert (HLS über MPEG-TS) oder über die Vorlage
$Number$.m4smit gemeinsamerinit.mp4(live DASH über CMAF) / über explizite<SegmentURL>auf.m4s(VOD DASH). Eine Änderung der Chunk-Größe zwischen live und VOD erfordert kein erneutes Öffnen der URL.Der Orphan-Scanner läuft stündlich; zur Beschleunigung PSS neu starten.