# Guia de Codificação de Vídeo em Transmissão

## 1. Visão geral

A codificação de vídeo em streaming elimina o ciclo tradicional de PNG durante a gravação de conjuntos de dados de vídeo. Em vez de:

1. Capturar quadro -> gravar PNG em disco -> (no final do episódio) ler PNGs -> codificar para MP4 -> excluir PNGs

Os quadros podem ser codificados em tempo real durante a captura:

1. Capturar quadro -> enfileirar para a thread do codificador -> codificar diretamente para MP4

Isso torna `save_episode()` quase instantâneo (o vídeo já está codificado quando o episódio termina) e elimina a espera bloqueante que ocorria anteriormente entre os episódios, especialmente com múltiplas câmeras em episódios longos.

## 2. Parâmetros de ajuste

| Parâmetro               | Flag de CLI                          | Tipo          | Padrão       | Descrição                                                       |
| ----------------------- | --------------------------------- | ------------- | ------------- | ----------------------------------------------------------------- |
| `streaming_encoding`    | `--dataset.streaming_encoding`    | `bool`        | `False`       | Ativar a codificação em tempo real durante a captura                          |
| `vcodec`                | `--dataset.rgb_encoder.vcodec`    | `str`         | `"libsvtav1"` | Codec de vídeo. `"auto"` detecta o melhor codificador de HW                     |
| `encoder_threads`       | `--dataset.encoder_threads`       | `int \| None` | `None` (automático) | Threads por instância do encoder. `None` deixará o vcoded decidir |
| `encoder_queue_maxsize` | `--dataset.encoder_queue_maxsize` | `int`         | `30`          | Quadros em buffer máximos por câmera (~1s a 30fps). Consome RAM       |

## 3. Considerações de desempenho

A codificação em streaming significa que a CPU está codificando o vídeo **durante** o loop de captura, e não depois. Isso cria um orçamento de CPU que deve ser compartilhado entre:

- **Loop de controle** (leitura das câmeras, controle do robô, gravação de dados não em vídeo)
- **Threads de codificação** (um pool por câmera)
- **Executar novamente a visualização** (se ativado)
- **Sistema operacional e outros processos**

### Impacto da resolução e do número de câmeras

| Configuração                     | Vazão (px/seg) | Carregamento de codificação de CPU | Observações                          |
| ------------------------- | ------------------- | ----------------- | ------------------------------ |
| 2camsx 640x480x3 @30fps   | 55M                 | Baixo               | Funciona na maioria dos sistemas          |
| 2camsx 1280x720x3 @30fps  | 165M                | Moderado          | Confortável em sistemas modernos  |
| 2camsx 1920x1080x3 @30fps | 373M                | Alto              | Exige um CPU de alto desempenho |

### `encoder_threads` Ajuste

Este parâmetro controla quantos threads cada instância do encoder usa internamente:

- **Valores mais altos** (por exemplo, 4-5): codificação mais rápida, mas usa mais núcleos de CPU por câmera. Bom para sistemas de alto desempenho com muitos núcleos.
- **Valores menores** (por exemplo, 1-2): Menos CPU por câmera, liberando núcleos para captura e visualização. Bom para imagens de baixa resolução e CPUs capazes.
- **`None` (padrão)**: Deixa o codec decidir. As informações disponíveis estão nos logs do codec.

### Backpressure e Descarte de Quadros

Cada câmera possui uma fila limitada (`encoder_queue_maxsize`, padrão 30 quadros). Quando o codificador não consegue acompanhar:

1. A fila fica cheia (consumindo RAM)
2. Novos quadros são **descartados** (não bloqueados) — o loop de captura continua ininterrupto
3. Um aviso é registrado: `"Encoder queue full for {camera}, dropped N frame(s)"`
4. No final do episódio, o total de quadros descartados por câmera é reportado

### Sintomas do Encoder ficando para trás

