LeRobot documentation

视频编码参数

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

视频编码参数

启用视频存储后,LeRobot 会将每个相机流存储为 MP4 文件,而不是为每个时间步保存一个图像文件。视频编码在时间维度上进行压缩,与大量 PNG 文件相比,通常能减小数据集体积并降低 I/O 开销,同时保留 MP4 这一所有播放器和加载器都能识别的格式。

将帧编码为 MP4 是一个完整的 FFmpeg 流程:涉及编码器选择、像素格式、GOP/关键帧、质量与速度的权衡,以及可选的额外编码器标志。其中大部分参数都可以通过 rgb_encoder 进行用户自定义,它是一个嵌套的 RGBEncoderConfig(lerobot.configs.video.RGBEncoderConfig),并通过 PyAV 传递。

您可以通过 CLI 使用 --dataset.rgb_encoder.<field> 来设置这些参数(例如,使用 lerobot-record 或 lerobot-rollout)。该配置块适用于该运行中的每个相机视频流。

必须开启视频存储,rgb_encoder 才会生效——在 Python API 中设置 use_videos=True,或在 CLI 中使用 --dataset.video=true(录制时的默认值)。如果关闭视频,输入将保持为图像,rgb_encoder 会被忽略。

有关帧写入与编码(流式与回合后)的时机、队列以及其他顶层 --dataset.* 开关的详细信息,请参阅 流式视频编码。有关编码参数对比和实验,请参阅 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 负载、丢帧)和训练(解码吞吐量、图像质量)。

仅在确有特定原因时才覆盖这些参数,并在依赖新设置之前,先测量其对流水线的影响。

以下所有标志在命令行中均以 --dataset.rgb_encoder. 为前缀。

参数类型默认描述
vcodecstr"libsvtav1"视频编解码器名称。"auto" 会从固定的优先级列表中选取第一个可用的硬件编码器,若不可用则回退到 libsvtav1。
pix_fmtstr"yuv420p"输出像素格式。必须受您 FFmpeg 构建中选择的编解码器支持。
gint2GOP 大小 — 每隔 g 帧一个关键帧。作为 FFmpeg 选项 g 输出。
crfint 或 float30抽象质量值,按编解码器映射(参见映射)。在映射单调的情况下,值越低表示质量越高 / 输出越大。
presetint 或 str12 *编码器速度预设;其含义取决于编解码器。
* 当未设置且 vcodec=libsvtav1 时,LeRobot 默认值为 12。
fast_decodeint0libsvtav1:0–2,通过 svtav1-params 传递。
h264 / hevc(软件):如果 >0,则设置 tune=fastdecode。
其他编解码器:通常不使用。
video_backendstr"pyav"目前仅实现了"pyav"用于视频编码。
extra_optionsdict{}在上述结构化字段之后合并的额外 FFmpeg 或特定编解码器选项。无法覆盖这些字段已设置的键。

深度流

深度图(Intel RealSense、Reachy 2)作为独立的视频流与 RGB 流一同存储。原始深度(uint16 毫米或 float32 米)无法通过 8 位编解码器保留,因此 LeRobot 会将每张深度图量化为 12 位编码([0, 4095])——默认采用对数量化,以匹配深度传感器 1/depth 的误差特性——然后将其打包为高比特深度的像素格式(gray12le),并使用 12 位编解码器进行编码。

原始深度 uint16 mm
float32 m
→
记录时间 裁剪 至 [depth_min,
depth_max]
→ 量化 12 位编码 0–4095
对数(默认)或线性
→ 打包 为 gray12le
平面
→ 编码 HEVC
Main 12
→ MP4 存储
流
→
加载时间 反量化 为 mm / m

通过并行的 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
参数类型默认描述
vcodecstr"hevc"HEVC Main 12(支持 12 位深度的编解码器,兼容 MP4)。
extra_optionsdict{"x265-params": "lossless=1"}深度默认设置为无损(精确往返);crf 将被忽略。传入 extra_options={} 并设置 crf 以获得更小的有损流。
pix_fmtstr"gray12le"用于承载量化码的单通道 12 位像素格式。
depth_minfloat0.01以米为单位的深度映射到量子0。解码时,低于该值的数值会被截断。
depth_maxfloat10.0以米为单位的深度映射到量子化值 4095。解码时,超出该范围的值会被截断。
shiftfloat3.5用于对数量化中靠近零处的数值稳定性的对数前偏移量(米)。必须满足 depth_min + shift > 0。
use_logboolTrue如果 true,则在日志空间中进行量化(推荐用于典型的深度传感器)。对于均匀/线性量化,请设置为 false。

depth_min、depth_max 和 shift 始终以米为单位进行解释,与输入深度的单位无关。输入会自动检测:整数数组(例如直接来自 RealSense 的 uint16 毫米值)被视为毫米,浮点数组被视为米。 请选择合适的 depth_min / depth_max 以涵盖传感器的实际工作范围——超出该范围的量化值会饱和,这可能会压缩边界处的细节。

深度特征在 meta/info.json 中通过 "is_depth_map": true 进行标记,其量化器设置(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_unitstr"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流派生字段必须在各个源之间保持一致,否则 FFmpeg 的 concat demuxer 将会失败。
松散合并video.g, video.crf, video.preset, video.fast_decode, video.extra_options编码器调优字段。如果所有来源一致,则保留该值;否则,将其设置为 null(对于 video.extra_options 则设置为 {}),并记录一条警告。
Update on GitHub