# ストリーミング動画エンコーディングガイド

## 1. 概要

ストリーミング動画エンコーディングにより、動画データセットの録画時の従来のPNG往復が不要になります。従来の方法では:

1. フレームをキャプチャ -> PNGをディスクに書き込み -> (エピソード終了時) PNGを読み込み -> MP4にエンコード -> PNGを削除

フレームはキャプチャ中にリアルタイムでエンコードできます:

1. フレームのキャプチャ -> エンコーダースレッドへのキューイング -> MP4への直接エンコード

これにより、`save_episode()`はほぼ即時に実行されるようになります（エピソードが終了する時点で動画はすでにエンコード済みです）。また、以前はエピソード間で発生していたブロッキングの待機が解消され、特に長時間のエピソードで複数のカメラを使用する場合にその効果が顕著です。

## 2. パラメータの調整

| パラメータ               | CLIフラグ                          | 型          | デフォルト       | 説明                                                       |
| ----------------------- | --------------------------------- | ------------- | ------------- | ----------------------------------------------------------------- |
| `streaming_encoding`    | `--dataset.streaming_encoding`    | `bool`        | `False`       | キャプチャ中にリアルタイムエンコーディングを有効にする                          |
| `vcodec`                | `--dataset.rgb_encoder.vcodec`    | `str`         | `"libsvtav1"` | ビデオコーデック。`"auto"`は最適なHWエンコーダーを検出します                     |
| `encoder_threads`       | `--dataset.encoder_threads`       | `int \| None` | `None`（自動） | エンコーダーインスタンスあたりのスレッド数。`None`の場合、vcodedが決定します |
| `encoder_queue_maxsize` | `--dataset.encoder_queue_maxsize` | `int`         | `30`          | カメラごとのバッファリングされる最大フレーム数(30fpsで約1秒分)。RAMを消費します       |

## 3. 性能に関する考慮事項

ストリーミングエンコーディングとは、キャプチャループの**最中に**CPUが動画をエンコードすることを意味します。これにより、次の間で共有されなければならないCPU予算が生まれます。

- **制御ループ**（カメラの読み取り、ロボットの制御、非動画データの書き込み）
- **エンコーダースレッド**（カメラごとに1つのプール）
- **可視化の再実行**（有効な場合）
- **OSおよびその他のプロセス**

### 解像度とカメラ台数の影響

| セットアップ                     | スループット（px/sec） | CPUエンコーディングの読み込み | 注記                          |
| ------------------------- | ------------------- | ----------------- | ------------------------------ |
| 2camsx 640x480x3 @30fps   | 55M                 | 低               | ほとんどのシステムで動作します          |
| 2camsx 1280x720x3 @30fps  | 165M                | 中程度          | モダンなシステムで快適に動作  |
| 2camsx 1920x1080x3 @30fps | 373M                | 高              | 高性能なハイエンドCPUが必要です |

### `encoder_threads` のチューニング

このパラメータは、各エンコーダーインスタンスが内部で使用するスレッド数を制御します:

- **高い値**（例：4〜5）：エンコード速度が速くなりますが、カメラごとに多くのCPUコアを使用します。コア数が豊富なハイエンドシステムに適しています。
- **低い値**（例：1〜2）：カメラごとのCPU使用量が少なくなり、キャプチャや可視化のコアを確保できます。低解像度の画像や高性能なCPUに適しています。
- **`None` (デフォルト)**: コーデックに決定を委ねます。利用可能な情報はコーデックのログにあります。

### バックプレッシャーとフレームのドロップ

各カメラには有界キュー（`encoder_queue_maxsize`、デフォルトは30フレーム）があります。エンコーダーが処理に追いつけない場合:

1. キューが埋まっていく（RAMを消費する）
2. 新しいフレームは**破棄**されます（ブロックされません）— キャプチャループは中断されずに続行されます
3. 警告が記録されます: `"Encoder queue full for {camera}, dropped N frame(s)"`
4. エピソード終了時、カメラごとの合計ドロップフレーム数が報告されます

### エンコーダーの遅延の兆候