- **O sistema fica lento e congela**: todos os CPUs estão em 100%
- **Avisos de quadros descartados** no log ou menos quadros/FPS do que o esperado no conjunto de dados gravado
- **Movimento robótico irregular**: Se a CPU estiver severamente sobrecarregada, até o loop de captura pode ser afetado
- **Atraso acumulado de reexecução**: A visualização fica para trás em relação ao tempo real

## 4. Codificação com Aceleração de Hardware

### Quando usar

Use a codificação de HW quando:

- A CPU é o gargalo (quadros perdidos, robô travando, atraso no rerun)
- Você possui hardware compatível (GPU ou codificador dedicado)
- Você está gravando com alto throughput (alta resolução ou com muitas câmeras)

### Escolhendo um Codec

| Codec                 | Uso de CPU | Tamanho do Arquivo      | Qualidade | Observações                                                            |
| --------------------- | --------- | -------------- | ------- | ---------------------------------------------------------------- |
| `libsvtav1` (padrão) | Alto      | Menor       | Melhor    | Padrão. Melhor compressão, porém mais intensivo em CPU                 |
| `h264`                | Médio    | ~30-50% maior | Bom    | Software H.264. Menor uso de CPU                                        |
| Codificadores de HW           | Muito Baixo  | Maior        | Bom    | Realiza o offload para hardware dedicado. Ideal para sistemas com restrições de CPU |

### Codificadores de HW disponíveis

| Codificador             | Plataforma      | Hardware                                                                                         | Valor da CLI                                        |
| ------------------- | ------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
| `h264_videotoolbox` | macOS         | Apple Silicon / Intel                                                                            | `--dataset.rgb_encoder.vcodec=h264_videotoolbox` |
| `hevc_videotoolbox` | macOS         | Apple Silicon / Intel                                                                            | `--dataset.rgb_encoder.vcodec=hevc_videotoolbox` |
| `h264_nvenc`        | Linux/Windows | GPU da NVIDIA                                                                                       | `--dataset.rgb_encoder.vcodec=h264_nvenc`        |
| `hevc_nvenc`        | Linux/Windows | GPU da NVIDIA                                                                                       | `--dataset.rgb_encoder.vcodec=hevc_nvenc`        |
| `h264_vaapi`        | Linux         | GPU Intel/AMD                                                                                    | `--dataset.rgb_encoder.vcodec=h264_vaapi`        |
| `h264_qsv`          | Linux/Windows | Intel Quick Sync                                                                                 | `--dataset.rgb_encoder.vcodec=h264_qsv`          |
| `auto`              | Qualquer           | Verifica o sistema em busca de codificadores de HW disponíveis. Se nenhum codificador de HW for encontrado, usa `libsvtav1` como alternativa | `--dataset.rgb_encoder.vcodec=auto`              |

> [!NOTE]
> Para usar os codificadores acelerados por HW, você pode precisar atualizar os drivers da sua GPU.

> [!NOTE]
> `libsvtav1` é o padrão porque oferece o melhor desempenho de treinamento; outros vcodecs podem reduzir o uso de CPU e ser mais rápidos, mas geralmente produzem arquivos maiores e podem afetar o tempo de treinamento.

## 5. Solução de problemas

