LeRobot documentation
Video encoding parameters
Video encoding parameters
ビデオストレージが有効な場合、LeRobotはタイムステップごとの画像ファイルを保存する代わりに、各カメラストリームをMP4ファイルとして保存します。ビデオエンコードは時間軸に沿って圧縮を行うため、PNGの山を扱う場合と比べて、通常はデータセットのサイズとI/Oを削減できます。また、MP4はすべてのプレイヤーやローダーが理解する形式であるため、互換性を保ちます。
MP4へのフレームエンコードは、エンコーダーの選択、ピクセルフォーマット、GOP/キーフレーム、品質と速度のバランス、および任意の追加エンコーダーフラグを含む、完全なFFmpegパイプラインです。これらの設定の多くは、PyAVを介して渡されるネストされたRGBEncoderConfig(lerobot.configs.video.RGBEncoderConfig)であるrgb_encoderを通じて、ユーザーが調整できます。
これらのパラメータは、--dataset.rgb_encoder.<field>(例:lerobot-recordまたはlerobot-rollout)を介してCLIから設定できます。このブロックは、その実行のすべてのカメラ映像ストリームに適用されます。
rgb_encoderが効果を発揮するには、ビデオの保存を有効にする必要があります — Python API ではuse_videos=True、CLI では--dataset.video=true(録画時のデフォルト値)を指定します。ビデオが無効の場合、入力は画像のままとなり、rgb_encoderは無視されます。
いつフレームが書き込まれるのか、エンコードされるのか(ストリーミングかエピソード後か)の詳細、キュー、およびその他のトップレベルの--dataset.*スイッチについては、Streaming Video Encodingを参照してください。エンコードパラメータの比較と実験については、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負荷、フレームドロップ)と学習(デコードスループット、画像品質)の両方に影響を与える可能性があります。
これらのパラメータを上書きするのは、明確な理由がある場合のみとし、新しい設定に依存する前に、パイプラインへの影響を測定してください。
以下のすべてのフラグは、CLI では --dataset.rgb_encoder. というプレフィックスが付与されます。
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
vcodec | str | "libsvtav1" | ビデオコーデック名。"auto"は、固定の優先度リストから最初の利用可能なハードウェアエンコーダーを選択し、利用できない場合はlibsvtav1にフォールバックします。 |
pix_fmt | str | "yuv420p" | 出力ピクセル形式。選択したコーデックが、お使いのFFmpegビルドでサポートしている必要があります。 |
g | int | 2 | GOPサイズ — gフレームごとにキーフレームを出力します。FFmpegオプションのgとして出力されます。 |
crf | intまたはfloat | 30 | 抽象的な品質値。コーデックごとにマッピングされます(マッピングを参照)。マッピングが単調な場合、値が低いほど品質が高く、出力サイズが大きくなります。 |
preset | intまたはstr | 12 * | エンコーダーの速度プリセット。意味はコーデックによって異なります。 * 未設定かつ vcodec=libsvtav1の場合、LeRobotはデフォルトで12を使用します。 |
fast_decode | int | 0 | libsvtav1: 0–2、svtav1-paramsを介して渡されます。h264 / hevc(ソフトウェア): >0の場合、tune=fastdecodeを設定します。その他のコーデック: 通常は使用されません。 |
video_backend | str | "pyav" | 現在、動画エンコーディングには"pyav"のみが実装されています。 |
extra_options | dict | {} | 上記の構造化フィールドの後にマージされる、FFmpegまたはコーデック固有の追加オプションです。これらのフィールドによって既に設定されているキーは上書きできません。 |
深度ストリーム
深度マップ(Intel RealSense、Reachy 2)は、RGB ストリームと並んで、独自のビデオストリームとして保存されます。生深度(uint16 のミリメートルまたは float32 のメートル)は 8 ビットコーデックでは保持できないため、LeRobot は各マップを 12 ビットコード([0, 4095])に量子化します。これはデフォルトで対数的に行われ、深度センサーの 1/depth エラープロファイルに合わせるためです。その後、高ビット深度のピクセルフォーマット(gray12le)にパッキングし、12 ビットコーデックでエンコードします。
float32 m →
depth_max] へ → 量子化 12ビットコード 0–4095
log(デフォルト)または linear → パック gray12le
プレーンへ → エンコード HEVC
Main 12
ストリーム →
並列のdepth_encoderブロック(DepthEncoderConfig)を通じて深度パイプラインを設定します。これはRGBEncoderConfigのすべてのフィールド(vcodec、pix_fmt、crf、…)を共有し、--dataset.depth_encoder.<field>で設定する4つの量子化パラメータを追加します。
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| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
vcodec | str | "hevc" | HEVC Main 12(12ビット対応のコーデック、MP4互換)。 |
extra_options | dict | {"x265-params": "lossless=1"} | Depth はデフォルトで lossless(完全なラウンドトリップ)です。crf は無視されます。より小さい有損ストリームにするには、extra_options={} を渡し、crf を設定してください。 |
pix_fmt | str | "gray12le" | 量子化コードを保持するために使用される、単一チャネルの12ビットピクセル形式。 |
depth_min | float | 0.01 | メートル単位の深さを量子化0にマッピングします。以下の値はデコード時にクリップされます。 |
depth_max | float | 10.0 | メートル単位の深度は量子化値4095にマッピングされます。これを超える値はデコード時にクリップされます。 |
shift | float | 3.5 | ゼロ付近の数値安定性のために対数量子化で使用するログ前オフセット(メートル)。depth_min + shift > 0 を満たす必要があります。 |
use_log | bool | True | trueの場合、対数空間で量子化します(一般的な深度センサーには推奨されます)。均一/線形量子化にはfalseを設定してください。 |
depth_min、depth_max、およびshiftは、入力深度の単位に関わらず、常にメートルとして解釈されます。入力は自動検出されます。整数配列(例: RealSense から直接取得したuint16のミリメートル値)はミリメートルとして、浮動小数点配列はメートルとして扱われます。depth_min/depth_maxは、センサーの実際の動作範囲を囲むように設定してください。この範囲外の量子は飽和するため、境界部分の詳細が潰れてしまう可能性があります。
Depth機能はmeta/info.json内で"is_depth_map": trueとしてフラグ付けされ、その量子化設定(video.depth_min、video.depth_max、video.shift、video.use_log)が永続化されます。これにより、読み込み時にdepthを物理単位に逆量子化することが可能になります。
読み込み時の出力ユニット
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_unit | str | "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ブロックには、2つのソースが寄与します:
| ソース | その由来 | フィールド |
|---|---|---|
| ストリーム由来 | 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の場合は{})に設定され、警告がログに記録されます。 |