# VJ FX Maker

https://xenoah.github.io/tools/vj-fx-maker/vj-fx-maker.htm

ブラウザ単体で動作する VJ 用エフェクトメーカー。`vj-fx-maker.htm` をダブルクリックで開くだけで起動します。
外部 CDN・ライブラリ・ビルドは一切不要です。

## 起動

```
vj-fx-maker.htm を Chrome / Edge / Firefox など WebGL 対応ブラウザで開く
```

ローカルファイルの読込みやマイク権限を使うため、HTTPS や `file://` ではなくローカルサーバ経由で開くことを推奨:

```
# Python が入っていれば
python -m http.server 8000
# → http://localhost:8000/
```

## 画面構成

```
┌──────────────────────────────────────────────────┐
│ Top: File / Edit / Layer / Effect / Audio / View shortcuts │
├──────────┬───────────────────────┬──────────────┤
│ Left     │   Center              │ Right        │
│ Project  │   Composition         │ Info / Audio │
│ 素材     │   <canvas> preview    │ Preview      │
│ 効果Library                      │ Effects      │
├──────────┴───────────────────────┴──────────────┤
│ Bottom: タイムライン枠 / エフェクト処理順        │
└──────────────────────────────────────────────────┘
```

- After Effects 風の 2 段トップバーに、素材/音声読込、プリセット、録画、MIDI、再生、A/B、XFade、エフェクト追加、Particles、音声入力、PNG、全画面、パネル表示を集約
- 左は **Project**、中央は **Composition**、右は **Info / Audio / Preview / Effects & Presets / Effect Controls**、下は **Timeline**
- プレビュー、タイムライン、レイヤー周辺の右クリックメニューからも、上部バーと同等の再生、In/Out、素材読込、エフェクト追加、複製/削除、録画、PNG、表示切替を実行可能

## 主な機能

### 素材の読み込み
- **ファイル**: 画像 (PNG/JPG/GIF など) または動画 (MP4/WebM など)
- **デモ映像**: 素材未読み込み時は自動で動くデモパターンを表示
- **再生/停止**: 動画の場合に有効

### エフェクト (全 51)
- 左パネルのカテゴリ別ライブラリから `＋` でレイヤーとして追加
- 同じ効果を複数レイヤーとして追加可能
- 右パネルで選択中レイヤーの有効化、複製、削除、パラメータ編集
- 右パネルまたは下タイムラインの ▲▼ ボタンで並び替え (＝処理順を入れ替え)
- 各効果は以下の共通スライダを持つ
  - **amount** … エフェクトの強さ
  - **speed** … 時間的速度 (アニメーション系)
  - **mix** … 元画像とのブレンド率
  - **bpmSync** … BPM 位相による amount 変調量
  - **audio** … 音量レベルによる amount 変調量
  - **fftTrig** … 指定周波数帯トリガーによる amount 変調量
- 一部の効果は固有のスライダ (centerX, angle, color など) を持つ
- **Particles** は density / size / spread / glow / spin / tunnel / streak / style / color を持ち、ネオン粒子、グリッド、トンネル、リング状の VJ 素材風表現を生成可能

