LeRobot documentation
비디오 인코딩 매개변수
비디오 인코딩 매개변수
비디오 저장이 활성화되면 LeRobot은 타임스텝마다 하나의 이미지 파일을 저장하는 대신 각 카메라 스트림을 MP4 파일로 저장합니다. 비디오 인코딩은 시간 축을 따라 압축을 수행하므로, PNG 파일 묶음에 비해 데이터셋 크기와 I/O를 줄이는 경우가 많습니다. 모든 플레이어와 로더가 이해하는 MP4 형식을 유지하면서요.
MP4로 프레임을 인코딩하는 것은 완전한 FFmpeg 파이프라인입니다. 인코더 선택, 픽셀 포맷, GOP/키프레임, 품질 대 속도 트레이드오프, 선택적 추가 인코더 플래그 등이 포함됩니다. 이러한 설정의 대부분은 PyAV를 통해 전달되는 rgb_encoder의 중첩된 RGBEncoderConfig (lerobot.configs.video.RGBEncoderConfig)를 통해 사용자가 조정할 수 있습니다.
이 매개변수는 --dataset.rgb_encoder.<field>를 사용하여 CLI에서 설정할 수 있습니다(예: lerobot-record 또는 lerobot-rollout 사용). 동일한 블록은 해당 실행의 모든 카메라 비디오 스트림에 적용됩니다.
rgb_encoder가 효과를 내려면 비디오 저장이 켜져 있어야 합니다 — Python API에서는use_videos=True, CLI에서는--dataset.video=true(기록 기본값)를 사용하세요. 비디오가 꺼져 있으면 입력은 이미지로 유지되고rgb_encoder는 무시됩니다.
언제 프레임이 기록되는지 인코딩되는지(스트리밍 vs. 에피소드 후)에 대한 세부 사항, 큐, 그리고 기타 최상위 --dataset.* 스위치는 Streaming Video Encoding을 참고하세요. 인코딩 파라미터 비교 및 실험은 video-benchmark Space를 참고하세요.
예시
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 부하, 프레임 드롭)와 학습(디코딩 처리량, 이미지 품질) 모두에 영향을 미칠 수 있습니다.
이 매개변수들은 특정 이유가 있을 때만 재정의하고, 새로운 설정에 의존하기 전에 파이프라인에 미치는 영향을 측정하세요.
아래의 모든 플래그는 CLI에서 --dataset.rgb_encoder. 접두사가 붙습니다.
| 매개변수 | 유형 | 기본값 | 설명 |
|---|---|---|---|
vcodec | str | "libsvtav1" | 비디오 코덱 이름. "auto"는 고정된 우선순위 목록에서 첫 번째 사용 가능한 하드웨어 인코더를 선택하며, 사용할 수 없으면 libsvtav1로 대체됩니다. |
pix_fmt | str | "yuv420p" | 출력 픽셀 형식. FFmpeg 빌드에서 선택한 코덱이 지원해야 합니다. |
g | int | 2 | GOP 크기 — g프레임마다 하나의 keyframe을 생성합니다. 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 | {} | Extra FFmpeg or codec specific options merged after the structured fields above. Cannot override keys already set by those fields. |
깊이 스트림
Depth map(Intel RealSense, Reachy 2)은 RGB 스트림과 함께 독립적인 비디오 스트림으로 저장됩니다. 원시 depth(uint16 밀리미터 또는 float32 미터)는 8-bit 코덱을 통과할 수 없으므로, LeRobot은 각 map을 12-bit 코드([0, 4095])로 양자화합니다. 기본적으로 depth 센서의 1/depth 오차 프로파일에 맞추기 위해 로그 스케일로 양자화한 후, 이를 고 비트 깊이 픽셀 포맷(gray12le)에 패킹하여 12-bit 코덱으로 인코딩합니다.
float32 m →
depth_max] 범위 → 양자화 12비트 코드 0–4095
로그(기본값) 또는 선형 → 패킹 gray12le
평면 → 인코딩 HEVC
Main 12
스트림 →
--dataset.depth_encoder.<field>를 통해 설정되는 4개의 양자화 옵션을 추가한 DepthEncoderConfig를 사용하여 병렬 depth_encoder 블록으로 깊이 파이프라인을 구성합니다. 이 블록은 RGBEncoderConfig의 모든 필드(vcodec, pix_fmt, crf, …)를 공유합니다.
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"} | Depth 기본값은 lossless(정확한 round-trip)이며, crf는 무시됩니다. 더 작은 lossy 스트림을 얻으려면 extra_options={}를 전달하고 crf를 설정하세요. |
pix_fmt | str | "gray12le" | 양자화 코드를 전달하는 데 사용되는 단일 채널 12비트 픽셀 형식입니다. |
depth_min | float | 0.01 | 미터 단위의 깊이를 양자화 0에 매핑합니다. 해당 값은 디코딩 시 클리핑됩니다. |
depth_max | float | 10.0 | 미터 단위의 깊이를 양자화 4095에 매핑합니다. 해당 값 이상은 디코딩 시 클리핑됩니다. |
shift | float | 3.5 | 0 근처에서 수치적 안정성을 위해 대수적 양자화에 사용되는 사전 로그 오프셋(미터). depth_min + shift > 0을 만족해야 합니다. |
use_log | bool | True | true인 경우, 로그 공간에서 양자화합니다(일반적인 깊이 센서에 권장됨). 균일/선형 양자화를 사용하려면 false로 설정하세요. |
depth_min,depth_max,shift는 입력深度的 단위와 관계없이 항상 미터로 해석됩니다. 입력은 자동 감지됩니다: 정수 배열(예: RealSense에서 바로 가져온uint16밀리미터)은 밀리미터로, 부동소수점 배열은 미터로 처리됩니다.depth_min/depth_max를 센서의 실제 작동 범위를 포괄하도록 선택하세요. 해당 범위를 벗어난 값은 포화(saturation) 상태가 되어 경계 부분의 디테일이 손실될 수 있습니다.
Depth 기능은 meta/info.json에서 "is_depth_map": true로 표시되며, 해당 quantizer 설정(video.depth_min, video.depth_max, video.shift, video.use_log)이 영구적으로 저장됩니다. 이를 통해 로드 시 depth를 물리적 단위로 역양자화할 수 있습니다.
로드 시 출력 단위
depth_encoder는 기록 시점의 문제입니다. 학습 중과 같은 로드 시점에 depth map이 역양자화되는 단위는 읽기 시점 플래그 --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 블록에는 두 가지 출처가 기여합니다:
| 소스 | 출처 | 필드 |
|---|---|---|
| 스트림에서 파생된 | PyAV를 사용하여 인코딩된 MP4에서 다시 읽습니다. | 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 | Stream에서 파생된 필드는 소스 간에 일치해야 하며, 그렇지 않으면 FFmpeg의 concat demuxer가 실패합니다. |
| 느슨하게 병합됨 | video.g, video.crf, video.preset, video.fast_decode, video.extra_options | Encoder-tuning 필드. 모든 소스가 일치하면 값이 유지되고, 일치하지 않으면 null(video.extra_options의 경우 {})로 설정되고 경고가 기록됩니다. |