LeRobot documentation
Parâmetros de codificação de vídeo
Parâmetros de codificação de vídeo
Quando o armazenamento em vídeo está habilitado, o LeRobot armazena cada fluxo de câmera como um arquivo MP4 em vez de salvar um arquivo de imagem por passo de tempo. A codificação de vídeo comprime ao longo do tempo, o que geralmente reduz o tamanho do conjunto de dados e a entrada/saída em comparação com uma pilha de PNG, mantendo o MP4 — um formato que todos os players e loaders entendem.
Codificar frames em um MP4 é um pipeline completo do FFmpeg: escolha do codificador, formato de pixel, GOP/keyframes, qualidade versus velocidade e flags extras opcionais do codificador. A maioria desses parâmetros é ajustável pelo usuário por meio de rgb_encoder, um RGBEncoderConfig aninhado (lerobot.configs.video.RGBEncoderConfig) passado por meio do PyAV.
Você pode definir esses parâmetros pela CLI com --dataset.rgb_encoder.<field> (por exemplo, com lerobot-record ou lerobot-rollout). O mesmo bloco se aplica a todos os fluxos de vídeo de câmera naquela execução.
O armazenamento de vídeo deve estar ativado para que
rgb_encodertenha algum efeito —use_videos=Truenas APIs Python, ou--dataset.video=truena CLI (o padrão de gravação). Com o vídeo desativado, as entradas permanecem como imagens ergb_encoderé ignorado.
Para detalhes sobre quando os frames são gravados versus codificados (streaming versus pós-episódio), filas e outros switches de nível superior --dataset.*, consulte Streaming Video Encoding. Para uma comparação de parâmetros de codificação e experimentos, consulte o video-benchmark Space.
Exemplo
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=trueParâmetros de ajuste
Os padrões são ajustados para equilibrar taxa de compressão, qualidade visual e velocidade de decodificação/seek para conjuntos de dados de robótica típicos. Alterá-los pode afetar tanto a gravação (carga de CPU, quedas de quadros) quanto o treinamento (vazão de decodificação, qualidade das imagens).
Sobrescreva esses parâmetros apenas se tiver um motivo específico para isso e meça o impacto no seu pipeline antes de confiar nas novas configurações.
Todas as flags abaixo são prefixadas com --dataset.rgb_encoder. na CLI.
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
vcodec | str | "libsvtav1" | Nome do codec de vídeo. "auto" seleciona o primeiro codificador de hardware disponível a partir de uma lista de preferências fixa, com fallback para libsvtav1. |
pix_fmt | str | "yuv420p" | Formato de pixel de saída. Deve ser suportado pelo codec escolhido na sua compilação do FFmpeg. |
g | int | 2 | Tamanho do GOP — uma keyframe a cada g quadros. Emitido como opção do FFmpeg g. |
crf | int ou float | 30 | Valor de qualidade abstrato, mapeado por codec (veja o mapeamento). Menor → maior qualidade / saída maior onde o mapeamento é monotônico. |
preset | int ou str | 12 * | Preset de velocidade do codificador; o significado depende do codec. * Quando não definido e vcodec=libsvtav1, o LeRobot usa 12 por padrão. |
fast_decode | int | 0 | libsvtav1: 0–2, passado via svtav1-params. h264 / hevc (software): se >0, define tune=fastdecode. Outros codecs: geralmente não utilizado. |
video_backend | str | "pyav" | Atualmente, apenas "pyav" está implementado para codificação de vídeo. |
extra_options | dict | {} | Opções específicas do FFmpeg ou do codec mescladas após os campos estruturados acima. Não é possível sobrescrever chaves já definidas por esses campos. |
Streams de profundidade
Mapas de profundidade (Intel RealSense, Reachy 2) são armazenados como seus próprios fluxos de vídeo ao lado dos fluxos RGB. A profundidade bruta (uint16 em milímetros ou float32 em metros) não sobrevive a um codec de 8 bits, portanto o LeRobot quantiza cada mapa para um código de 12 bits ([0, 4095]) — logaritmicamente por padrão, para corresponder ao perfil de erro 1/depth dos sensores de profundidade — e, em seguida, o empacota em um formato de pixel de alta profundidade de bits (gray12le) e o codifica com um codec de 12 bits.
float32 m →
depth_max] → Quantizar códigos de 12 bits 0–4095
log (padrão) ou linear → Empacotar em plano gray12le
→ Codificar HEVC
Main 12
→
Configure o pipeline de profundidade por meio de um bloco depth_encoder paralelo (DepthEncoderConfig). Ele compartilha todos os campos de RGBEncoderConfig (vcodec, pix_fmt, crf, …) e adiciona quatro parâmetros de quantizador, definidos via --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| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
vcodec | str | "hevc" | HEVC Main 12 (um codec compatível com 12 bits, compatível com MP4). |
extra_options | dict | {"x265-params": "lossless=1"} | A profundidade padrão é sem perdas (ida e volta exata); crf é ignorado. Passe extra_options={} e defina crf para um stream com perdas menor. |
pix_fmt | str | "gray12le" | Formato de pixel de 12 bits em canal único usado para transportar os códigos quantizados. |
depth_min | float | 0.01 | Profundidade em metros mapeada para o quântico 0. Os valores abaixo são limitados na decodificação. |
depth_max | float | 10.0 | Profundidade em metros mapeada para quântico 4095. Valores acima são limitados na decodificação. |
shift | float | 3.5 | Deslocamento pré-log (em metros) usado na quantização logarítmica para estabilidade numérica perto de zero. Deve satisfazer depth_min + shift > 0. |
use_log | bool | True | Se true, quantiza no espaço logarítmico (recomendado para sensores de profundidade típicos). Defina como false para quantização uniforme/linear. |
depth_min,depth_maxeshiftsão sempre interpretados em metros, independentemente da unidade da profundidade de entrada. As entradas são detectadas automaticamente: arrays inteiros (por exemplo,uint16em milímetros direto de um RealSense) são tratados como milímetros, e arrays de ponto flutuante como metros. Escolhadepth_min/depth_maxpara delimitar a faixa de trabalho real do seu sensor — quanta fora dessa faixa saturam, o que pode comprimir detalhes nas bordas.
Os recursos de profundidade são marcados com "is_depth_map": true em meta/info.json, e as configurações do quantizador deles (video.depth_min, video.depth_max, video.shift, video.use_log) são persistidas — o que permite que a profundidade seja desquantizada de volta para unidades físicas no carregamento.
Unidade de saída no momento do carregamento
depth_encoder é uma preocupação de tempo de gravação. A unidade para a qual os mapas de profundidade são desquantizados no carregamento (por exemplo, durante o treinamento) é definida separadamente pela flag de tempo de leitura --dataset.depth_output_unit:
lerobot-train \
--dataset.repo_id=<my_username>/<my_dataset_name> \
--dataset.depth_output_unit=m \
--policy.type=act| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
depth_output_unit | str | "mm" | Os mapas de profundidade de unidades físicas são desquantizados para, ao carregar: "mm" (milímetros) ou "m" (metros). |
Essa é uma escolha de apresentação apenas no momento da decodificação — ela não altera o vídeo armazenado nem seus metadados, de modo que o mesmo conjunto de dados pode ser lido como
mmoumsem re-codificação. Isso não afeta conjuntos de dados sem câmeras de profundidade.
Persistência nos metadados do conjunto de dados
Após o primeiro episódio de um fluxo de vídeo ser codificado, a configuração do codificador é persistida nos metadados do conjunto de dados (meta/info.json) sob cada recurso de vídeo, junto com os valores obtidos do próprio arquivo. Para um recurso de vídeo observation.images.<camera>, o layout em 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 }
}
}
}
}Duas fontes contribuem para o bloco info:
| Fonte | De onde vem | Campos |
|---|---|---|
| Derivado de stream | Leia de volta do MP4 codificado com PyAV. | video.height, video.width, video.codec, video.pix_fmt, video.fps, video.channels, is_depth_map, audio.* |
| Derivado do codificador | Retirado de RGBEncoderConfig / DepthEncoderConfig. | video.g, video.crf, video.preset, video.fast_decode, video.video_backend, video.extra_options |
Este bloco é preenchido uma única vez, a partir do primeiro episódio. Ele pressupõe que todos os episódios no conjunto de dados foram codificados com o mesmo
rgb_encoder. Alterar as configurações do codificador no meio de uma gravação não é suportado — oinfo.jsonrefletirá apenas os parâmetros usados para o primeiro episódio.
Mesclando conjuntos de dados
Ao agregar conjuntos de dados com merge_datasets, os arquivos de vídeo são concatenados como estão (sem re-codificação) e os campos do codificador em info.json são mesclados por chave:
| Regra de mesclagem | Campos | Comportamento |
|---|---|---|
| Deve corresponder | video.codec, video.pix_fmt, video.height, video.width, video.fps | Os campos derivados do stream devem corresponder entre as fontes; caso contrário, o demuxer concat do FFmpeg falha. |
| Mesclados de forma frouxa | video.g, video.crf, video.preset, video.fast_decode, video.extra_options | Campos de ajuste do codificador. Se todas as fontes concordarem, o valor é mantido; caso contrário, ele é definido como null (ou {} para video.extra_options) e um aviso é registrado. |