流式视频编码指南
1. 概述
流式视频编码消除了视频数据集记录期间传统的 PNG 往返过程。不再是:
- 捕获帧 -> 将 PNG 写入磁盘 -> (在回合结束时)读取 PNG -> 编码为 MP4 -> 删除 PNG
帧可以在捕获期间实时编码:
- 捕获帧 -> 排队到编码器线程 -> 直接编码为 MP4
这使得 save_episode() 几乎是即时的(视频在回合结束时已经编码完成),并消除了以前在回合之间发生的阻塞等待,特别是在长回合中有多个摄像头的情况下。
2. 调优参数
| 参数 | CLI 标志 | 类型 | 默认值 | 描述 |
|---|---|---|---|---|
streaming_encoding |
--dataset.streaming_encoding |
bool |
True |
在捕获期间启用实时编码 |
vcodec |
--dataset.camera_encoder.vcodec |
str |
"libsvtav1" |
视频编解码器。"auto" 检测最佳硬件编码器 |
encoder_threads |
--dataset.encoder_threads |
int \| None |
None(自动) |
每个编码器实例的线程数。None 将让编解码器决定 |
encoder_queue_maxsize |
--dataset.encoder_queue_maxsize |
int |
30 |
每个摄像头的最大缓冲帧数(30fps 时约 1 秒)。消耗 RAM |
3. 性能考虑
流式编码意味着 CPU 在捕获循环期间编码视频,而不是之后。这创建了一个必须在以下各项之间共享的 CPU 预算:
- 控制循环(读取摄像头、控制机器人、写入非视频数据)
- 编码器线程(每个摄像头一个池)
- Rerun 可视化(如果启用)
- 操作系统和其他进程
分辨率和摄像头数量的影响
| 设置 | 吞吐量(像素/秒) | CPU 编码负载 | 注释 |
|---|---|---|---|
| 2 个摄像头 640x480x3 @30fps | 55M | 低 | 在大多数系统上工作 |
| 2 个摄像头 1280x720x3 @30fps | 165M | 中等 | 在现代系统上舒适 |
| 2 个摄像头 1920x1080x3 @30fps | 373M | 高 | 需要强大的高端 CPU |
encoder_threads 调优
此参数控制每个编码器实例内部使用多少线程:
- 较高值(例如 4-5):编码更快,但每个摄像头使用更多 CPU 核心。适合具有多核心的高端系统。
- 较低值(例如 1-2):每个摄像头使用更少的 CPU,为捕获和可视化释放核心。适合低分辨率图像和有能力的 CPU。
None(默认):让编解码器决定。信息可在编解码器日志中获得。
背压和丢帧
每个摄像头都有一个有界队列(encoder_queue_maxsize,默认 30 帧)。当编码器跟不上时:
- 队列填满(消耗 RAM)
- 新帧被丢弃(不阻塞)——捕获循环继续不间断
- 记录警告:
"Encoder queue full for {camera}, dropped N frame(s)" - 在回合结束时,报告每个摄像头的总丢帧数
编码器落后的症状
- 系统感觉卡顿和冻结:所有 CPU 都处于 100%
- 日志中的丢帧警告或记录数据集中的帧数/FPS 低于预期
- 机器人运动不流畅:如果 CPU 严重过载,甚至捕获循环也可能受到影响
- 累积的 rerun 延迟:可视化落后于实时
4. 硬件加速编码
何时使用
在以下情况下使用硬件编码:
- CPU 是瓶颈(丢帧、机器人不流畅、rerun 延迟)
- 您有兼容的硬件(GPU 或专用编码器)
- 您以高吞吐量记录(高分辨率或多个摄像头)
选择编解码器
| 编解码器 | CPU 使用 | 文件大小 | 质量 | 注释 |
|---|---|---|---|---|
libsvtav1(默认) |
高 | 最小 | 最佳 | 默认。最佳压缩但最耗 CPU |
h264 |
中等 | 约大 30-50% | 良好 | 软件 H.264。较低的 CPU |
| 硬件编码器 | 非常低 | 最大 | 良好 | 卸载到专用硬件。最适合 CPU 受限的系统 |
可用的硬件编码器
| 编码器 | 平台 | 硬件 | CLI 值 |
|---|---|---|---|
h264_videotoolbox |
macOS | Apple Silicon / Intel | --dataset.camera_encoder.vcodec=h264_videotoolbox |
hevc_videotoolbox |
macOS | Apple Silicon / Intel | --dataset.camera_encoder.vcodec=hevc_videotoolbox |
h264_nvenc |
Linux/Windows | NVIDIA GPU | --dataset.camera_encoder.vcodec=h264_nvenc |
hevc_nvenc |
Linux/Windows | NVIDIA GPU | --dataset.camera_encoder.vcodec=hevc_nvenc |
h264_vaapi |
Linux | Intel/AMD GPU | --dataset.camera_encoder.vcodec=h264_vaapi |
h264_qsv |
Linux/Windows | Intel Quick Sync | --dataset.camera_encoder.vcodec=h264_qsv |
auto |
任何 | 探测系统以查找可用的硬件编码器。如果未找到硬件编码器,则回退到 libsvtav1 |
--dataset.camera_encoder.vcodec=auto |
[!NOTE] 为了使用硬件加速编码器,您可能需要升级 GPU 驱动程序。
[!NOTE]
libsvtav1是默认设置,因为它提供最佳的训练性能;其他编解码器可以减少 CPU 使用并更快,但它们通常会产生更大的文件,并可能影响训练时间。
5. 故障排除
| 症状 | 可能原因 | 修复 |
|---|---|---|
| 系统冻结或机器人运动不流畅或 Rerun 可视化延迟 | CPU 饥饿(100% 负载使用) | 关闭其他应用程序,减少编码吞吐量,降低 encoder_threads,使用 h264,使用 display_data=False。如果 CPU 继续处于 100%,则可能不足以满足您的设置,考虑 --dataset.streaming_encoding=false 或硬件编码(--dataset.camera_encoder.vcodec=auto) |
| "Encoder queue full" 警告或数据集中的丢帧 | 编码器跟不上(队列溢出) | 如果 CPU 未达到 100%:增加 encoder_threads,增加 encoder_queue_maxsize 或使用硬件编码(--dataset.camera_encoder.vcodec=auto)。 |
| 高 RAM 使用 | 队列填充速度快于编码速度 | encoder_threads 太低或 CPU 不足。减少 encoder_queue_maxsize 或使用硬件编码 |
| 大视频文件 | 使用硬件编码器或 H.264 | 预期的权衡。如果 CPU 允许,切换到 libsvtav1 |
save_episode() 仍然很慢 |
streaming_encoding 为 False |
设置 --dataset.streaming_encoding=true |
| 编码器线程崩溃 | 编解码器不可用或设置无效 | 检查 vcodec 是否已安装,尝试 --dataset.camera_encoder.vcodec=auto |
| 记录的数据集缺少帧 | CPU/GPU 饥饿或偶尔的负载峰值 | 如果约 5% 的帧缺失,您的系统可能过载——遵循上述建议。如果缺失的帧较少(约 2%),它们可能是由于偶尔的瞬态负载峰值(通常在启动时)造成的,可以认为是预期的。 |
6. 推荐配置
这些估计是保守的;我们建议在您的设置上测试它们——从低负载开始并逐渐增加。
高端系统:现代 12+ 核心(24+ 线程)
250-500M 像素/秒之间的吞吐量在 CPU 上应该是舒适的。为了获得更好的结果,如果可用,请尝试硬件编码。
# 3 个摄像头 1280x720x3 @30fps:默认设置效果良好。可选地增加编码器并行度。
# 2 个摄像头 1920x1080x3 @30fps:默认设置效果良好。可选地增加编码器并行度。
lerobot-record --dataset.encoder_threads=5 ...
# 3 个摄像头 1920x1080x3 @30fps:可能需要一些调优。
中端系统:现代 8+ 核心(16+ 线程)或 Apple Silicon
80-300M 像素/秒之间的吞吐量在 CPU 上应该是可能的。
# 3 个摄像头 640x480x3 @30fps:默认设置效果良好。可选地减少编码器并行度。
# 2 个摄像头 1280x720x3 @30fps:默认设置效果良好。可选地减少编码器并行度。
lerobot-record --dataset.encoder_threads=2 ...
# 2 个摄像头 1920x1080x3 @30fps:可能需要一些调优。
低资源系统:现代 4+ 核心(8+ 线程)或 Raspberry Pi 5
在非常受限的系统上,流式编码可能与捕获循环竞争过于激烈。禁用它会回退到基于 PNG 的方法,其中编码发生在回合之间(阻塞,但不干扰捕获)。或者,以较低的吞吐量记录以减少捕获和编码负载。还可以考虑将编解码器更改为 h264 并使用批量编码。
# 2 个摄像头 640x480x3 @30fps:需要一些调优。
# 使用 H.264,禁用流式传输,考虑批量编码
lerobot-record --dataset.camera_encoder.vcodec=h264 --dataset.streaming_encoding=false ...
7. 结束语
性能最终取决于您的确切设置——每秒帧数、分辨率、CPU 核心和负载、可用内存、回合长度以及您选择的编码器。始终使用目标工作负载进行测试,注意您的 CPU 和系统能力,并合理调整 encoder_threads、encoder_queue_maxsize 和 vcodec。也就是说,一个常见的实用配置(对于许多应用程序)是三个摄像头,分辨率为 640×480x3 @30fps;这通常在现代系统中使用默认流式视频编码设置运行良好。始终通过将视频持续时间与 CLI 回合持续时间进行比较并确认行数等于 FPS × CLI 持续时间来验证您记录的数据集是否健康。