# フォルダ内の動画をまとめてテストして結果を保存する手順

「特定のフォルダに入れた動画を全部処理して、スコア／グレードを保存したい」ときの手順です。
API サーバーを立てずに、コマンド一発でフォルダ内の動画を end-to-end 推論（上流AI → LLM評価 → グレード算出）し、結果をファイルに保存します。

同梱スクリプト: `app/batch_test.py`

---

## 1. 準備

```bash
cd ~/ramen-grade                      # 設置フォルダ
source .venv/bin/activate             # セットアップ済みの仮想環境
export PYTHONIOENCODING=utf-8 PYTHONUTF8=1
export RAMEN_SUITE_DIR="$(pwd)/upstream_suite"
# APIキーは secrets/byteplus.key か  export ARK_API_KEY=xxxx
```

テストしたい動画を、パッケージ直下の `test_videos/` に置きます（同梱済みのフォルダ）:
```bash
# ここに .MOV / .mp4 などを置く（scp等で転送）
ls ~/ramen-grade/test_videos/
```

---

## 2. 実行

```bash
python app/batch_test.py --input test_videos --slot 開店前
```
（どのフォルダから実行してもOK。結果は既定でパッケージ直下の `results/` に出ます）

- `--input` … 動画が入ったフォルダ（**必須**）。対応拡張子: `.mp4 .mov .m4v .avi .mkv`
- `--slot`  … 時間帯（全動画共通。例 `開店前` / `17時〜19時`）。省略可
- `--brix`  … スープ濃度の実測値（全動画共通）。省略時は濃度推定AIが推定
- `--out`   … 結果の保存先フォルダ（**既定: パッケージ直下の `results/`**）

> **パスについて**: パッケージはどの階層に設置しても動きます（コードは自分の位置を基準にパスを解決します）。
> `--input` に相対パスを渡した場合は「実行時のカレントディレクトリ → パッケージ直下」の順に探すため、
> `test_videos` のようにパッケージ直下へ置いておけば、**どのフォルダから実行しても** 同じ場所を指します。
> `--out` を省略すると常にパッケージ直下の `results/` に出るので、実行場所によって出力先がブレません。

実行すると1本ずつ処理され、進捗が表示されます:
```
入力: /home/user/ramen-grade/test_videos  動画 5 本
出力: /home/user/ramen-grade/results
モデル読込中（初回のみ1〜2分）...
[1/5] 123.MOV ... scored (total=88.3/A, soup=86.1/A) 47s
[2/5] 124.MOV ... 要確認 (total=-/-, soup=-/-) 12s
...
===== 完了 =====
採点: 4 / 要確認: 1 / エラー: 0  （計 5 本）
```

### 動画ごとに濃度・時間帯を変えたい場合（CSV指定）
`meta.csv` を用意して `--csv` で渡します（列は一部だけでも可）:
```csv
filename,brix,slot,store
123.MOV,12,開店前,豚山サンプル店
124.MOV,,17時〜19時,豚山サンプル店
```
```bash
python app/batch_test.py --input test_videos --csv meta.csv
```
CSVで空欄にした項目は、`--brix` / `--slot` / `--store` で渡した共通値が使われます。
```bash
```

---

## 3. 保存される結果（`--out` フォルダ内）

| ファイル | 内容 |
|---|---|
| `results.csv` | **一覧表**。動画名・status・total/soupのスコアとグレード・可読性・濃度など（Excelでそのまま開ける／UTF-8 BOM付き） |
| `results.jsonl` | 全動画の全結果（中間結果込み・1行1動画） |
| `details/<動画名>.json` | 動画ごとの詳細JSON（上流AIの判定・LLM評価の各軸まで） |

### `status` の見方
- `scored` … 採点成功（`total_score`/`total_grade`、`soup_score`/`soup_grade`）
- `要確認` … AIが判定不能（湯気過多・スープ面不可視・LLM判定不可）。点は付かない
- `error` … 処理中に例外（`error` 列に理由）。1本失敗しても残りは続行します

---

## 4. 注意

- **入力フォルダの動画は削除されません**（APIサーバー経由と違い、テスト用途なので残します）。
- 初回はモデル読込に1〜2分。以降は動画1本あたり CPU で数十秒〜2分。
- メモリ8GB環境では swap を必ず設定（未設定だと処理中に `Killed` で落ちることあり）。
- 同じ `--out` に再実行すると `results.csv` / `results.jsonl` は上書きされます。残したい場合は `--out results_20260717` のように分けてください。