| Sintoma                                                            | Causa provável                                 | Corrigir                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Sistema congela ou movimento robótico irregular ou atraso na visualização do Rerun | CPU com falta de recursos (uso de carga de 100%)                | Feche outros aplicativos, reduza a taxa de codificação, diminua `encoder_threads`, use `h264`, use `display_data=False`. Se a CPU continuar em 100%, ela pode ser insuficiente para sua configuração; considere `--dataset.streaming_encoding=false` ou codificação por hardware (`--dataset.rgb_encoder.vcodec=auto`) |
| Avisos de "Encoder queue full" ou quadros descartados no dataset         | O Encoder não consegue acompanhar (estouro de fila)       | Se a CPU não estiver em 100%: aumente `encoder_threads`, aumente `encoder_queue_maxsize` ou use codificação de HW (`--dataset.rgb_encoder.vcodec=auto`).                                                                                                                                                    |
| Uso elevado de RAM                                                     | Fila preenchendo mais rápido do que a codificação           | `encoder_threads` muito baixo ou CPU insuficiente. Reduza `encoder_queue_maxsize` ou use codificação por HW                                                                                                                                                                                                 |
| Arquivos de vídeo grandes                                                  | Usando codificador de HW ou H.264                    | Compromisso esperado. Alterne para `libsvtav1` se a CPU permitir                                                                                                                                                                                                                                          |
| `save_episode()` ainda lento                                        | `streaming_encoding` é `False`              | Defina `--dataset.streaming_encoding=true`                                                                                                                                                                                                                                                          |
| Crash da thread do codificador                                               | Codec não disponível ou configurações inválidas      | Verifique se `vcodec` está instalado, tente `--dataset.rgb_encoder.vcodec=auto`                                                                                                                                                                                                                             |
| O conjunto de dados gravado está com quadros ausentes                                 | Fome de CPU/GPU ou picos ocasionais de carga | Se ~5% dos quadros estiverem faltando, é provável que seu sistema esteja sobrecarregado — siga as recomendações acima. Se menos quadros estiverem faltando (~2%), eles provavelmente são devidos a picos transitórios ocasionais de carga (frequentemente na inicialização) e podem ser considerados esperados.                                               |

## 6. Configurações recomendadas

Essas estimativas são conservadoras; recomendamos testá-las no seu ambiente — comece com uma carga baixa e aumente-a gradualmente.

### Sistemas de alto desempenho: 12+ núcleos modernos (24+ threads)

Um throughput entre ~250-500M px/sec deve ser confortável em CPU. Para resultados ainda melhores, tente a codificação em HW, se disponível.

```bash
# 3camsx 1280x720x3 @30fps: Defaults work well. Optionally increase encoder parallelism.
# 2camsx 1920x1080x3 @30fps: Defaults work well. Optionally increase encoder parallelism.
lerobot-record --dataset.encoder_threads=5 ...

# 3camsx 1920x1080x3 @30fps: Might require some tuning.
```

### Sistemas de faixa intermediária: 8+ núcleos modernos (16+ threads) ou Apple Silicon

Um throughput de ~80-300M px/sec deve ser possível em CPU.

```bash
# 3camsx 640x480x3 @30fps: Defaults work well. Optionally decrease encoder parallelism.
# 2camsx 1280x720x3 @30fps: Defaults work well. Optionally decrease encoder parallelism.
lerobot-record --dataset.encoder_threads=2 ...

# 2camsx 1920x1080x3 @30fps: Might require some tuning.
```

### Sistemas de Recursos Limitados: 4+ núcleos modernos (8+ threads) ou Raspberry Pi 5

Em sistemas muito restritos, a codificação em streaming pode competir excessivamente com o loop de captura. Desativá-la faz com que o sistema volte para a abordagem baseada em PNG, na qual a codificação ocorre entre episódios (bloqueante, mas não interfere na captura). Alternativamente, grave com uma taxa de transferência menor para reduzir a carga tanto da captura quanto da codificação. Considere também alterar o codec para `h264` e usar codificação em lote.

```bash
# 2camsx 640x480x3 @30fps: Requires some tuning.

# Use H.264, disable streaming, consider batching encoding
lerobot-record --dataset.rgb_encoder.vcodec=h264 --dataset.streaming_encoding=false ...
```

## 7. Nota final

O desempenho depende, em última análise, da sua configuração exata — quadros por segundo, resolução, núcleos e carga da CPU, memória disponível, duração do episódio e o codificador escolhido. Sempre teste com a sua carga de trabalho alvo, tenha em mente as capacidades da sua CPU & do sistema e ajuste `encoder_threads`, `encoder_queue_maxsize` e `vcodec` de forma razoável. Dito isso, uma configuração prática comum (para muitas aplicações) é três câmeras em 640×480x3 @30fps; isso geralmente funciona bem com as configurações padrão de codificação de vídeo em streaming em sistemas modernos. Sempre verifique se o seu conjunto de dados gravado está íntegro comparando a duração do vídeo com a duração do episódio da CLI e confirmando que a contagem de linhas é igual a FPS × duração da CLI.

