# LUT プリセット

`edit.json` の `output.look.lut` から**名前で参照する** 3D LUT（`.cube`）の表です。素材ライブラリ
（`assets/` / `catalog/`）ではなく、コードが id からファイルを解決する参照表なので
[presets/](../INDEX.md) に置いています（`meta.json` は持ちません。§由来）。

ここに置く LUT は**自前生成**です（旧実装 `akari-video-on-os/src/lib/color-grade.ts` の色演算式を
`bake-luts.mjs` に移植して焼いたもの）。第三者ライセンスの制約がないため実ファイルをそのまま
同梱しています。出所不明のフリー LUT 収集はしていません（内部の render-basics 契約・残裁定 2 の裁定）。

## 構造

```
presets/luts/
  index.jsonl        # 1 プリセット 1 行。id・name・when_to_use・tags・params・source を持つ。AI が読むのはここだけ
  bake-luts.mjs      # PRESETS テーブルから .cube を決定的に再生成するスクリプト
  bake-previews.mjs  # LUT とトランジションの見本を純 JS で再生成する入口
  reference-frame.webp # 全 LUT で共有する合成図案（160×180）
  <id>/
    <id>.cube         # 3D LUT 本体（LUT_3D_SIZE 33）。render-cut が読む
    preview.webp      # 左半分が元色・右半分が LUT 適用後（320×180）
```

## エントリ

- **natural** — 控えめなコントラスト・彩度・暖色寄りの微調整のみ。汎用の穏当な既定候補
- **cinematic** — ティール&オレンジ系のフィルム調ルック。強めの作風主張あり
- **film-warm** — 黒をわずかに浮かせ、ハイライトを琥珀色へ寄せた暖色フィルム
- **mono** — 彩度を完全に除き、引き締まった階調に整えるモノクロ
- **silver-retain** — 元色をわずかに残しながら低彩度・高コントラストにする銀残し
- **vintage-fade** — 黒浮き・低彩度・黄転びで古いプリントの退色感を作るレトロ調
- **cool-clear** — 青寄りの色温度と軽いコントラストで白と空気感を澄ませる寒色調
- **night-neon** — 青紫の暗部と高彩度で人工光を際立たせるネオン夜景調
- **forest-soft** — 緑をわずかに足し、階調と彩度を柔らかく整える vlog 向け自然調
- **sunset-gold** — 強い暖色と橙のハイライトで夕景の金色を押し出すゴールド調

選定に必要な `when_to_use` / `ai_usage` / `params` は [index.jsonl](./index.jsonl) にあります。

## 参照方法

`edit.json` の `output.look.lut` に id（例: `"natural"`）を渡すと、
`packages/render-cut/src/render-inputs.mjs` が `presets/luts/<id>/<id>.cube` を解決します。
パス区切り文字を含む値（例: `"assets/custom.cube"`）はプロジェクトルート相対のパスとして扱われ、
プリセット参照にはなりません。強さは `output.look.intensity`（0〜1）で調整します。

## 再生成

```
node presets/luts/bake-luts.mjs
node presets/luts/bake-previews.mjs
```

`bake-luts.mjs` 内の `PRESETS` テーブルを編集すれば、パラメータを調整のうえ決定的に再生成できます。
見本は `.cube` を三線形補間して焼きます。WebP と確認用 PNG の生成は Node 標準機能と
`presets/luts/` の純 JS だけで完結します。再生成のたびに同じバイト列になります。

## 見本の基準フレーム

権利の確認が必要な写真は使わず、空・日差し・緑・人物の肌色・暗部を含む 8 色の
図案を `preview-art.mjs` で決定論的に合成し、`reference-frame.webp` に同梱しています。
空は縦方向、肌は暗部から明部へ、画面下のグレー帯は黒から白へ、限られた色を
規則的に並べた階調です。
左右には同じ構図を置き、
右だけ各 LUT を強さ 1.0 で適用します。見本は画素値を比較しやすい色票であり、
実写の肌色や質感の最終確認は実素材で行ってください。

一覧の確認画像は `evidence/v1-preset-previews/contact-sheet.png` です。

## 検証（新しい LUT を焼いたら通す）

素材（`assets/`）と違い、LUT は見た目のレビューではなく**実映像に当てたピクセル実測**で見る。

```sh
node --test packages/render-cut/test/output-look.test.mjs
```

このテストが押さえている不変条件:

- LUT 無しとの間にピクセル差が測定可能なだけ出ること（`natural` は意図的に控えめなので、
  H.264 丸め後でも差が残る領域で測る）
- `intensity` が 0〜1 で比例混合されること（0 で完全に無変換へ戻る）
- LUT 未指定時のフィルタチェーンが従来と一致すること（非回帰）

加えて**人物の肌色が破綻しないか**を実素材で目視する。強い色転換を持つ LUT は
`intensity` 0.5 前後から確認する（`index.jsonl` の `ai_usage` に同じ規律を書く）。

## 由来（2026-07-29）

`catalog/luts/` から移設しました。`catalog/` は「実体を持たない取得先の索引」という契約でしたが、
LUT は実体を持ち、かつ人が選んでコピーするものではなくコードが id で引く表です。素材ライブラリの
`meta.json` を無理に持たせていたため `validate-asset.mjs` が 1 件あたり 8 件の赤を出しており
（`category: "lut"` が enum 外・`knobs` が文字列配列・`license.spdx` が null・`remote: false` なのに
`source` を持つ 等）、移設に合わせて `index.jsonl` へ置き換えています。
