LeRobot documentation

Tham số mã hóa video

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

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_encoder có hiệu lực — use_videos=True trong API Python, hoặc --dataset.video=true trên CLI (mặc định khi ghi hình). Khi video tắt, đầu vào vẫn là hình ảnh và rgb_encoder bị 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ạiMặc địnhMô tả
vcodecstr"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_fmtstr"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.
gint2Kí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.
crfint hoặc float30Giá 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.
presetint hoặc str12 *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_decodeint0libsvtav1: 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_backendstr"pyav"Hiện tại, chỉ có "pyav" được triển khai cho việc mã hóa video.
extra_optionsdict{}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.

Độ sâu thô uint16 mm
float32 m
→
Thời điểm ghi Cắt trong [depth_min,
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
→ MP4 lưu
luồng
→
Thời điểm tải Khử lượng tử hóa thành mm / m

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ạiMặc địnhMô tả
vcodecstr"hevc"HEVC Main 12 (codec hỗ trợ 12-bit, tương thích MP4).
extra_optionsdict{"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_fmtstr"gray12le"Định dạng pixel 12-bit đơn kênh được sử dụng để mang các mã lượng tử hóa.
depth_minfloat0.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_maxfloat10.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ã.
shiftfloat3.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_logboolTrueNế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_max và shift luô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ụ uint16 milimé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ọn depth_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ạiMặc địnhMô tả
depth_output_unitstr"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 mm hoặc m mà 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ồnNó đến từ đâuCá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óaTrí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.json sẽ 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ộpCác trườngHành vi
Phải khớpvideo.codec, video.pix_fmt, video.height, video.width, video.fpsCá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ẻovideo.g, video.crf, video.preset, video.fast_decode, video.extra_optionsCá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.
Update on GitHub