---
title: DVR / Archives
url: https://doc.pstreamer.tv/fr/manual/dvr.html
lang: fr
product: Perfect Streamer
version: 1.13.3.445
---

# DVR / Archives

Depuis la version 1.13, **Perfect Streamer** intègre un DVR — une archive flux persistante sur disque, fonctionnant en parallèle avec la diffusion OTT normale (HLS / DASH). L’archive est écrite automatiquement, sans processus séparé, et lue via les mêmes URLs OTT que le live — seule différence : le paramètre query.

**Fonctionnalités :**

- Enregistrement de chaque flux OTT dans l’archive sur le stockage choisi.
- Lecture HLS, DASH et Low-Latency HLS de l’archive (VOD) sur les mêmes URL que le live (DASH et LL-HLS — sur CMAF, en *OTT/HLS/LL-HLS/LL-Dash*).
- Sous-titres (WebVTT) — écrits avec les chunks TS.
- Plusieurs stockages — un flux est lié à un seul ; différents flux peuvent écrire sur différents disques.
- Nettoyage automatique par temps de rétention et utilisation disque.
- EPG-aligned VOD — archive par référence à un événement EPG.
- VOD adaptatif — pris en charge pour les groupes adaptatifs.

**Le DVR ne requiert pas de licence séparée.** Activé par flux en ajoutant une liaison stockage.

Le DVR ne remplace pas la diffusion live. Si un flux possède une archive, le client reçoit une playlist live au comportement identique à celui sans DVR. L’archive ne commence à se lire que lorsque le client demande explicitement le mode VOD via un paramètre de requête de l’URL (voir ci-dessous).

## Configuration du stockage

Un stockage est un enregistrement dans la section **Configuration / DVR Storage**. Chaque enregistrement décrit un répertoire sur disque où PSS écrit les fichiers d’archive. Un flux utilise un stockage.

À l’ajout d’un stockage, on configure :

**Name** — nom affiché.

**Dir Path** — chemin du répertoire sur disque. Après création, le chemin **n’est pas modifiable** — pour déplacer l’archive, supprimer l’enregistrement et en créer un nouveau. Les fichiers existants **ne sont pas touchés sur disque** à la suppression.

**Max Usage**, % — seuil d’utilisation disque (par défaut 90 %). Au-dessus, le nettoyage size-based démarre (voir ci-dessous). Min 1 %, max 100 %.

**Cleanup Interval**, sec — période de la tâche de nettoyage (par défaut 10 sec). À chaque tick, on coupe d’abord tout ce qui dépasse la profondeur de rétention ; puis, si **Max Usage** est dépassé, les anciens chunks.

**Disk Pressure Grace**, sec — durée pendant laquelle **Used %** doit dépasser **Max Usage** en continu avant le **Size-based cleanup** (par défaut 60 sec). Filtre les pics courts.

**Disk Pressure Cut**, sec — limite haute par tick de nettoyage : secondes vidéo par flux supprimables d’un coup (par défaut 300 sec). Le reste passe au tick suivant.

**Disk Emergency Bytes** — seuil d’espace libre sous lequel le stockage passe en *Error* et l’enregistrement s’arrête (par défaut 2 GiB). Reprise auto si espace libre ≥ 2 × cette valeur.

**Alarm Disk-Full Hysteresis**, % — la marge sous **Max Usage** jusqu’à laquelle le nettoyage basé sur la taille abaisse le remplissage, afin que **Used %** ne fluctue pas juste au niveau du seuil (2 % par défaut).

La plupart des valeurs par défaut conviennent aux installations courantes ; seul **Max Usage** et **Dir Path** demandent généralement un ajustement.

**Il est judicieux de créer un stockage par disque.** Si plusieurs enregistrements avec des sous-répertoires différents sont définis sur le même disque, ils se disputent l’espace libre — le disque est partagé, mais le nettoyage est propre à chaque stockage.

## Liaison d’un flux à un stockage

Dans les paramètres **Stream / OTT** apparaît une section **DVR** :

**Storage** — liste déroulante des stockages ; *0* signifie « archive désactivée pour ce flux ».

**Storage Hours** — profondeur d’archive de ce flux, en heures, de 1 à 2160 (jusqu’à 90 jours). Les chunks plus anciens que cette valeur sont supprimés à chaque tick de la tâche de nettoyage (**Rolling cleanup**).

