# Руководство по потоковому кодированию видео

## 1. Обзор

Потоковое кодирование видео устраняет традиционный цикл обработки PNG при записи набора данных видео. Вместо:

1. Захват кадра -> запись PNG на диск -> (в конце эпизода) чтение PNG -> кодирование в MP4 -> удаление PNG

Кадров можно кодировать в реальном времени во время захвата:

1. Захват кадра -> очередь в поток кодировщика -> кодирование непосредственно в MP4

Благодаря этому `save_episode()` выполняется практически мгновенно (видео уже закодировано к моменту завершения эпизода), а блокирующая пауза, которая ранее возникала между эпизодами, особенно при использовании нескольких камер в длинных эпизодах, устраняется.

## 2. Параметры настройки

| Параметр               | Флаг CLI                          | Тип          | По умолчанию       | Описание                                                       |
| ----------------------- | --------------------------------- | ------------- | ------------- | ----------------------------------------------------------------- |
| `streaming_encoding`    | `--dataset.streaming_encoding`    | `bool`        | `False`       | Включить кодирование в реальном времени во время захвата                          |
| `vcodec`                | `--dataset.rgb_encoder.vcodec`    | `str`         | `"libsvtav1"` | Видеокодек. `"auto"` определяет лучший аппаратный энкодер                     |
| `encoder_threads`       | `--dataset.encoder_threads`       | `int \| None` | `None` (авто) | Потоков на экземпляр энкодера. `None` оставит решение за vcoded |
| `encoder_queue_maxsize` | `--dataset.encoder_queue_maxsize` | `int`         | `30`          | Максимальное количество буферизованных кадров на камеру (~1 с при 30 кадрах/с). Потребляет оперативную память       |

## 3. Вопросы производительности

Потоковое кодирование означает, что CPU кодирует видео **во время** цикла захвата, а не после него. Это создаёт бюджет CPU, который необходимо распределять между:

- **Цикл управления** (чтение данных с камер, управление роботом, запись данных, не являющихся видео)
- **Потоки кодирования** (один пул на камеру)
- **Повторить визуализацию** (если включено)
- **ОС и другие процессы**

### Влияние разрешения и количества камер

| Настройка                     | Пропускная способность (px/сек) | Загрузка кодирования на CPU | Примечания                          |
| ------------------------- | ------------------- | ----------------- | ------------------------------ |
| 2camsx 640x480x3 @30fps   | 55M                 | Низкий               | Работает на большинстве систем          |
| 2camsx 1280x720x3 @30fps  | 165M                | Умеренный          | Комфортно на современных системах  |
| 2camsx 1920x1080x3 @30fps | 373M                | Высокий              | Требуется мощный высокопроизводительный процессор |

### Настройка `encoder_threads`

Этот параметр определяет, сколько потоков использует каждый экземпляр кодировщика внутри:

- **Более высокие значения** (например, 4–5): более быстрое кодирование, но используется больше ядер CPU на камеру. Подходит для мощных систем с большим количеством ядер.
- **Меньшие значения** (например, 1–2): меньше CPU на камеру, что освобождает ядра для захвата и визуализации. Подходит для изображений с низким разрешением и производительных CPU.
- **`None` (по умолчанию)**: позволяет кодексу принимать решение. Информация доступна в журналах кодека.

### Backpressure и отбрасывание кадров

Каждая камера имеет ограниченную очередь (`encoder_queue_maxsize`, по умолчанию 30 кадров). Если кодировщик не успевает обрабатывать данные:

1. Очередь заполняется (расходует оперативную память)
2. Новые кадры **отбрасываются** (не блокируются) — цикл захвата продолжается без прерываний
3. В журнал выводится предупреждение: `"Encoder queue full for {camera}, dropped N frame(s)"`
4. По завершении эпизода отчитывается общее количество потерянных кадров для каждой камеры

### Симптомы отставания кодировщика

- **Система работает с задержками и зависает**: все процессоры загружены на 100%
- Предупреждения **о пропущенных кадрах** в журнале или более низкое значение кадров/ФПС, чем ожидалось, в записанном наборе данных
- **Рывки в движении робота**: при сильной перегрузке ЦП может пострадать даже цикл захвата
- **Накопленная задержка повторного запуска**: визуализация отстаёт от реального времени

## 4. Аппаратно-ускоренное кодирование

### Когда использовать

Используйте аппаратное кодирование, когда:

- CPU является узким местом (потеря кадров, рывки робота, задержка в Rerun)
- У вас есть совместимое оборудование (GPU или выделенный энкодер)
- Вы записываете данные с высокой пропускной способностью (высокое разрешение или большое количество камер)

### Выбор кодека

| Кодировщик                 | Использование CPU | Размер файла      | Качество | Примечания                                                            |
| --------------------- | --------- | -------------- | ------- | ---------------------------------------------------------------- |
| `libsvtav1` (по умолчанию) | Высокий      | Минимальный       | Лучший    | По умолчанию. Лучшее сжатие, но максимальная нагрузка на CPU                 |
| `h264`                | Средний    | на ~30-50% больше | Хорошо    | Программный H.264. Меньшая нагрузка на CPU                                        |
| Аппаратные кодировщики           | Очень низкий  | Самые большие        | Хорошо    | Переносит данные на выделенное оборудование. Лучше всего подходит для систем с ограниченными ресурсами CPU |

