# 機能設計書 36-VapourSynth連携

## 概要

本ドキュメントは、StaxRipアプリケーションにおけるVapourSynthフレームサーバーとの連携機能の設計を記述する。

### 本機能の処理概要

VapourSynth連携機能は、VapourSynthスクリプト（.vpy）を使用してソース映像のデコード、フィルタリング、フレーム処理を行う機能である。Pythonベースのスクリプティング環境を提供し、AviSynth+と並ぶもう一つのフレームサーバーオプションとして機能する。

**業務上の目的・背景**：VapourSynthはPythonベースの次世代フレームサーバーであり、64bit環境での安定動作、より柔軟なスクリプティング、色空間処理の正確性等の利点がある。特にHDR/高ビット深度映像の処理では優れた結果を得られる。

**機能の利用シーン**：
- HDR映像のトーンマッピング処理
- 高ビット深度（10bit/12bit/16bit）映像の処理
- Python機能を活用した高度なフィルタ処理
- モダンなプラグイン（libplacebo、neo_f3kdb等）の使用

**主要な処理内容**：
1. ScriptEngine.VapourSynthの設定とスクリプト生成
2. フィルタプロファイル（VapourSynthProfiles）の管理
3. プラグイン自動ロードコード（core.std.LoadPlugin）の生成
4. vspipeを通じたフレーム供給
5. set_output()によるクリップ出力設定

**関連システム・外部連携**：VapourSynthランタイム（vapoursynth.dll）、vspipe.exe、各種プラグイン。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | MainForm | 主画面 | lgbFiltersでフィルタ一覧表示（VS Filters）|
| 3 | CropForm | 参照画面 | クロップ値の設定（VapourSynthスクリプトに反映） |
| 8 | PreviewForm | 参照画面 | VapourSynthスクリプトのプレビュー表示 |
| 22 | CodeEditor | 参照画面 | スクリプトの直接編集 |

## 機能種別

フレームサーバー連携 / スクリプト生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| p.Script.Engine | ScriptEngine | Yes | VapourSynthを指定 | ScriptEngine.VapourSynth |
| p.Script.Filters | List(Of VideoFilter) | Yes | フィルタのリスト | Source フィルタが必須 |
| s.VapourSynthProfiles | List(Of FilterCategory) | No | フィルタプロファイル | - |
| s.LoadVapourSynthPlugins | Boolean | No | プラグイン自動ロードの有効化 | デフォルト: True |

### 入力データソース

- p.Script: プロジェクトのビデオスクリプト設定
- s.VapourSynthProfiles: アプリケーション設定のフィルタプロファイル
- VapourSynthFilterProfileDefaults.txt: 埋め込みリソースのデフォルトプロファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| .vpy ファイル | テキストファイル | 生成されたVapourSynthスクリプト |
| ServerInfo | オブジェクト | フレームサーバーから取得した映像情報 |

### 出力先

- p.TempDir/{base}.vpy: 生成されたスクリプトファイル

## 処理フロー

### 処理シーケンス