- **システムがカクカクしてフリーズする**: すべての CPU が 100% になっています
- ログ内の**ドロップフレーム警告**、または記録されたデータセットで期待値を下回るフレーム数/FPS
- **ロボットの動きがぎこちない**: CPU が深刻に過負荷状態にある場合、キャプチャループにも影響が出る可能性があります
- **蓄積された再実行ラグ**: 可視化がリアルタイムに追いつかない

## 4. ハードウェアアクセラレーションによるエンコーディング

### 使用タイミング

次の場合は、HWエンコーディングを使用してください：

- CPUがボトルネック（フレームドロップ、ロボットの動作がカクカクする、rerunの遅延）
- 互換性のあるハードウェア（GPUまたは専用エンコーダー）をお持ちです
- 高スループット（高解像度または多数のカメラ）で記録しています

### コーデックの選択

| コーデック                 | CPU使用率 | ファイルサイズ      | 品質 | 注記                                                            |
| --------------------- | --------- | -------------- | ------- | ---------------------------------------------------------------- |
| `libsvtav1`（デフォルト） | 高      | 最小       | ベスト    | デフォルト。最も高い圧縮率ですが、CPU負荷も最大です                 |
| `h264`                | 中程度    | 約30〜50%大きい | 良い    | ソフトウェア H.264。CPU負荷の低減                                        |
| HWエンコーダー           | 非常に低い  | 最大        | 良い    | 専用ハードウェアにオフロードします。CPUリソースが制約されているシステムに最適です |

### 利用可能なHWエンコーダー

| エンコーダー             | プラットフォーム      | ハードウェア                                                                                         | CLI 値                                        |
| ------------------- | ------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
| `h264_videotoolbox` | macOS         | Apple Silicon / Intel                                                                            | `--dataset.rgb_encoder.vcodec=h264_videotoolbox` |
| `hevc_videotoolbox` | macOS         | Apple Silicon / Intel                                                                            | `--dataset.rgb_encoder.vcodec=hevc_videotoolbox` |
| `h264_nvenc`        | Linux/Windows | NVIDIA GPU                                                                                       | `--dataset.rgb_encoder.vcodec=h264_nvenc`        |
| `hevc_nvenc`        | Linux/Windows | NVIDIA GPU                                                                                       | `--dataset.rgb_encoder.vcodec=hevc_nvenc`        |
| `h264_vaapi`        | Linux         | Intel/AMD GPU                                                                                    | `--dataset.rgb_encoder.vcodec=h264_vaapi`        |
| `h264_qsv`          | Linux/Windows | Intel Quick Sync                                                                                 | `--dataset.rgb_encoder.vcodec=h264_qsv`          |
| `auto`              | すべて           | 利用可能なHWエンコーダをシステムにクエリします。HWエンコーダが見つからない場合は`libsvtav1`にフォールバックします | `--dataset.rgb_encoder.vcodec=auto`              |

> [!NOTE]
> HWアクセラレーション対応エンコーダーを使用するには、GPUドライバーのアップグレードが必要な場合があります。

> [!NOTE]
> `libsvtav1`がデフォルトであるのは、最も優れた学習パフォーマンスを提供するためです。他のvcodecsはCPU使用量を削減し、より高速になる場合がありますが、通常はファイルサイズが大きくなり、学習時間に影響を与える可能性があります。

## 5. トラブルシューティング

