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

# DVR / Arquivo

Desde a versão 1.13, **Perfect Streamer** inclui um DVR integrado — um arquivo de fluxo persistente em disco, paralelo à saída OTT normal (HLS / DASH). O arquivo é gravado automaticamente, sem processo separado, e reproduzido pelas mesmas URLs OTT que o live — única diferença: o parâmetro query.

**Recursos:**

- Gravação de cada fluxo OTT ao arquivo no armazenamento escolhido.
- Reprodução HLS, DASH e Low-Latency HLS do arquivo (VOD) nas mesmas URLs que o live (DASH e LL-HLS — em CMAF, no *OTT/HLS/LL-HLS/LL-Dash*).
- Legendas (WebVTT) — gravadas junto com chunks TS.
- Vários armazenamentos — um fluxo é vinculado a um; fluxos distintos podem gravar em discos distintos.
- Limpeza automática por tempo de retenção e uso do disco.
- EPG-aligned VOD — arquivo conforme evento EPG referenciado.
- VOD adaptativo — suportado para grupos adaptativos.

**O DVR não requer licença separada.** Ativado por fluxo adicionando vinculação ao armazenamento.

O DVR não substitui a transmissão ao vivo. Se um fluxo possui arquivo, o cliente recebe uma playlist ao vivo com o mesmo comportamento de quando não há DVR. O arquivo só começa a reproduzir quando o cliente solicita explicitamente o modo VOD por meio de um parâmetro de consulta da URL (ver abaixo).

## Configuração do armazenamento

Um armazenamento é um registro na seção **Configuration / DVR Storage**. Cada registro descreve um diretório em disco onde PSS grava arquivos. Um fluxo usa um armazenamento.

Ao adicionar um armazenamento, configura-se:

**Name** — nome exibido.

**Dir Path** — caminho do diretório em disco. Após criar o registro, o caminho **não pode ser alterado** — para mover o arquivo, apagar o registro e criar um novo. Os arquivos existentes **não são tocados em disco** ao apagar o registro.

**Max Usage**, % — limiar de uso do disco (padrão 90 %). Ao exceder, inicia limpeza size-based (ver abaixo). Mín 1 %, máx 100 %.

**Cleanup Interval**, seg — período da tarefa de limpeza (padrão 10 seg). A cada tick corta-se primeiro o mais antigo que a profundidade de retenção; depois, se exceder **Max Usage**, chunks antigos.

**Disk Pressure Grace**, seg — segundos que **Used %** deve exceder **Max Usage** continuamente antes do **Size-based cleanup** (padrão 60 seg). Filtra picos curtos.

**Disk Pressure Cut**, seg — limite superior por tick de limpeza: segundos de vídeo por fluxo apagáveis de uma vez (padrão 300 seg). O resto passa ao próximo tick.

**Disk Emergency Bytes** — limiar de espaço livre abaixo do qual o armazenamento entra em *Error* e a gravação para (padrão 2 GiB). Recuperação auto se espaço livre ≥ 2 × este valor.

**Alarm Disk-Full Hysteresis**, % — a margem abaixo de **Max Usage** até à qual a limpeza baseada em tamanho reduz o preenchimento, para que **Used %** não oscile mesmo junto ao limiar (2 % por padrão).

A maioria dos valores padrão serve para instalações típicas; geralmente basta ajustar **Max Usage** e **Dir Path**.

**Faz sentido criar um armazenamento por disco.** Se no mesmo disco forem indicados vários registros com subdiretórios distintos, eles competirão pelo espaço livre — o disco é compartilhado, mas a limpeza é própria de cada armazenamento.

## Vinculação de um fluxo ao armazenamento

Nos ajustes **Stream / OTT** aparece uma seção **DVR**:

**Storage** — lista suspensa de armazenamentos; *0* significa «arquivo desativado para este fluxo».

