Skip to content

视频录制功能

概述

L2 三个数据源(scripted / rl / teleop)统一支持视频录制功能,用于:

  • 质量检查:快速浏览轨迹质量,筛选出失败或异常的 episode
  • 演示展示:生成高质量视频用于论文、报告或演示

快速开始

1. scripted 数据源

bash
# 基础录制(每个 episode 都录)
uv run sim2lerobot scripted collect --task lift_cube --num_demos 10 --num_envs 4 --video

# 每 5 个 episode 录一个(减少磁盘占用)
uv run sim2lerobot scripted collect --task lift_cube --num_demos 50 --num_envs 4 --video --video_interval 5

输出

  • HDF5: data/lift_cube/scripted/{run_id}/episodes.hdf5
  • 视频: data/lift_cube/scripted/{run_id}/videos/episode-*.mp4

2. RL 数据源

bash
# 先训练 PPO
uv run sim2lerobot rl train --task lift_cube

# 然后 rollout 并录制视频
uv run sim2lerobot rl rollout \
    --task lift_cube \
    --checkpoint data/lift_cube/rl/latest.pt \
    --num_demos 100 \
    --num_envs 32 \
    --video \
    --video_interval 10

输出

  • HDF5: data/lift_cube/rl/{run_id}/episodes.hdf5
  • 视频: data/lift_cube/rl/{run_id}/videos/episode-*.mp4

3. teleop 数据源

bash
# keyboard 遥操作录制
uv run sim2lerobot teleop record --task lift_cube --num_demos 5 --video

输出

  • HDF5: data/lift_cube/teleop/{run_id}/episodes.hdf5
  • 视频: data/lift_cube/teleop/{run_id}/videos/episode-*.mp4

参数说明

参数默认值说明
--videoFalse启用视频录制(不加此参数则不录制)
--video_interval1每 N 个 episode 录一个视频

输出目录结构

视频和 HDF5 数据按任务和数据源分目录保存,每次运行落一个独立的 {run_id}/ 子目录(默认时间戳),重复执行不再互相覆盖:

data/
├── lift_cube/
│   ├── scripted/
│   │   └── {run_id}/
│   │       ├── episodes.hdf5
│   │       ├── run.log
│   │       ├── meta.json
│   │       └── videos/
│   │           ├── episode-0.mp4
│   │           ├── episode-1.mp4
│   │           └── ...
│   ├── rl/
│   │   ├── latest.pt              # symlink,指向最近一次 train run 的最终 checkpoint
│   │   └── {run_id}/
│   │       ├── episodes.hdf5
│   │       ├── run.log
│   │       ├── meta.json
│   │       └── videos/
│   │           ├── episode-0.mp4
│   │           └── ...
│   └── teleop/
│       └── {run_id}/
│           ├── episodes.hdf5
│           ├── run.log
│           ├── meta.json
│           └── videos/
│               ├── episode-0.mp4
│               └── ...

性能影响

  • 运行时间开销:~10-20%(取决于分辨率和帧率)
  • 磁盘占用:每个 episode 约 1-5 MB(H.264 编码,1280×720)
  • 显存占用:增加约 100-200 MB(用于渲染缓冲区)

视频规格

  • 分辨率:1280×720(由 env_cfg.viewer.window_width/height 决定)
  • 帧率:与仿真频率一致
    • scripted/rl:50 Hz(sim.dt=0.01 × decimation=2
    • teleop:30 Hz(--step_hz 30
  • 编码:H.264 (mp4),CRF 23(平衡质量和文件大小)
  • 视角:透视相机,默认位置 (7.5, 7.5, 7.5) 米,朝向场景中心

可以通过修改 env_cfg.viewer.eyeenv_cfg.viewer.lookat 调整视角。

技术实现

基于 IsaacLab 内置的视频录制基础设施:

  • VideoRecorder:IsaacLab 的 envs.utils.video_recorder 模块,通过 render_mode="rgb_array" 启用
  • omni.replicator:IsaacSim 的渲染扩展,通过 AppLauncher(enable_cameras=True) 自动加载
  • gymnasium RecordVideo wrapper:标准的 gym wrapper,自动处理视频编码和保存
  • 统一接口l2/utils/video.py 提供 wrap_env_with_video_recorder() 函数,三个数据源共享

代码示例

python
# 1. 创建 env 时传入 render_mode="rgb_array"
env = gym.make(task_id, cfg=env_cfg, render_mode="rgb_array")

# 2. 用统一接口包装
from video_utils import wrap_env_with_video_recorder

env = wrap_env_with_video_recorder(
    env,
    video_dir="data/lift_cube/scripted/{run_id}/videos",
    video_prefix="lift_cube",
    episode_trigger=lambda ep_id: ep_id % 5 == 0,  # 每 5 个录一个
)

# 3. 正常运行,视频自动录制
env.reset()
for _ in range(100):
    env.step(actions)
env.close()  # 重要:让 wrapper 完成编码

架构流程

用户脚本 (collect.py / rollout_and_record.py / record.py)

    ├─ 创建 env 时传入 render_mode="rgb_array"
    │   └─ 触发 IsaacLab VideoRecorder 初始化
    │       ├─ Kit backend (PhysX): 使用 omni.replicator.core
    │       └─ Newton backend: 使用 Newton GL viewer

    ├─ 调用 wrap_env_with_video_recorder(env, ...)
    │   └─ 包装为 gym.wrappers.RecordVideo
    │       ├─ episode_trigger: 决定哪些 episode 录制
    │       ├─ video_length: 每个视频的最大帧数(0=整个 episode)
    │       └─ video_folder: 输出目录

    └─ 正常运行 env.step()
        └─ RecordVideo wrapper 自动调用 env.render()
            └─ VideoRecorder.render_rgb_array() 返回 RGB 帧
                └─ 编码并保存为 mp4

故障排查

ModuleNotFoundError: No module named 'omni.replicator' 或 'isaacsim.core.rendering_manager'

原因:IsaacSim 的视频录制相关模块未安装,或 IsaacLab 的 isaaclab.python.headless.rendering.kit experience 文件缺少依赖。

解决

  1. 代码已实现优雅降级。如果缺少必要模块,会打印警告并继续运行(不录制视频)。数据采集不受影响。
  2. 如果需要视频录制,确保 IsaacLab 的 apps/isaaclab.python.headless.rendering.kit 文件的 [dependencies] 部分包含:
    toml
    "isaacsim.core.rendering_manager" = {}
    这个修复已经应用到当前 IsaacLab 安装中。如果重新安装或更新 IsaacLab,需要重新应用此修复。详见 IsaacLab 视频修复说明

视频文件为空或损坏

原因:env 在视频编码完成前被关闭。

解决:确保 env.close() 在主循环结束后调用,让 RecordVideo wrapper 有时间完成编码。

视频帧率不稳定

原因:仿真频率不稳定(CPU/GPU 负载过高)。

解决

  • 减少并行 env 数量(--num_envs
  • 降低视频分辨率(修改 env_cfg.viewer.window_width/height
  • 增加 --video_interval,只录制部分 episode

显存不足

原因:视频录制需要额外的渲染缓冲区。

解决

  • 减少并行 env 数量(--num_envs
  • 增加 --video_interval
  • 降低视频分辨率(修改 env_cfg.viewer
  • 不录制视频(去掉 --video 参数)

相关文档

参考