**Storage Min Hour** — seuil de protection bas (heures). Le nettoyage ne supprime jamais de chunks plus récents, même sous pression **Max Usage**. Utile si la logique métier exige un enregistrement récent garanti, ex. « les 2 dernières heures toujours présentes ».

Modification de **Storage** à la volée :

- mettre *0* — désactive l’archive ; les chunks sur disque sont **conservés**, plus rien n’est écrit. Les sessions VOD renvoient 404 ;
- choix d’un autre stockage — le flux se détache de l’ancien et écrit dans le nouveau. Les fichiers de l’ancien disque ne sont pas migrés.

Les modifications de **Storage Hours** et **Storage Min Hour** s’appliquent aussitôt — au tick suivant, le nettoyage utilise la nouvelle valeur.

Après configuration, le flux écrit automatiquement l’archive dès qu’il passe en *Running*.

## VOD : lecture de l’archive

L’archive est lue via **les mêmes URLs** que le live HLS / DASH (voir section *OTT service*) — seul le paramètre query change.

### URLs et paramètres

URL pour HLS, DASH et Low-Latency HLS (DASH et LL-HLS — sur CMAF, nécessitent le mode *OTT/HLS/LL-HLS/LL-Dash*) :

- [http://host:port/hls/stream/login/password/index.m3u8](http://host:port/hls/stream/login/password/index.m3u8)
- [http://host:port/dash/stream/login/password/index.mpd](http://host:port/dash/stream/login/password/index.mpd)
- [http://host:port/llhls/stream/login/password/index.m3u8](http://host:port/llhls/stream/login/password/index.m3u8)

Sans paramètre query — live ordinaire à **fenêtre glissante**. Avec le paramètre *t* — mode VOD.

| Paramètre | Rôle |
| --- | --- |
| `t=<epoch>` | Heure de début VOD (Unix epoch, sec). *t=0* — depuis le début de l’archive. La présence de *t* (même *t=0*) active le mode VOD. |
| `d=<sec>` | Durée de la fenêtre VOD, sec. *d=0* ou paramètre absent — « jusqu’à maintenant ». N’a de sens qu’avec *t*. |
| `epg=<epoch>` | EPG-aligned VOD : le serveur localise l’événement EPG actif au moment indiqué et prend ses *start* et *duration* comme bornes. Incompatible avec *t* et *d* (remplacement côté serveur). Voir ci-dessous. |
| `a`, `s`, `m`, `v` | Paramètres live standard (voir *OTT service*) ; `s` et `m` ignorés en mode VOD. |

Comportement selon *t* et *d* :

| t | d | Fenêtre | Condition 404 |
| --- | --- | --- | --- |
| aucun | — | live (fenêtre glissante) | — |
| 0 | aucun / 0 | [début archive, maintenant] | DVR non lié |
| 0 | > 0 | [début archive, +d] | DVR non lié |
| > 0 | aucun / 0 | [t, maintenant] | DVR non lié |
| > 0 | > 0 | [t, t+d] | DVR non lié |

Normalisation des bornes :

- *t* avant le début de l’archive — start est automatiquement aligné sur le premier chunk disponible (le nettoyage a pu rogner). Ce n’est **pas un 404** — on sert ce qui reste.
- *t* dans le futur ou fenêtre entièrement avant l’archive — playlist vide mais valide (HLS : header seul + `EXT-X-ENDLIST` ; DASH : `@type="static"`, `mediaPresentationDuration="PT0S"`).
- Les chunks sont sélectionnés strictement par leur instant de début tombant dans l’intervalle semi-ouvert *[t, t+d)* — pas de segments partiels.

VOD sur un flux sans archive (ou dont le stockage est en *Error*) — **404** immédiat sur master playlist / MPD. Aucune session créée.

Textes d’erreur dans le corps 404 (visibles dans les logs et le corps HTTP) :

- `VOD: stream not running` — le flux est dans la config mais pas en *Running*.
- `VOD: no DVR archive` — aucun stockage défini sur le flux, ou stockage en *Error*.
- `VOD: DVR detached` — le flux a été détaché du stockage entre les requêtes.
- `VOD: EPG event not found` — aucun événement trouvé pour `?epg=`.

Playlist HLS VOD — **fermée** (le lecteur voit la durée et peut chercher) :

```
#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
```

Ces marqueurs sont absents de la playlist live — c’est la seule différence.

MPD DASH VOD — **statique** : `@type="static"`, `mediaPresentationDuration` fixe, `<SegmentURL>` explicites. Le DASH live reste `@type="dynamic"`.

Si l’intervalle choisi a des **trous** dans l’archive (ex. redémarrage d’enregistrement ou nettoyage au milieu), le MPD DASH est scindé automatiquement en plusieurs `<Period>` — un par piste contiguë. Les lecteurs (VLC, dashjs, Shaka) franchissent les frontières de période sans configuration.

### EPG-aligned VOD

Si le flux est lié à une source EPG (champs **EPG Source** et **EPG Channel** des paramètres du flux), le client peut demander l’archive **par un instant compris dans un événement EPG** :

- [http://host:port/hls/stream/login/password/index.m3u8?epg=1778500000](http://host:port/hls/stream/login/password/index.m3u8?epg=1778500000)
- [http://host:port/dash/stream/login/password/index.mpd?epg=1778500000](http://host:port/dash/stream/login/password/index.mpd?epg=1778500000)

Le serveur localise l’événement EPG actif à l”*epoch* donné et utilise ses *start* et *duration* comme bornes de la fenêtre VOD. Utile pour les catalogues : l’UI connaît l’heure de l’événement mais n’a pas à calculer les bornes exactes.

Si le flux n’est pas lié à l’EPG ou qu’aucun événement n’est actif — **404 ``VOD: EPG event not found``**. *t* et *d* sont ignorés en présence de *epg*.

### Flux adaptatifs

Les groupes adaptatifs (voir [HLS Adaptive Multistream](ott.md#adaptive)) acceptent les mêmes paramètres VOD :

- [http://host:port/hls/adaptive/group/login/password/index.m3u8?t=0](http://host:port/hls/adaptive/group/login/password/index.m3u8?t=0)
- [http://host:port/dash/adaptive/group/login/password/index.mpd?t=0](http://host:port/dash/adaptive/group/login/password/index.mpd?t=0)

Seules les variantes avec un stockage DVR configuré entrent dans la master playlist (HLS). Celles sans DVR sont ignorées (`VOD: variant N has no DVR` apparaît au log) ; l’assemblage continue avec les autres.

En variante DASH, chaque qualité devient un `<Representation>` distinct dans des `<Period>` communs ; le lecteur peut changer de qualité sans rouvrir le manifeste.

### Comportement du lecteur

Le VOD HLS / DASH de l’archive est lu par les lecteurs standards : VLC, hls.js, dashjs, Shaka, ffmpeg. La recherche timeline marche.

Si le lecteur demande un segment déjà supprimé par le nettoyage, le serveur renvoie **404 pour ce segment** (pas 500). VLC, hls.js, dashjs sautent ce segment et continuent au suivant.

Fonctionnalités complémentaires :

- **Protection des sessions actives** : tant qu’une session VOD est ouverte, le nettoyage ne supprime pas les chunks dans sa fenêtre (voir ci-dessous).
- **Live-edge bridge** : si un client en session VOD demande un segment au-delà de la borne droite de la fenêtre VOD — par exemple, avance dans la timeline en atteignant la fin de l’archive — le serveur fournit automatiquement le segment depuis la mémoire live. Pas de redirections, pas de réauthentification.
- **Cache playlist** : sur des requêtes répétées du même VOD `index.m3u8` / `index.mpd`, le serveur renvoie une réponse identique octet pour octet — sans reconstruction. Adapté à un CDN devant PSS.

## Sous-titres dans l’archive

Si le flux porte des sous-titres (DVB Subtitling, Teletext ou WebVTT) et que l’option **OTT WebVTT** est active, les sous-titres sont archivés en parallèle des chunks TS — en fichiers `.vtt` à côté des `.ts`.

En live, la master playlist contient `EXT-X-MEDIA:TYPE=SUBTITLES` ; en VOD, le serveur renvoie une **playlist VOD de sous-titres** (avec `ENDLIST`) et des segments `.vtt` aux mêmes URLs.

Particularités :

- **HLS** : l’en-tête `X-TIMESTAMP-MAP` est conservé au début de chaque `.vtt` (requis par la spec HLS).
- **DASH** : l’en-tête `X-TIMESTAMP-MAP` est retiré à la volée (lié au PCR absolu, en conflit avec l’ancre DASH ; sinon VLC affiche des sous-titres vides).
- En groupe adaptatif : si le sub-stream actif n’écrit pas de sous-titres, les segments VTT renvoient 404. Sur la variante suivante, le lecteur peut en recevoir à nouveau.

Les sous-titres se désactivent via l’option **OTT WebVTT** du flux, ou en n’activant pas HLS en mode *OTT/HLS*.

## Nettoyage et rétention

PSS utilise quatre stratégies de nettoyage, exécutées à chaque tick de la tâche de nettoyage (par défaut toutes les 10 sec) :

1. **Rolling cleanup** (par flux) : pour chaque flux, les chunks plus vieux que **Storage Hours** sont supprimés. Tourne toujours, même disque à moitié vide.
2. **Size-based cleanup** (par stockage) : quand **Used %** dépasse en continu **Max Usage** pendant **Disk Pressure Grace** sec, les chunks les plus anciens sont coupés **au prorata** sur tous les flux liés au stockage. Par tick : **Disk Pressure Cut** sec vidéo par flux. Jamais de chunks plus jeunes que **Storage Min Hour**.
3. **Emergency disk-full cut** : si l’espace libre tombe sous **Disk Emergency Bytes**, le nettoyage devient agressif et peut supprimer même des chunks protégés. L’enregistrement s’arrête jusqu’à reprise de l’espace libre avec hystérésis × 2.
4. **Orphan scan** : des fichiers non répertoriés dans l’index peuvent subsister sur le disque (après un arrêt brutal de PSS). Le collecteur parcourt les sous-répertoires des flux et supprime ces fichiers « oubliés » — le premier passage peu après le démarrage du service, puis une fois par heure et à chaque déclenchement de la pression disque. Pour se protéger d’une course avec l’écriture, les fichiers de moins de 60 s sont ignorés.

**Note.** Les tâches de nettoyage tournent en arrière-plan ; l’utilisateur n’a normalement rien à faire. Si l’archive croît plus vite qu’elle n’est rognée, baisser **Storage Hours** sur les flux ou augmenter **Disk Pressure Cut**.

## Protection des sessions VOD actives

À l’ouverture d’une session VOD, un « créneau de protection » avec l’heure de début de fenêtre est posé sur chaque stockage impliqué. Les nettoyages **Rolling** et **size-based** ne touchent pas les chunks dans la fenêtre de la session ouverte. Le créneau est libéré automatiquement à la fermeture (FIN, timeout).

Cela signifie :

- Si un client garde une session VOD longtemps, il peut chercher tout instant dans sa fenêtre — les chunks ne « disparaissent pas sous lui ».
- Le nettoyage **Max Usage** peut temporairement ne pas ramener **Used %** au seuil tant qu’une session est active ; dès le départ du client, le nettoyage rattrape.
- **Emergency disk-full cut** et **Storage Min Hour** contournent la protection : si le disque est presque vide, les chunks sont supprimés et le client reçoit 404 sur les segments touchés (le lecteur les saute).
- Après redémarrage de PSS, les créneaux de protection disparaissent — le nettoyage reprend aussitôt.

## Plusieurs stockages

On peut créer un nombre quelconque d’enregistrements **DVR Storage** — un par répertoire / disque. Les flux sont liés indépendamment à différents stockages. Nettoyage et seuils (**Max Usage**, **Disk Pressure**) fonctionnent par stockage.

Cas d’usage :

- **Tiering par valeur** : stockage SSD rapide pour chaînes premium avec grande profondeur, stockage HDD capacitif pour les autres.
- **Disque dédié à l’archive** : pour que l’enregistrement DVR ne concurrence pas le disque système ou les fichiers temporaires.
- **Séparation par projet** : un disque pour le lot de chaînes nº 1, un autre pour le nº 2 — simplifie migration et audit.

Changer la liaison du flux (champ **Storage** dans **Stream / OTT**) bascule l’enregistrement à la volée. Les anciens fichiers restent intacts sur le disque précédent — à supprimer à la main ou à réattacher en remettant le flux.

## État du stockage et monitoring

La section **Data / DVR Storage List** (et l’API `GET /data/dvr-storage-list`) affiche par stockage :

- **State** — *Ready* / *Error* (ainsi que l’état intermédiaire *Not Ready* pour un stockage qui vient d’être ajouté).
- **Total / Free / Used Bytes** — espace libre et occupé sur le disque.
- **Used %** — pourcentage actuel d’utilisation.
- **Archived Bytes** — taille totale des chunks indexés sur tous les flux liés (hors fichiers orphelins).
- **Pressure Since Sec** — moment (epoch) où **Used %** a d’abord dépassé **Max Usage** dans l’épisode courant ; *0* signifie « pas de pression ».
- **Active Task** — l’opération de maintenance en arrière-plan en cours d’exécution : *gc-orphans* (suppression des fichiers orphelins), *disk-pressure-trim* (élagage sous pression disque) ou *none*, et depuis combien de secondes elle s’exécute. Les opérations de courte durée (< 2 s) ne clignotent pas dans l’interface.
- **Last cleanup** — un récapitulatif des dernières exécutions de nettoyage : depuis combien de temps a eu lieu la précédente collecte des fichiers orphelins (et combien ont été supprimés) et le dernier élagage sous pression disque (combien d’espace a été libéré).
- **Attached streams** — la liste des flux rattachés ; pour chacun sont affichés le nom, l’indicateur d’enregistrement en cours (*active*), la profondeur d’archive configurée (*retention-hours*) et le remplissage réel (*archived-sec* et *archived-bytes*). La somme des *archived-bytes* sur l’ensemble des flux est égale aux **Archived Bytes** de tout le stockage.

États :

- *Ready* — le répertoire est disponible, l’enregistrement et le nettoyage se déroulent normalement.
- *Error* — le répertoire de stockage est indisponible (démonté, droits manquants, erreur de système de fichiers) ou l’espace libre sur le disque est critique ; l’enregistrement est arrêté. La récupération est automatique — dès que le répertoire est de nouveau disponible et qu’un espace libre suffisant apparaît.

Si le stockage est passé en *Error*, vérifiez si le répertoire de l’archive est monté et s’il y a de l’espace libre sur le disque — PSS ne sort pas seul de cet état tant que le problème n’est pas physiquement résolu.

Remplissage de l’archive dans le temps :

- Au niveau du flux (**Data / Stream**), la métrique **storage-gap-percent** est disponible — la proportion de trous temporels dans l’archive accumulée : *0 %* signifie un enregistrement continu, des valeurs plus élevées signifient qu’il y a des trous dans l’archive (redémarrages de la source, segments supprimés par le nettoyage).
- Le endpoint `GET /data/dvrstat` renvoie un histogramme du remplissage de l’archive par intervalles de temps, avec le marquage des événements d’enregistrement (démarrage/arrêt de la source, changement de **PMT**, commutations de l’embrouillage, reconstruction de l’index, passage de nettoyage) et de l’activité des sous-titres — pour le rendu de la frise de l’archive DVR dans l’interface d’administration.

## Protection contre la perte accidentelle

Plusieurs opérations admin entraînent une **perte d’archive** ou un **arrêt de la diffusion VOD**. Avant exécution, l’UI affiche une confirmation modale :

- **Suppression d’un DVR Storage** — tous les flux liés perdent l’accès VOD ; les fichiers restent sur disque mais sont inaccessibles via PSS sans l’enregistrement.
- **Bascule du flux vers un autre stockage** — le VOD sur l’ancienne archive cesse.
- **Détachement du flux du stockage** (Storage = 0) — même effet.
- **Baisse de Max Usage** — peut déclencher le nettoyage size-based et supprimer d’anciens chunks.
- **Baisse de Storage Hours / Storage Min Hour** — peut sortir une partie de l’archive du rolling.

Décision produit assumée : opération autorisée mais avec confirmation, et les fichiers supprimés restent sur disque (restaurables depuis un backup). Placer l’archive sur un serveur de fichiers / RAID séparé réduit fortement le risque de perte irréversible.

## Limites de la version actuelle

- Une session VOD ouverte par un client **ne suit pas** le live edge — si de nouveaux chunks ont été ajoutés pendant la session, le client doit redemander la playlist (comportement standard HLS / DASH).
- Un stockage par disque est recommandé — plusieurs enregistrements avec sous-répertoires différents se disputent l’espace libre.
- Les segments sont adressés par hachage (HLS sur MPEG-TS) ou via le modèle `$Number$.m4s` avec un `init.mp4` commun (live DASH sur CMAF) / via des `<SegmentURL>` explicites vers des `.m4s` (VOD DASH). Modifier la taille de chunk entre live et VOD ne nécessite pas de rouvrir l’URL.
- Le scanner orphelin tourne chaque heure ; pour accélérer, redémarrer PSS.