**Storage Hours** — profundidade do arquivo para este fluxo, em horas, de 1 a 2160 (até 90 dias). Os chunks mais antigos que esse valor são apagados a cada tick da tarefa de limpeza (**Rolling cleanup**).

**Storage Min Hour** — limiar de proteção inferior (horas). A limpeza nunca apaga chunks mais novos, mesmo sob pressão **Max Usage**. Útil se a lógica de negócio exige gravação recente garantida, ex. «as últimas 2 horas sempre presentes».

Alteração de **Storage** em tempo real:

- definir *0* — desativa o arquivo; os chunks em disco são **mantidos**, novos não são gravados. As sessões VOD passam a responder 404;
- escolher outro armazenamento — o fluxo se desvincula do antigo e passa a gravar no novo. Os arquivos do antigo não são migrados.

Mudanças em **Storage Hours** e **Storage Min Hour** se aplicam de imediato — a limpeza usa o novo valor no próximo tick.

Após configuração, o fluxo grava o arquivo automaticamente ao entrar em *Running*.

## VOD: reprodução do arquivo

O arquivo é reproduzido pelas **mesmas URLs** que o live HLS / DASH (ver seção *OTT service*) — só muda o parâmetro query.

### URLs e parâmetros

URLs para HLS, DASH e Low-Latency HLS (DASH e LL-HLS — em CMAF, requerem o modo *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)

Sem parâmetros query — live normal com **janela deslizante**. Com o parâmetro *t* — modo VOD.

| Parâmetro | Função |
| --- | --- |
| `t=<epoch>` | Hora de início VOD (Unix epoch, seg). *t=0* — desde o início do arquivo. A presença de *t* (mesmo *t=0*) ativa o modo VOD. |
| `d=<sec>` | Duração da janela VOD, seg. *d=0* ou ausente — «até o momento atual». Só faz sentido com *t*. |
| `epg=<epoch>` | EPG-aligned VOD: o servidor localiza o evento EPG ativo no momento dado e usa seus *start* e *duration* como bordas da janela. Incompatível com *t* e *d* (substituição server-side). Ver abaixo. |
| `a`, `s`, `m`, `v` | Parâmetros live padrão (ver *OTT service*); `s` e `m` são ignorados em modo VOD. |

Comportamento conforme *t* e *d*:

| t | d | Janela | Condição 404 |
| --- | --- | --- | --- |
| nenhum | — | live (janela deslizante) | — |
| 0 | nenhum / 0 | [início arquivo, agora] | DVR não vinculado |
| 0 | > 0 | [início arquivo, +d] | DVR não vinculado |
| > 0 | nenhum / 0 | [t, agora] | DVR não vinculado |
| > 0 | > 0 | [t, t+d] | DVR não vinculado |

Normalização das bordas:

- *t* anterior ao início do arquivo — start é alinhado automaticamente ao primeiro chunk disponível (a limpeza pode ter cortado). Não é **404** — entrega-se o que resta.
- *t* no futuro ou janela toda antes do arquivo — playlist vazia mas válida (HLS: só header + `EXT-X-ENDLIST`; DASH: `@type="static"`, `mediaPresentationDuration="PT0S"`).
- Os chunks são selecionados estritamente pelo instante de início do chunk que cai no intervalo semiaberto *[t, t+d)* — não há segmentos parciais.

VOD em um fluxo sem arquivo (ou cujo armazenamento está em *Error*) — **404** imediato em master playlist / MPD. Nenhuma sessão é criada.

Texto de erro no corpo 404 (visível em logs do servidor e HTTP body):

- `VOD: stream not running` — o fluxo está na config mas não em *Running*.
- `VOD: no DVR archive` — o fluxo não tem armazenamento ou está em *Error*.
- `VOD: DVR detached` — o fluxo se desvinculou do armazenamento entre requisições.
- `VOD: EPG event not found` — sem evento para `?epg=`.

Playlist HLS VOD — **fechada** (o player vê a duração e pode buscar):

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

Esses marcadores não estão na playlist live — essa é a única diferença.