```
1. スクリプトエンジン確認
   └─ p.Script.Engine = ScriptEngine.VapourSynth

2. フィルタリストからスクリプト生成
   └─ GetScript(): Filtersからスクリプト文字列を構築

3. マクロ展開
   └─ Macro.Expand(): %crop_left%等のマクロを実際の値に変換

4. VapourSynthスクリプト修正
   └─ ModifyVSScript(): import文、プラグインロード追加

5. set_output()追加確認
   └─ clip.set_output()が存在しない場合は追加

6. スクリプトファイル書き出し
   └─ WriteFileUTF8(): UTF-8エンコーディング

7. フレームサーバー起動
   └─ FrameServerFactory.Create(): vspipe経由でフレーム情報取得

8. 検証と情報取得
   └─ Synchronize(): エラーチェックとServerInfo更新
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{Engine = VapourSynth?}
    B -->|No| C[AviSynth処理へ]
    B -->|Yes| D[Filters取得]
    D --> E[GetScript実行]
    E --> F[各フィルタのScriptを連結]
    F --> G[Macro.Expand]
    G --> H[ModifyVSScript]
    H --> I[import vapoursynth追加]
    I --> J[core = vs.core追加]
    J --> K[プラグインロードコード生成]
    K --> L{set_output存在?}
    L -->|No| M[clip.set_output追加]
    L -->|Yes| N[スキップ]
    M --> O[スクリプト書き出し UTF-8]
    N --> O
    O --> P[FrameServerFactory.Create]
    P --> Q{エラー?}
    Q -->|Yes| R[エラー情報設定]
    Q -->|No| S[ServerInfo取得]
    R --> T[終了]
    S --> T
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-36-01 | Sourceフィルタ必須 | 最初のフィルタはSourceカテゴリであること | スクリプト検証時 |
| BR-36-02 | import自動追加 | スクリプトにimport vapoursynth, coreが含まれない場合は追加 | ModifyVSScript時 |
| BR-36-03 | set_output必須 | .set_output()が存在しない場合は自動追加 | スクリプト生成時 |
| BR-36-04 | UTF-8エンコーディング | VapourSynthスクリプトはUTF-8で保存 | WriteFile時 |
| BR-36-05 | 関数名検出 | core.xxx.FunctionName形式の関数を検出してプラグインをロード | ModifyVSScript時 |
| BR-36-06 | Pythonスクリプト形式 | clip変数を使用したVapourSynth標準形式 | スクリプト出力時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし（ファイルベースの処理）

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | スクリプトエラー | VapourSynthスクリプトの構文エラー | GetError()で取得、UIに表示 |
| - | プラグイン不在 | 必要なプラグインがインストールされていない | LoadPlugin行をコメントアウト |
| - | AbortException | Package.VapourSynth.VerifyOK = False | 処理中断 |

### リトライ仕様

リトライ処理なし

## トランザクション仕様

ファイル操作のためトランザクション管理なし

## パフォーマンス要件

- スクリプト同期は必要に応じて実行（LastCode比較による最適化）
- フレームサーバーはUsing文で適切に破棄

## セキュリティ考慮事項

- スクリプト内のパスは適切にエスケープ
- プラグインパスはPackage管理システムで検証済みのもののみ使用

## 備考

- VapourSynthは64bit専用
- Pythonランタイムとの依存関係あり

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

VideoScriptクラスのVapourSynth関連プロパティを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | VideoScript.vb | `Source/Video/VideoScript.vb` | IsVapourSynthプロパティ（39-43行目） |
| 1-2 | VideoScript.vb | `Source/Video/VideoScript.vb` | FileTypeプロパティ（45-49行目）- "vpy"を返す |

**読解のコツ**: IsVapourSynthはEngine = ScriptEngine.VapourSynthをチェック、FileTypeは"vpy"を返す。

#### Step 2: VapourSynthスクリプト修正を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | VideoScript.vb | `Source/Video/VideoScript.vb` | ModifyVSScript()メソッド（346-372行目） |
| 2-2 | VideoScript.vb | `Source/Video/VideoScript.vb` | GetVsPortableAutoLoadPluginCode()（327-344行目） |

**主要処理フロー**:
- **352-358行目**: import文とcore定義が存在しない場合の追加
- **360-361行目**: SourceFileLoader importの追加
- **367-369行目**: set_output()が存在しない場合の追加

#### Step 3: プラグインロードコード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | VideoScript.vb | `Source/Video/VideoScript.vb` | ModifyVSScript(ByRef script, ByRef code)メソッド（374-400行目） |
| 3-2 | VideoScript.vb | `Source/Video/VideoScript.vb` | WriteVSCode()メソッド（402-431行目） |
| 3-3 | VideoScript.vb | `Source/Video/VideoScript.vb` | FindFunctionsVS()メソッド（578-610行目） |

**主要処理フロー**:
- **374行目**: 関数名検出開始
- **376-399行目**: プラグインとフィルタ名のマッチング
- **402-431行目**: core.std.LoadPluginまたはcore.avs.LoadPluginの生成
- **578-610行目**: ドット記法からの関数名抽出

#### Step 4: スクリプト同期を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | VideoScript.vb | `Source/Video/VideoScript.vb` | Synchronize()メソッド（194-319行目） |

**主要処理フロー**:
- **291-292行目**: WriteFileUTF8でUTF-8保存
- **305-313行目**: FrameServerFactory.Createでvspipe起動

#### Step 5: フィルタプロファイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | VideoScript.vb | `Source/Video/VideoScript.vb` | FilterCategory.GetVapourSynthDefaults()（930-936行目） |
| 5-2 | VideoScript.vb | `Source/Video/VideoScript.vb` | GetDefaults()のVapourSynth部分（754-761行目） |

**主要処理フロー**:
- **930-936行目**: 埋め込みリソースからデフォルトプロファイル読み込み
- **754-761行目**: VapourSynthのデフォルトスクリプト

### プログラム呼び出し階層図

```
MainForm
    │
    ├─ FiltersListView
    │      └─ Load(): lgbFilters.Text = "VS Filters"
    │
    └─ p.Script (VideoScript)
           │
           ├─ GetScript()
           │      └─ 各フィルタのScript連結
           │
           ├─ GetFullScript()
           │      └─ Macro.Expand() + ModifyScript()
           │
           ├─ ModifyVSScript()
           │      ├─ import追加
           │      ├─ core定義追加
           │      ├─ FindFunctionsVS()
           │      ├─ WriteVSCode()
           │      │      └─ core.std.LoadPlugin
           │      └─ set_output()追加
           │
           └─ Synchronize()
                  ├─ WriteFileUTF8()
                  └─ FrameServerFactory.Create()
                         └─ vspipe経由でServerInfo取得
```

### データフロー図

```
[入力]                          [処理]                              [出力]

p.Script.Filters ───────────────▶ GetScript() ──────────────────▶ スクリプト文字列
      │                               │
      ▼                               │
VideoFilter.Script                    │
      │                               ▼
      │                         Macro.Expand()
      │                               │
      │                               ▼
      │                      ModifyVSScript()
      │                               │
      │                    ┌──────────┴──────────┐
      │                    ▼                     ▼
      │              import追加           プラグインロード
      │                    │                     │
      │                    ▼                     │
      │              core定義追加                │
      │                    │                     │
      │                    ▼                     ▼
      │           set_output()追加     core.std.LoadPlugin
      │                    │                     │
      │                    └──────────┬──────────┘
      │                               │
      │                               ▼
      └────────────────────────▶ WriteFileUTF8()
                                      │
                                      ▼
                                .vpy ファイル
                                      │
                                      ▼
                          FrameServerFactory.Create()
                                      │
                                      ▼
                              vspipe経由でServerInfo
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| VideoScript.vb | `Source/Video/VideoScript.vb` | ソース | VideoScript、VapourSynth関連メソッドの定義 |
| FiltersListView.vb | `Source/Controls/FiltersListView.vb` | ソース | フィルタ一覧UIコントロール |
| FrameServerHelp.vb | `Source/Video/FrameServerHelp.vb` | ソース | フレームサーバーヘルパー |
| Package.vb | `Source/General/Package.vb` | ソース | VapourSynth、vspipeパッケージ定義 |
| Macro.vb | `Source/General/Macro.vb` | ソース | マクロ展開処理 |
| VapourSynthFilterProfileDefaults.txt | `埋め込みリソース` | リソース | デフォルトフィルタプロファイル |