| 症状                                                            | 考えられる原因                                 | 修正                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| システムがフリーズする、ロボットの動作がぎこちなくなる、またはRerunのビジュアライゼーションが遅延する | CPUが逼迫（負荷使用率100%）                | 他のアプリを閉じ、エンコードのスループットを下げ、`encoder_threads`を減らし、`h264`を使用し、`display_data=False`を使用してください。CPUが引き続き100%のままの場合、お使いの環境では性能が不足している可能性があります。`--dataset.streaming_encoding=false`またはHWエンコード（`--dataset.rgb_encoder.vcodec=auto`）を検討してください。 |
| データセットにおける「Encoder queue full」の警告やフレームのドロップ         | エンコーダーが追いついていない（キューのオーバーフロー）       | CPUが100%に達していない場合: `encoder_threads`を増やす、`encoder_queue_maxsize`を増やす、またはHWエンコーディングを使用する(`--dataset.rgb_encoder.vcodec=auto`)。                                                                                                                                                    |
| RAM使用量が高い                                                     | エンコードよりキューの充填が速い           | `encoder_threads` が低すぎるか、CPU が不足しています。`encoder_queue_maxsize` を減らすか、HW エンコーディングを使用してください。                                                                                                                                                                                                 |
| 大規模な動画ファイル                                                  | HWエンコーダーまたはH.264の使用                    | 想定されるトレードオフ。CPUが許可している場合は`libsvtav1`に切り替えてください                                                                                                                                                                                                                                          |
| `save_episode()` がまだ遅い                                        | `streaming_encoding` は `False` です              | `--dataset.streaming_encoding=true` を設定します                                                                                                                                                                                                                                                          |
| エンコーダースレッドのクラッシュ                                               | コーデックが利用できないか、設定が無効です      | `vcodec`がインストールされていることを確認し、`--dataset.rgb_encoder.vcodec=auto`を試してください。                                                                                                                                                                                                                             |
| 記録されたデータセットにフレームが欠落しています                                 | CPU/GPUの逼迫または一時的な負荷の急増 | フレームの約5%が欠落している場合、システムが過負荷状態である可能性が高いです。上記の推奨事項に従ってください。欠落しているフレームが少ない場合（約2%）、それは一時的な負荷の急増（起動時によく見られます）によるものと考えられ、想定内の範囲とみなすことができます。                                               |

## 6. 推奨設定

これらの推定値は保守的なものです。ご自身の環境でテストすることをお勧めします。低い負荷から開始し、徐々に負荷を上げていきましょう。

### ハイエンドシステム: 最新の12コア以上(24スレッド以上)

CPUでのスループットは、約250〜500M px/sec程度であれば快適に動作するはずです。さらに良い結果を得たい場合は、利用可能な場合はHWエンコーディングを試してください。

```bash
# 3camsx 1280x720x3 @30fps: Defaults work well. Optionally increase encoder parallelism.
# 2camsx 1920x1080x3 @30fps: Defaults work well. Optionally increase encoder parallelism.
lerobot-record --dataset.encoder_threads=5 ...

# 3camsx 1920x1080x3 @30fps: Might require some tuning.
```

### ミッドレンジシステム: 最新の8コア以上(16スレッド以上)またはApple Silicon

CPUでは、約80〜300M px/secのスループットが実現可能であるはずです。

```bash
# 3camsx 640x480x3 @30fps: Defaults work well. Optionally decrease encoder parallelism.
# 2camsx 1280x720x3 @30fps: Defaults work well. Optionally decrease encoder parallelism.
lerobot-record --dataset.encoder_threads=2 ...

# 2camsx 1920x1080x3 @30fps: Might require some tuning.
```

### リソースが限られたシステム: 最新の4コア以上(8スレッド以上)またはRaspberry Pi 5

制約の厳しいシステムでは、ストリーミングエンコードがキャプチャループと過度に競合する可能性があります。これを無効化すると、エピソード間でエンコードが行われるPNGベースのアプローチにフォールバックします（ブロッキングは発生しますが、キャプチャには干渉しません）。また、キャプチャとエンコードの負荷を軽減するために、より低いスループットで記録することも検討してください。さらに、コーデックを`h264`に変更し、バッチエンコードを使用することも検討してください。

```bash
# 2camsx 640x480x3 @30fps: Requires some tuning.

# Use H.264, disable streaming, consider batching encoding
lerobot-record --dataset.rgb_encoder.vcodec=h264 --dataset.streaming_encoding=false ...
```

## 7. 結びの言葉

パフォーマンスは最終的に、正確なセットアップ — フレームレート、解像度、CPU コア数と負荷、利用可能なメモリ、エピソードの長さ、選択したエンコーダー — に依存します。必ずターゲットのワークロードでテストし、CPU とシステム的能力に注意を払い、`encoder_threads`、`encoder_queue_maxsize`、`vcodec` を適切に調整してください。とはいえ、一般的な実用的な設定（多くのアプリケーションにおいて）は、640×480x3 @30fps の 3 台のカメラです。これは、モダンなシステムではデフォルトのストリーミング動画エンコード設定で通常問題なく動作します。記録されたデータセットが健全であることを確認するために、必ず動画の再生時間を CLI のエピソード時間と比較し、行数が FPS × CLI 時間と等しいことを確認してください。