MPD DASH VOD — **estático**: `@type="static"`, `mediaPresentationDuration` fixo, `<SegmentURL>` explícitos. O DASH live permanece `@type="dynamic"`.

Se o intervalo escolhido tem **lacunas** no arquivo (p. ex. reinício de gravação ou limpeza no meio), o MPD DASH é dividido em vários `<Period>` — um por trecho contíguo. Os players (VLC, dashjs, Shaka) cruzam os limites de período sem configuração especial.

### EPG-aligned VOD

Se o fluxo está vinculado a uma fonte EPG (campos **EPG Source** e **EPG Channel** nos ajustes), o cliente pode solicitar o arquivo **por um instante contido em um evento 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)

O servidor localiza o evento EPG ativo no *epoch* dado e usa seus *start* e *duration* como bordas da janela VOD. Útil para catálogos: a UI sabe a hora do evento mas não precisa calcular bordas exatas.

Se o fluxo não está vinculado a EPG ou não há evento ativo — **404 ``VOD: EPG event not found``**. *t* e *d* são ignorados se há *epg*.

### Fluxos adaptativos

Os grupos adaptativos (ver [HLS Adaptive Multistream](ott.md#adaptive)) aceitam os mesmos parâmetros 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)

Na master playlist (HLS) só entram variantes com armazenamento DVR configurado. As sem DVR são puladas (no log aparece `VOD: variant N has no DVR`); a montagem segue com as demais.

Na variante DASH, cada qualidade vira um `<Representation>` distinto em `<Period>` comuns; o player troca de qualidade sem reabrir o manifesto.

### Comportamento do player

O VOD HLS / DASH do arquivo toca em players padrão: VLC, hls.js, dashjs, Shaka, ffmpeg. A busca na timeline funciona.

Se o player pede um segmento já apagado pela limpeza, o servidor retorna **404 para esse segmento** (não 500). VLC, hls.js, dashjs pulam o segmento e seguem no próximo.

Recursos adicionais:

- **Proteção de sessões ativas**: enquanto há sessão VOD aberta, a limpeza não apaga chunks na sua janela (ver abaixo).
- **Live-edge bridge**: se um cliente em sessão VOD solicitar um segmento além do limite direito da janela VOD — por exemplo, avança na timeline ao atingir o fim do arquivo — o servidor entrega automaticamente o segmento da memória live. Sem redirecionamentos e sem reautenticação.
- **Cache de playlist**: em requisições repetidas do mesmo VOD `index.m3u8` / `index.mpd`, o servidor retorna resposta idêntica byte a byte — sem reconstruir. Adequado para CDN à frente do PSS.

## Legendas no arquivo

Se o fluxo traz legendas (DVB Subtitling, Teletext ou WebVTT) e a opção **OTT WebVTT** está ativa, as legendas são arquivadas em paralelo aos chunks TS — em arquivos `.vtt` ao lado de `.ts`.

Em modo live, a master playlist contém `EXT-X-MEDIA:TYPE=SUBTITLES`; em modo VOD, o servidor retorna uma **playlist VOD de legendas** (com `ENDLIST`) e segmentos `.vtt` nas mesmas URLs.

Particularidades:

- **HLS**: o cabeçalho `X-TIMESTAMP-MAP` é preservado no início de cada `.vtt` (exigido pela spec HLS).
- **DASH**: o cabeçalho `X-TIMESTAMP-MAP` é removido em tempo real (ligado ao PCR absoluto, conflita com a âncora DASH; senão, VLC mostra legendas vazias).
- Em grupo adaptativo: se o sub-stream ativo não grava legendas, os segmentos VTT retornam 404. Na próxima variante, o player pode receber legendas de novo.

As legendas se desativam via **OTT WebVTT** no fluxo, ou não ativando HLS em modo *OTT/HLS*.

## Limpeza e retenção

PSS usa quatro estratégias de limpeza, executadas a cada tick da tarefa de limpeza (padrão a cada 10 seg):

1. **Rolling cleanup** (por fluxo): por fluxo, apagam-se chunks mais antigos que **Storage Hours**. Roda sempre, mesmo com disco semivazio.
2. **Size-based cleanup** (por armazenamento): quando **Used %** excede **Max Usage** continuamente por **Disk Pressure Grace** seg, os chunks mais antigos são cortados **proporcionalmente** entre fluxos vinculados. Por tick: **Disk Pressure Cut** seg de vídeo por fluxo. Nunca chunks mais novos que **Storage Min Hour**.
3. **Emergency disk-full cut**: se o espaço livre cai abaixo de **Disk Emergency Bytes**, a limpeza age agressivamente e pode apagar até chunks protegidos por sessão. A gravação para até o espaço livre voltar com histerese × 2.
4. **Orphan scan**: no disco podem permanecer arquivos não contabilizados no índice (após uma parada abrupta do PSS). O coletor percorre os subdiretórios dos fluxos e remove esses arquivos “esquecidos” — a primeira passagem pouco após o início do serviço, depois uma vez por hora e sempre que a pressão de disco for acionada. Como proteção contra uma corrida com a escrita, arquivos com menos de 60 s são ignorados.

**Nota.** As tarefas de limpeza rodam em segundo plano; o usuário normalmente não age. Se o arquivo cresce mais rápido do que é cortado, reduzir **Storage Hours** nos fluxos ou aumentar **Disk Pressure Cut**.

## Proteção de sessões VOD ativas

Ao abrir uma sessão VOD, em cada armazenamento envolvido registra-se um «slot de proteção» com a hora de início da janela. As limpezas **Rolling** e **size-based** não tocam chunks na janela da sessão aberta. O slot é liberado automaticamente ao fechar (FIN, timeout).

Isso significa:

- Se o cliente mantém a sessão VOD por muito tempo, pode buscar a qualquer instante na sua janela — os chunks não «somem sob ele».
- A limpeza por **Max Usage** pode não levar **Used %** ao limiar enquanto a sessão estiver ativa; ao cliente sair, a limpeza alcança.
- **Emergency disk-full cut** e **Storage Min Hour** contornam a proteção: se o disco está quase sem livre, os chunks são apagados e o cliente recebe 404 nos segmentos afetados (o player os pula).
- Após reiniciar o PSS, os slots de proteção somem — a limpeza retoma de imediato.

## Vários armazenamentos

Pode-se criar qualquer número de registros **DVR Storage** — um por diretório / disco. Os fluxos se vinculam a armazenamentos distintos de forma independente. A limpeza e limiares (**Max Usage**, **Disk Pressure**) operam por armazenamento.

Casos de uso:

- **Tiering por valor**: armazenamento SSD rápido para canais premium com grande profundidade, HDD capacitivo para o resto.
- **Disco dedicado ao arquivo**: para que a gravação DVR não concorra com o disco do sistema ou arquivos temporários.
- **Separação por projeto**: um disco para o lote nº 1, outro para o nº 2 — simplifica migração e auditoria.

Trocar a vinculação do fluxo (campo **Storage** em **Stream / OTT**) comuta a gravação em tempo real. Os arquivos antigos ficam intactos no disco anterior — podem ser apagados manualmente ou retomar a gravação revertendo o fluxo.

## Estado do armazenamento e monitoramento

A seção **Data / DVR Storage List** (e a API `GET /data/dvr-storage-list`) mostra por armazenamento:

- **State** — *Ready* / *Error* (mais o estado intermediário *Not Ready* em um armazenamento recém-adicionado).
- **Total / Free / Used Bytes** — espaço livre e ocupado no disco.
- **Used %** — porcentagem atual de uso.
- **Archived Bytes** — tamanho total dos chunks indexados de todos fluxos vinculados (sem orphans).
- **Pressure Since Sec** — momento (epoch) em que **Used %** primeiro excedeu **Max Usage** neste episódio; *0* significa «sem pressão».
- **Active Task** — a operação de manutenção em segundo plano em execução neste momento: *gc-orphans* (remoção de arquivos órfãos), *disk-pressure-trim* (corte sob pressão de disco) ou *none*, e há quantos segundos ela já está em execução. Operações de curta duração (< 2 s) não piscam na interface.
- **Last cleanup** — um resumo das últimas execuções de limpeza: há quanto tempo ocorreu a anterior recolha de ficheiros órfãos (e quantos foram eliminados) e o último corte sob pressão de disco (quanto espaço foi libertado).
- **Attached streams** — a lista dos fluxos associados; para cada um são exibidos o nome, o indicador de gravação em curso (*active*), a profundidade de arquivo configurada (*retention-hours*) e o preenchimento real (*archived-sec* e *archived-bytes*). A soma de *archived-bytes* de todos os fluxos é igual a **Archived Bytes** de todo o armazenamento.

Estados:

- *Ready* — o diretório está disponível, a gravação e a limpeza ocorrem normalmente.
- *Error* — o diretório de armazenamento está indisponível (desmontado, sem permissões, erro do sistema de arquivos) ou há espaço livre criticamente baixo no disco; a gravação é interrompida. A recuperação é automática — assim que o diretório fica novamente disponível e surge espaço livre suficiente.

Se o armazenamento entrou em *Error*, verifique se o diretório do arquivo está montado e se há espaço livre no disco — o PSS não sai sozinho desse estado até que o problema seja resolvido fisicamente.

Preenchimento do arquivo ao longo do tempo:

- No nível do stream (**Data / Stream**) está disponível a métrica **storage-gap-percent** — a proporção de lacunas de tempo no arquivo acumulado: *0 %* significa gravação contínua, valores mais altos significam que há descontinuidades no arquivo (reinícios da fonte, trechos cortados pela limpeza).
- O endpoint `GET /data/dvrstat` retorna um histograma do preenchimento do arquivo por intervalos de tempo, com a marcação de eventos de gravação (início/parada da fonte, mudança de **PMT**, comutações de embaralhamento, reconstrução do índice, execução de limpeza) e de atividade de legendas — para desenhar a linha do tempo do arquivo DVR na interface de administração.

## Proteção contra perda acidental

Várias operações do admin causam **perda do arquivo** ou **cessação da entrega VOD**. Antes de executá-las, a UI mostra confirmação modal:

- **Excluir DVR Storage** — todos os fluxos vinculados perdem acesso VOD; os arquivos ficam no disco mas são inacessíveis via PSS sem o registro.
- **Trocar o fluxo para outro armazenamento** — o VOD sobre o arquivo antigo deixa de funcionar.
- **Desvincular o fluxo do armazenamento** (Storage = 0) — mesmo efeito.
- **Reduzir Max Usage** — pode disparar a limpeza size-based e apagar chunks antigos.
- **Reduzir Storage Hours / Storage Min Hour** — pode tirar parte do arquivo do rolling-window.

Decisão deliberada do produto: a operação é possível mas com confirmação, e os arquivos apagados ficam no disco (restauráveis de backup). Colocar o arquivo em servidor de arquivos / RAID separado reduz muito o risco de perda irreversível.

## Limitações da versão atual

- Uma sessão VOD aberta pelo cliente **não acompanha** o live edge — se vieram chunks durante a sessão, o cliente deve repedir a playlist (comportamento padrão HLS / DASH).
- Atribuir um armazenamento por disco é o recomendado — vários registros com subdiretórios distintos disputam o espaço.
- Os segmentos são endereçados por hash (HLS sobre MPEG-TS) ou pelo modelo `$Number$.m4s` com um `init.mp4` comum (live DASH sobre CMAF) / por `<SegmentURL>` explícitas para `.m4s` (VOD DASH). Alterar o tamanho do chunk entre live e VOD não exige reabrir a URL.
- O orphan scanner roda por hora; para acelerar, reiniciar PSS.
