LeRobot documentation
Tham số mã hóa video
Tham số mã hóa video
Khi lưu trữ video được bật, LeRobot lưu mỗi luồng camera dưới dạng tệp MP4 thay vì lưu một tệp ảnh cho mỗi bước thời gian. Mã hóa video nén dữ liệu theo chiều thời gian, thường giúp giảm kích thước bộ dữ liệu và I/O so với một tập hợp các tệp PNG, đồng thời vẫn giữ MP4 — định dạng mà mọi trình phát và trình nạp đều hiểu.
Việc mã hóa các khung hình thành MP4 là một quy trình FFmpeg hoàn chỉnh: lựa chọn bộ mã hóa, định dạng pixel, GOP/khung hình chính, cân bằng giữa chất lượng và tốc độ, cùng các cờ bộ mã hóa bổ sung tùy chọn. Hầu hết các thông số này đều có thể được người dùng điều chỉnh thông qua rgb_encoder, một cấu hình RGBEncoderConfig lồng nhau (lerobot.configs.video.RGBEncoderConfig) được truyền qua PyAV.
Bạn có thể đặt các tham số này từ CLI bằng --dataset.rgb_encoder.<field> (ví dụ với lerobot-record hoặc lerobot-rollout). Khối này áp dụng cho mọi luồng video camera trong lần chạy đó.
Lưu trữ video phải được bật để
rgb_encodercó hiệu lực —use_videos=Truetrong API Python, hoặc--dataset.video=truetrên CLI (mặc định khi ghi hình). Khi video tắt, đầu vào vẫn là hình ảnh vàrgb_encoderbị bỏ qua.
Để biết chi tiết về khi nào các khung hình được ghi so với được mã hóa (streaming so với sau mỗi episode), hàng đợi và các công tắc cấp cao --dataset.* khác, hãy xem Mã hóa video streaming. Để so sánh các tham số mã hóa và các thí nghiệm, hãy xem Space video-benchmark.
Ví dụ
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Điều chỉnh các tham số
Các giá trị mặc định được điều chỉnh để cân bằng giữa tỷ lệ nén, chất lượng hình ảnh và tốc độ giải mã/tìm kiếm cho các bộ dữ liệu robotics điển hình. Việc thay đổi chúng có thể ảnh hưởng đến cả quá trình ghi (tải CPU, mất khung hình) và huấn luyện (tốc độ thông qua giải mã, chất lượng hình ảnh).
Chỉ ghi đè các tham số này nếu bạn có lý do cụ thể, và đo lường tác động lên pipeline của bạn trước khi dựa vào các cài đặt mới.
Tất cả các cờ bên dưới đều được đặt tiền tố --dataset.rgb_encoder. trên CLI.
| Tham số | Loại | Mặc định | Mô tả |
|---|---|---|---|
vcodec | str | "libsvtav1" | Tên codec video. "auto" chọn trình mã hóa phần cứng khả dụng đầu tiên từ một danh sách ưu tiên cố định, sau đó chuyển sang libsvtav1. |
pix_fmt | str | "yuv420p" | Định dạng pixel đầu ra. Phải được hỗ trợ bởi codec đã chọn trong bản dựng FFmpeg của bạn. |
g | int | 2 | Kích thước GOP — một khung chính mỗi g khung hình. Được phát dưới dạng tùy chọn FFmpeg g. |
crf | int hoặc float | 30 | Giá trị chất lượng trừu tượng, được ánh xạ theo từng codec (xem phép ánh xạ). Giá trị thấp hơn → chất lượng cao hơn / kích thước đầu ra lớn hơn khi phép ánh xạ là đơn điệu. |
preset | int hoặc str | 12 * | Cài đặt trước tốc độ mã hóa; ý nghĩa phụ thuộc vào codec. * Khi chưa được đặt và vcodec=libsvtav1, LeRobot mặc định là 12. |
fast_decode | int | 0 | libsvtav1: 0–2, được truyền qua svtav1-params. h264 / hevc (phần mềm): nếu >0, sẽ đặt tune=fastdecode. Các codec khác: thường không được sử dụng. |
video_backend | str | "pyav" | Hiện tại, chỉ có "pyav" được triển khai cho việc mã hóa video. |
extra_options | dict | {} | Các tùy chọn cụ thể của FFmpeg hoặc codec bổ sung, được hợp nhất sau các trường có cấu trúc ở trên. Không thể ghi đè các khóa đã được thiết lập bởi các trường đó. |
Dòng dữ liệu độ sâu
Bản đồ độ sâu (Intel RealSense, Reachy 2) được lưu trữ dưới dạng luồng video riêng bên cạnh các luồng RGB. Độ sâu thô (uint16 milimét hoặc float32 mét) không thể tồn tại qua bộ mã hóa 8-bit, do đó LeRobot lượng tử hóa mỗi bản đồ thành mã 12-bit ([0, 4095]) — mặc định theo logarit, để phù hợp với hồ sơ lỗi 1/depth của các cảm biến độ sâu — sau đó đóng gói nó vào định dạng pixel có độ sâu bit cao (gray12le) và mã hóa bằng bộ mã hóa 12-bit.
float32 m →
depth_max] → Lượng tử hóa mã 12-bit 0–4095
log (mặc định) hoặc tuyến tính → Gói vào mặt phẳng gray12le
→ Mã hóa HEVC
Main 12
luồng →
Cấu hình pipeline độ sâu thông qua khối depth_encoder song song (DepthEncoderConfig). Nó chia sẻ mọi trường của RGBEncoderConfig (vcodec, pix_fmt, crf, …) và thêm bốn thông số lượng tử hóa, được đặt qua --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| Tham số | Loại | Mặc định | Mô tả |
|---|---|---|---|
vcodec | str | "hevc" | HEVC Main 12 (codec hỗ trợ 12-bit, tương thích MP4). |
extra_options | dict | {"x265-params": "lossless=1"} | Độ sâu mặc định là không mất mát (khôi phục chính xác); crf bị bỏ qua. Truyền extra_options={} và đặt crf để có luồng mất mát nhỏ hơn. |
pix_fmt | str | "gray12le" | Định dạng pixel 12-bit đơn kênh được sử dụng để mang các mã lượng tử hóa. |
depth_min | float | 0.01 | Độ sâu tính bằng mét được ánh xạ sang lượng tử 0. Các giá trị bên dưới sẽ bị cắt khi giải mã. |
depth_max | float | 10.0 | Độ sâu tính bằng mét được ánh xạ sang lượng tử 4095. Các giá trị lớn hơn sẽ bị cắt khi giải mã. |
shift | float | 3.5 | Độ lệch trước logarit (mét) được sử dụng trong lượng tử hóa logarit để đảm bảo ổn định số học gần bằng không. Phải thỏa mãn depth_min + shift > 0. |
use_log | bool | True | Nếu true, thực hiện lượng tử hóa trong không gian log (được khuyến nghị cho các cảm biến độ sâu thông thường). Đặt thành false để lượng tử hóa đều/tuyến tính. |
depth_min,depth_maxvàshiftluôn được hiểu theo đơn vị mét, bất kể đơn vị của dữ liệu đầu vào. Đầu vào được tự động phát hiện: mảng số nguyên (ví dụuint16milimét lấy trực tiếp từ RealSense) được coi là milimét, mảng số thực được coi là mét. Chọndepth_min/depth_maxđể bao phủ phạm vi hoạt động thực tế của cảm biến — các giá trị nằm ngoài phạm vi đó sẽ bị bão hòa, có thể làm mất chi tiết ở các biên.
Các tính năng độ sâu được đánh dấu bằng "is_depth_map": true trong meta/info.json, và các cài đặt bộ lượng tử hóa của chúng (video.depth_min, video.depth_max, video.shift, video.use_log) được lưu trữ — đây là điều cho phép độ sâu được giải lượng tử hóa trở lại đơn vị vật lý khi tải.
Đơn vị đầu ra khi tải
depth_encoder là một vấn đề về thời điểm ghi. Đơn vị mà các bản đồ độ sâu được khử lượng tử hóa khi tải (ví dụ trong quá trình huấn luyện) được thiết lập riêng bằng cờ thời điểm đọc --dataset.depth_output_unit:
lerobot-train \
--dataset.repo_id=<my_username>/<my_dataset_name> \
--dataset.depth_output_unit=m \
--policy.type=act| Tham số | Loại | Mặc định | Mô tả |
|---|---|---|---|
depth_output_unit | str | "mm" | Bản đồ độ sâu đơn vị vật lý được khử lượng tử hóa khi tải: "mm" (milimét) hoặc "m" (mét). |
Đây hoàn toàn là một lựa chọn về cách trình bày tại thời điểm giải mã — nó không làm thay đổi video đã lưu trữ hoặc metadata của nó, do đó cùng một dataset có thể được đọc dưới dạng
mmhoặcmmà không cần mã hóa lại. Nó không có tác dụng đối với các dataset không có camera đo độ sâu.
Lưu trữ trong metadata của dataset
Sau khi tập đầu tiên của một luồng video được mã hóa, cấu hình bộ mã hóa sẽ được lưu trữ vào metadata của dataset (meta/info.json) dưới mỗi tính năng video, cùng với các giá trị được dò từ chính tệp. Đối với một tính năng video observation.images.<camera>, bố cục trong info.json là:
{
"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 }
}
}
}
}Hai nguồn đóng góp vào khối info:
| Nguồn | Nó đến từ đâu | Các trường |
|---|---|---|
| Được dẫn xuất từ luồng | Đọc lại từ MP4 đã mã hóa bằng PyAV. | video.height, video.width, video.codec, video.pix_fmt, video.fps, video.channels, is_depth_map, audio.* |
| Được suy ra từ bộ mã hóa | Trích từ RGBEncoderConfig / DepthEncoderConfig. | video.g, video.crf, video.preset, video.fast_decode, video.video_backend, video.extra_options |
Khối này được nạp một lần, từ tập đầu tiên. Nó giả định rằng mọi tập trong bộ dữ liệu đều được mã hóa bằng cùng một
rgb_encoder. Việc thay đổi cài đặt bộ mã hóa giữa chừng quá trình ghi hình không được hỗ trợ —info.jsonsẽ chỉ phản ánh các tham số được sử dụng cho tập đầu tiên.
Gộp các bộ dữ liệu
Khi tổng hợp các bộ dữ liệu bằng merge_datasets, các tệp video được nối lại như ban đầu (không mã hóa lại) và các trường encoder trong info.json được gộp theo từng khóa:
| Quy tắc gộp | Các trường | Hành vi |
|---|---|---|
| Phải khớp | video.codec, video.pix_fmt, video.height, video.width, video.fps | Các trường có nguồn gốc từ stream phải khớp nhau giữa các nguồn, nếu không thì concat demuxer của FFmpeg sẽ thất bại. |
| Được hợp nhất lỏng lẻo | video.g, video.crf, video.preset, video.fast_decode, video.extra_options | Các trường encoder-tuning. Nếu mọi nguồn đều đồng thuận, giá trị sẽ được giữ lại; nếu không, nó sẽ được đặt thành null (hoặc {} cho video.extra_options) và một cảnh báo sẽ được ghi log. |