### Доступные аппаратные кодировщики

| Кодер             | Платформа      | Аппаратное обеспечение                                                                                         | Значение 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 | NVIDIA GPU                                                                                       | `--dataset.rgb_encoder.vcodec=h264_nvenc`        |
| `hevc_nvenc`        | Linux/Windows | NVIDIA GPU                                                                                       | `--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`              | Любой           | Определяет доступные аппаратные энкодеры в системе. Если аппаратный энкодер не найден, используется `libsvtav1` | `--dataset.rgb_encoder.vcodec=auto`              |

> [!NOTE]
> Для использования аппаратно-ускоренных кодировщиков может потребоваться обновление драйверов GPU.

> [!NOTE]
> `libsvtav1` используется по умолчанию, так как обеспечивает наилучшую производительность обучения; другие vcodecs могут снижать нагрузку на CPU и работать быстрее, но обычно создают файлы большего размера и могут влиять на время обучения.

## 5. Устранение неполадок

| Симптом                                                            | Возможная причина                                 | Исправление                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Система зависает, движение робота рывками или задержки в визуализации Rerun | CPU голод (100% загрузка)                | Закройте другие приложения, снизьте пропускную способность кодирования, уменьшите значение `encoder_threads`, используйте `h264`, установите `display_data=False`. Если загрузка CPU по-прежнему составляет 100%, возможно, его мощности недостаточно для вашей конфигурации. Рассмотрите вариант с `--dataset.streaming_encoding=false` или аппаратным кодированием (`--dataset.rgb_encoder.vcodec=auto`). |
| Предупреждения «Encoder queue full» или потеря кадров в наборе данных         | Кодировщик не успевает (переполнение очереди)       | Если загрузка CPU не составляет 100%: увеличьте `encoder_threads`, увеличьте `encoder_queue_maxsize` или используйте аппаратное кодирование (`--dataset.rgb_encoder.vcodec=auto`).                                                                                                                                                    |
| Высокое потребление ОЗУ                                                     | Очередь заполняется быстрее, чем идёт кодирование           | Слишком низкое значение `encoder_threads` или недостаточная мощность CPU. Уменьшите `encoder_queue_maxsize` или используйте аппаратное кодирование                                                                                                                                                                                                 |
| Большие видеофайлы                                                  | Использование аппаратного кодировщика или H.264                    | Ожидаемый компромисс. Переключитесь на `libsvtav1`, если CPU позволяет                                                                                                                                                                                                                                          |
| `save_episode()` всё ещё медленный                                        | `streaming_encoding` равно `False`              | Установите `--dataset.streaming_encoding=true`                                                                                                                                                                                                                                                          |
| Сбой потока кодировщика                                               | Кодировщик недоступен или параметры недействительны      | Проверьте, что `vcodec` установлен, попробуйте `--dataset.rgb_encoder.vcodec=auto`                                                                                                                                                                                                                             |
| В записанном наборе данных отсутствуют кадры                                 | Голодание CPU/GPU или периодические всплески нагрузки | Если пропущено ~5% кадров, система, вероятно, перегружена — следуйте рекомендациям выше. Если пропущено меньше кадров (~2%), они, скорее всего, вызваны периодическими кратковременными пиками нагрузки (часто при запуске) и могут считаться ожидаемыми.                                               |

## 6. Рекомендуемые конфигурации

Эти оценки являются консервативными; мы рекомендуем протестировать их на вашей конфигурации — начните с низкой нагрузки и постепенно увеличивайте её.

### Высокопроизводительные системы: современные 12+ ядер (24+ потоков)

Пропускная способность в диапазоне ~250–500 млн пикс/сек должна быть комфортной для CPU. Для еще лучших результатов попробуйте аппаратное кодирование, если оно доступно.

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

### Системы среднего уровня: современные 8+ ядер (16+ потоков) или Apple Silicon

Пропускная способность в диапазоне ~80–300 млн пикс/сек должна быть достижима на 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.
```

### Системы с ограниченными ресурсами: современные 4+ ядра (8+ потоков) или Raspberry Pi 5

На системах с очень ограниченными ресурсами потоковое кодирование может чрезмерно конкурировать с циклом захвата. Отключение этой функции возвращает систему к основанному на PNG подходу, при котором кодирование выполняется между эпизодами (блокирующее, но не мешает захвату). Альтернативный вариант — записывать с меньшей пропускной способностью, чтобы снизить нагрузку как на захват, так и на кодирование. Также стоит рассмотреть смену кодека на `h264` и использование пакетного кодирования.

```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. Заключительное замечание

Производительность в конечном счёте зависит от вашей конкретной конфигурации — кадров в секунду, разрешения, количества ядер и загрузки CPU, доступной памяти, длительности эпизода и выбранного вами кодировщика. Всегда тестируйте систему с целевой нагрузкой, учитывайте возможности вашего CPU & системы и разумно настраивайте параметры `encoder_threads`, `encoder_queue_maxsize` и `vcodec`. Тем не менее, распространённая практическая конфигурация (для многих приложений) — это три камеры с разрешением 640×480x3 @30fps; как правило, она стабильно работает с настройками потокового видеокодирования по умолчанию на современных системах. Всегда проверяйте целостность записанного набора данных, сравнивая длительность видео с длительностью эпизода в CLI и убеждаясь, что количество строк равно FPS × длительности в CLI.

