LeRobot documentation
Параметры кодирования видео
Параметры кодирования видео
Когда включено хранение видео, LeRobot сохраняет каждый поток камеры в виде файла MP4, а не одного файла изображения на каждый шаг времени. Видеокодирование сжимает данные во времени, что обычно уменьшает размер датасета и нагрузку на I/O по сравнению с набором PNG, при этом сохраняя формат MP4 — понятный любому плееру и загрузчику.
Кодирование кадров в MP4 представляет собой полный конвейер FFmpeg: выбор кодека, пиксельного формата, GOP/ключевых кадров, баланса между качеством и скоростью, а также дополнительные флаги кодека. Большинство этих параметров настраиваются пользователем через rgb_encoder, вложенный RGBEncoderConfig (lerobot.configs.video.RGBEncoderConfig), передаваемый через PyAV.
Эти параметры можно задать из командной строки с помощью --dataset.rgb_encoder.<field> (например, при использовании lerobot-record или lerobot-rollout). Этот блок параметров применяется ко всем потокам видео с камер в данном запуске.
Для того чтобы
rgb_encoderимел какой-либо эффект, хранилище видео должно быть включено —use_videos=Trueв Python API или--dataset.video=trueв CLI (значение по умолчанию при записи). Если видео выключено, входные данные остаются в виде изображений, аrgb_encoderигнорируется.
Подробнее о том, когда кадры записываются, а когда кодируются (потоковая передача или после эпизода), о очередях и других параметрах верхнего уровня --dataset.*, см. Потоковое кодирование видео. Для сравнения параметров кодирования и экспериментов см. Space video-benchmark.
Пример
lerobot-record \
--robot.type=so100_follower \
--robot.port=/dev/tty.usbmodem58760431541 \
--robot.cameras="{laptop: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--robot.id=black \
--teleop.type=so100_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=blue \
--dataset.repo_id=<my_username>/<my_dataset_name> \
--dataset.num_episodes=2 \
--dataset.single_task="Grab the cube" \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2 \
--dataset.rgb_encoder.vcodec=h264 \
--dataset.rgb_encoder.preset=fast \
--dataset.rgb_encoder.extra_options='{"tune": "film", "profile:v": "high", "bf": 2}' \
--display_data=trueПараметры настройки
Значения по умолчанию подобраны так, чтобы обеспечить баланс между коэффициентом сжатия, визуальным качеством и скоростью декодирования/перемотки для типичных наборов данных робототехники. Их изменение может повлиять как на запись (нагрузка на CPU, потеря кадров), так и на обучение (производительность декодирования, качество изображений).
Переопределяйте эти параметры только при наличии конкретной причины и измеряйте их влияние на ваш конвейер перед тем, как полагаться на новые настройки.
Все флаги ниже имеют префикс --dataset.rgb_encoder. в командной строке.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
vcodec | str | "libsvtav1" | Название кодека видео. "auto" выбирает первый доступный аппаратный энкодер из фиксированного списка предпочтений, при этом в качестве резервного варианта используется libsvtav1. |
pix_fmt | str | "yuv420p" | Формат пикселей на выходе. Должен поддерживаться выбранным кодеком в вашей сборке FFmpeg. |
g | int | 2 | Размер GOP — ключевой кадр каждые g кадров. Передаётся как опция FFmpeg g. |
crf | int или float | 30 | Абстрактное значение качества, отображаемое для каждого кодека (см. соответствие). Чем ниже значение, тем выше качество и больше размер выходных данных, если отображение монотонно. |
preset | int или str | 12 * | Пресет скорости кодирования; значение зависит от кодека. * Если параметр не задан и vcodec=libsvtav1, LeRobot по умолчанию использует 12. |
fast_decode | int | 0 | libsvtav1: 0–2, передаётся через svtav1-params. h264 / hevc (программное кодирование): если >0, устанавливает tune=fastdecode. Другие кодеки: обычно не используется. |
video_backend | str | "pyav" | В настоящее время для кодирования видео реализован только "pyav". |
extra_options | dict | {} | Дополнительные параметры FFmpeg или кодека, объединяемые после структурированных полей, перечисленных выше. Не могут переопределять ключи, уже установленные этими полями. |
Потоки глубины
Карты глубины (Intel RealSense, Reachy 2) хранятся как отдельные видеопотоки наряду с RGB-потоками. Сырые данные глубины (uint16 в миллиметрах или float32 в метрах) не могут быть сохранены 8-битным кодеком, поэтому LeRobot квантует каждую карту в 12-битный код ([0, 4095]) — по умолчанию логарифмически, чтобы соответствовать профилю ошибки 1/depth датчиков глубины, — а затем упаковывает его в формат пикселей с высокой глубиной бит (gray12le) и кодирует 12-битным кодеком.
float32 м →
depth_max] → Квантование 12-битные коды 0–4095
log (по умолчанию) или linear → Упаковка в gray12le
плоскость → Кодирование HEVC
Main 12
поток →
Настройте конвейер глубины с помощью параллельного блока depth_encoder (DepthEncoderConfig). Он разделяет все поля RGBEncoderConfig (vcodec, pix_fmt, crf, …) и добавляет четыре параметра квантизатора, которые задаются через --dataset.depth_encoder.<field>:
lerobot-record \
... \
--dataset.depth_encoder.vcodec=hevc \
--dataset.depth_encoder.depth_min=0.05 \
--dataset.depth_encoder.depth_max=5.0 \
--dataset.depth_encoder.use_log=true| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
vcodec | str | "hevc" | HEVC Main 12 (кодек с поддержкой 12 бит, совместимый с MP4). |
extra_options | dict | {"x265-params": "lossless=1"} | Глубина по умолчанию — без потерь (точное восстановление); crf игнорируется. Передайте extra_options={} и задайте crf, чтобы получить более компактный поток с потерями. |
pix_fmt | str | "gray12le" | Одноканальный 12-битный формат пикселей, используемый для хранения квантованных кодов. |
depth_min | float | 0.01 | Глубина в метрах, отображённая в квантовое значение 0. Значения ниже обрезаются при декодировании. |
depth_max | float | 10.0 | Глубина в метрах, отображённая в квантовое значение 4095. Значения выше обрезаются при декодировании. |
shift | float | 3.5 | Смещение перед логарифмом (в метрах), используемое в логарифмической квантизации для численной стабильности вблизи нуля. Должно удовлетворять условию depth_min + shift > 0. |
use_log | bool | True | Если true, квантование выполняется в логарифмическом пространстве (рекомендуется для типичных датчиков глубины). Установите false для равномерного/линейного квантования. |
depth_min,depth_maxиshiftвсегда интерпретируются в метрах, независимо от единицы измерения входной глубины. Входные данные определяются автоматически: целочисленные массивы (например,uint16в миллиметрах, полученные напрямую с RealSense) считаются миллиметрами, а массивы с плавающей точкой — метрами. Выберитеdepth_min/depth_maxтак, чтобы они охватывали фактический рабочий диапазон вашего датчика — значения вне этого диапазона насыщаются, что может привести к потере деталей на границах.
Глубинные признаки помечаются как "is_depth_map": true в meta/info.json, а настройки их квантизатора (video.depth_min, video.depth_max, video.shift, video.use_log) сохраняются — именно это позволяет при загрузке деквантовать глубину обратно в физические единицы.
Выходная единица при загрузке
depth_encoder — это параметр, относящийся к моменту записи. Единица, в которую карты глубины деквантуются при загрузке (например, во время обучения), задаётся отдельно флагом времени чтения --dataset.depth_output_unit:
lerobot-train \
--dataset.repo_id=<my_username>/<my_dataset_name> \
--dataset.depth_output_unit=m \
--policy.type=act| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
depth_output_unit | str | "mm" | Карты глубины физических единиц декуантизуются при загрузке в: "mm" (миллиметры) или "m" (метры). |
Это исключительно выбор способа отображения на этапе декодирования — он не изменяет сохранённое видео или его метаданные, поэтому один и тот же датасет можно читать как
mmилиmбез перекодирования. На датасеты без камер глубины это не влияет.
Сохранение в метаданных набора данных
После кодирования первого эпизода видеопотока конфигурация кодировщика сохраняется в метаданных набора данных (meta/info.json) для каждого видеособенности, наряду со значениями, полученными из самого файла. Для видеособенности observation.images.<camera> структура в info.json выглядит следующим образом:
{
"features": {
"observation.images.laptop": {
"dtype": "video",
"shape": [480, 640, 3],
"info": {
"video.height": 480,
"video.width": 640,
"video.codec": "h264",
"video.pix_fmt": "yuv420p",
"video.fps": 30,
"video.channels": 3,
"is_depth_map": false,
"video.g": 2,
"video.crf": 30,
"video.preset": "fast",
"video.fast_decode": 0,
"video.video_backend": "pyav",
"video.extra_options": { "tune": "film", "profile:v": "high", "bf": 2 }
}
}
}
}Два источника формируют блок info:
| Источник | Откуда он берётся | Поля |
|---|---|---|
| Полученные из потока | Чтение обратно из закодированного MP4 с помощью PyAV. | video.height, video.width, video.codec, video.pix_fmt, video.fps, video.channels, is_depth_map, audio.* |
| Полученные из энкодера | Взято из RGBEncoderConfig / DepthEncoderConfig. | video.g, video.crf, video.preset, video.fast_decode, video.video_backend, video.extra_options |
Этот блок заполняется один раз, на основе первого эпизода. Предполагается, что каждый эпизод в наборе данных был закодирован с помощью одного и того же
rgb_encoder. Изменение настроек кодировщика в процессе записи не поддерживается — в файлеinfo.jsonбудут отражены только параметры, использованные для первого эпизода.
Объединение наборов данных
При агрегировании датасетов с помощью merge_datasets видефайлы объединяются без перекодирования, а поля энкодера в info.json объединяются по ключам:
| Правило слияния | Поля | Поведение |
|---|---|---|
| Должно совпадать | video.codec, video.pix_fmt, video.height, video.width, video.fps | Поля, полученные из потока, должны совпадать между источниками, иначе concat-демуксер FFmpeg завершится с ошибкой. |
| Слабое слияние | video.g, video.crf, video.preset, video.fast_decode, video.extra_options | Поля для настройки энкодера. Если все источники согласны, значение сохраняется; в противном случае оно устанавливается в null (или {} для video.extra_options), и в журнал записывается предупреждение. |