### バッジ表記
| バッジ | 意味 |
|---|---|
| 実装 (緑) | フル WebGL 実装、想定通り動作 |
| 簡易 (黄) | 簡略化したシェーダ実装 |
| 監視 (青) | 状態表示専用 (#50 BPM/音量) |

### A/B シーン
- 上ツールバーの **A / B** ボタンで編集対象シーンを切替
- 各シーンは独立したレイヤースタックを持つ
- **XFade** スライダで A/B をブレンド。0=A、1=B、中間でクロスフェード
- プリセットには両シーンとクロスフェーダ位置を保存

### BPM
- 数値直接入力
- `tap` ボタンを 2 回以上連打 (1.6 秒以内) で平均 BPM を自動算出
- 各エフェクトの **bpmSync** スライダで amount を sin 同期させる

### タイムライン
- **再生 / 停止 / 先頭 / Loop**: 上ツールバーから操作
- **duration**: 4〜60秒でコンポジション長を変更
- **mode**: 秒表示 / ビート表示のルーラー切替
- **snap**: off / 1拍 / 半拍 / 8分単位でスクラブ位置を吸着
- **In / Out**: 再生範囲を指定。Loop ON 時は Out 到達で In に戻る
- ルーラーをドラッグすると停止状態でスクラブし、プレビューへ即時反映
- 各エフェクトレイヤーはクリップとして開始/終了範囲を持つ
- クリップ中央ドラッグで範囲ごと移動、左右ハンドルのドラッグで開始/終了を調整
- クリップ範囲外のレイヤーはレンダリングされない
- 音声ファイル読み込み時は波形ピークを解析し、タイムラインルーラー背景へ表示

### キーフレーム
- 右パネルの各パラメータ右にある **◆** で現在時刻へキーを追加
- タイムラインでレイヤーを展開するとパラメータ行とキー点を表示
- キー点をクリックで選択、ドラッグで時刻移動
- 複数キー間は線形補間され、レンダリングへリアルタイム反映
- `Delete` で選択キーを削除、`Ctrl+C` / `Ctrl+V` で選択キーを現在時刻へコピー&ペースト
- パラメータ行の **G** ボタンでグラフ表示に切替
- グラフ上の点は左右ドラッグで時刻、上下ドラッグで値を編集

### Undo / Redo
- レイヤー追加、削除、移動、有効化、クリップ範囲変更、パラメータ変更、キーフレーム操作を履歴化
- スライダーなどの連続入力は短い間隔でまとめて1履歴に圧縮
- 上ツールバーの **Undo / Redo** またはキーボードで操作

### 音声 (Audio Reactive)
- **マイク**: ボタン押下で `getUserMedia({audio:true})` を要求
- **ファイル**: 音声ファイルを読み込んで再生 (スピーカーから音も出る)
- **感度**: 検出レベルにかける線形ゲイン
- 各エフェクトの **audio** スライダで amount を音量で押し上げる
- **FFT Hz / width / threshold**: `AnalyserNode.getByteFrequencyData()` で指定周波数帯の平均レベルを取得し、しきい値で判定
- **edge**: 立ち上がり (`rise`)、立ち下がり (`fall`)、両方 (`both`) からトリガー条件を選択
- 各エフェクトの **fftTrig** スライダで、キックなど特定周波数帯のトリガーに反応させる

### MIDI
- **MIDI ON** で Web MIDI API の入力を有効化
- 各パラメータ右の **M** ボタンで MIDI Learn を開始し、次に入った CC / Note を割当
- CC は 0–127 をパラメータ範囲へ線形マップ
- 選択レイヤーの **MIDI on/off** で Note / CC による有効化制御を割当
- **MIDI key** で Note / CC による `amount` キーフレーム追加を割当
- 左パネルの MIDI セクションで割当一覧を確認・削除

### プリセット
- **保存**: A/B シーン、レイヤー、クリップ範囲、キーフレーム、composition、FFT トリガー設定、MIDI バインドを JSON でダウンロード (`vjfx-preset-*.json`)
- **読込**: JSON ファイル選択でインポート
- **ランダム**: 3〜7 個のレイヤーを無作為に追加、各パラメータとキーフレームを乱数化
- **クリア**: レイヤースタックを空にする

### 録画
- `● 録画` ボタンで In/Out 範囲の録画開始 (canvas.captureStream(60))
- 開始時に In へ移動し、Out 到達で自動停止
- MP4/H.264 を優先し、非対応環境では WebM へ自動フォールバック
- 出力形式に合わせて `vjfx-rec-*.mp4` または `vjfx-rec-*.webm` がダウンロードされる
- 録画中は状態表示と進捗バーを表示
- `PNG` ボタンで現在のフレームを PNG 保存

### 表示
- **全画面** ボタン or `f` キー: プレビューをフルスクリーン
- **パネル隠す** ボタン or `h` キー: UI パネルを隠してプレビューを最大化
- 右クリックメニュー: 操作対象に応じて、再生、In/Out、レイヤー操作、エフェクト追加、録画、PNG、表示切替を表示
- 左 / 右 / 下パネル境界はドラッグでリサイズ可能
- **解像度 scale**: 内部レンダリング解像度を 25–100% に変更 (重い時は下げる)

## 実装エフェクト一覧 (51)

| # | 名前 | 状態 |
|---|---|---|
| 01 | ズーム | 実装 |
| 02 | パン | 実装 |
| 03 | クロップ | 実装 |
| 04 | 回転 | 実装 |
| 05 | ミラー | 実装 |
| 06 | タイル | 実装 |
| 07 | 万華鏡 | 実装 |
| 08 | スプリット | 実装 |
| 09 | PiP | 実装 |
| 10 | ラップスクロール | 実装 |
| 11 | 色相回転 | 実装 |
| 12 | 彩度 | 実装 |
| 13 | コントラスト | 実装 |
| 14 | 明るさ | 実装 |
| 15 | ガンマ | 実装 |
| 16 | 反転 | 実装 |
| 17 | モノクロ | 実装 |
| 18 | グラデーションマップ | 実装 |
| 19 | ポスタライズ | 実装 |
| 20 | LUT風 | 簡易 |
| 21 | グロー | 実装 |
| 22 | エッジグロウ | 実装 |
| 23 | ブルーム | 簡易 |
| 24 | レンズフレア | 簡易 |
| 25 | ライトリーク | 簡易 |
| 26 | ビネット | 実装 |
| 27 | ストロボ | 実装 |
| 28 | フラッシュ | 実装 |
| 29 | ガウスブラー | 実装 |
| 30 | モーションブラー | 実装 |
| 31 | ラジアルブラー | 実装 |
| 32 | ズームブラー | 実装 |
| 33 | 波形歪み | 実装 |
| 34 | レンズ歪み | 実装 |
| 35 | 渦巻き | 実装 |
| 36 | ノイズディスプレイス | 実装 |
| 37 | 液状化ワープ | 簡易 |
| 38 | 画面シェイク | 実装 |
| 39 | RGBシフト | 実装 |
| 40 | 色収差 | 実装 |
| 41 | グリッチ | 簡易 |
| 42 | スライスずれ | 簡易 |
| 43 | ブロックノイズ | 簡易 |
| 44 | ピクセル化 | 実装 |
| 45 | スキャンライン | 実装 |
| 46 | フィルムグレイン | 実装 |
| 47 | VHSノイズ | 簡易 |
| 48 | 残像 / トレイル | 実装 |
| 49 | フィードバック | 実装 |
| 50 | BPM/音量連動 | 監視 |
| 51 | Particles | 実装 |

## キーボード

| キー | 動作 |
|---|---|
| `Space` | 再生 / 停止 |
| `←` / `→` | 1フレーム戻る / 進む |
| `Home` / `End` | 先頭 / 末尾へ移動 |
| `I` / `O` | 現在時刻を In / Out に設定 |
| `Delete` | 選択キーフレーム削除 |
| `Ctrl+C` / `Ctrl+V` | 選択キーフレームのコピー / 貼付 |
| `Ctrl+Z` | Undo |
| `Ctrl+Y` / `Ctrl+Shift+Z` | Redo |
| `f` | 全画面切替 |
| `h` | UI パネル表示切替 |

## 既知の制限

- WebGL1 を前提とした実装。古いモバイル GPU では `for` ループ内のテクスチャタップ数で性能が落ちることがあります。重い場合は **解像度 scale** を 0.5 などに下げてください。
- ブラー / グロー系は単一パスでの近似実装です。本格的な分離畳み込み + ダウンサンプル化はしていません。
- レンズフレア・ライトリーク・VHS ノイズ・液状化ワープは手続き的な簡易表現です (バッジ「簡易」)。
- 動画ファイルそのものの音声は AudioContext へつないでいません。音量連動には別途「音声ファイル」または「マイク」を入力してください。
- FFT トリガーは指定帯域の平均レベルによる判定です。キック抽出などは曲やミックスに応じて **FFT Hz / width / threshold / 感度** の調整が必要です。
- Particles は 1 パスの手続き的シェーダです。密度や解像度を上げると GPU 負荷が上がります。
- Web MIDI API はブラウザ/OS/権限に依存します。非対応ブラウザでは MIDI セクションに unsupported と表示されます。
- 波形表示は読み込んだ音声ファイルのピーク解析であり、動画素材内の音声波形は表示しません。
- グラフエディタは数値パラメータのみ対応です。色パラメータは通常のキー点編集になります。
- MediaRecorder の MP4 出力可否はブラウザ依存です。非対応時は WebM で保存します。
- 効果順を変えるとフィードバック / 残像 (`u_prev`) のループ位置が変わるため、見た目が大きく変化します (これは仕様です)。
- 一部のブラウザでは `file://` から `getUserMedia` がブロックされる場合があります。ローカルサーバ (上記参照) からの起動を推奨します。
- プリセット JSON は `version: 3` の A/B シーン形式で保存します。旧 `version: 1` / `version: 2` の効果プリセットも読込可能です。

## ファイル

| ファイル | 内容 |
|---|---|
| `vj-fx-maker.htm` | アプリ本体 (HTML + CSS + JS の単一ファイル) |
| `vj-fx-maker_readme.md` | このファイル |
