# 機能設計書 44-フレームカット

## 概要

本ドキュメントは、StaxRipにおけるフレームカット機能の設計を記述する。この機能は、開始フレームと終了フレームを指定して映像の一部を抽出（カット）する機能である。

### 本機能の処理概要

フレームカット機能は、映像の特定範囲を指定してエンコード対象とする機能である。指定した範囲のみがエンコードされ、不要な部分（オープニング、エンディング、CM等）を除去できる。

**業務上の目的・背景**：TV録画やBD/DVDリッピング映像には、本編以外にCM、番組予告、オープニング/エンディングなどの不要部分が含まれることが多い。フレームカット機能は、これらを除去して本編のみをエンコードするために必要である。

**機能の利用シーン**：
- TV録画からCMを除去
- 映画からクレジットを除去
- 複数エピソードを個別にカット
- 特定シーンのみを抽出

**主要な処理内容**：
1. PreviewFormでカット範囲を視覚的に指定
2. 開始フレーム・終了フレームの設定
3. Rangesリストへの範囲追加
4. AviSynth+/VapourSynthのTrimコード生成
5. 音声・字幕の同期カット

**関連システム・外部連携**：
- AviSynth+ Trimフィルタ
- VapourSynth std.Trim関数
- mkvmerge（音声・字幕カット）
- NicAudio（音声カット）
- QSVEnc/VCEEnc（--trim オプション）

**権限による制御**：特になし（全ユーザーが利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | MainForm | 主画面 | カット範囲の表示、TrimCodeの管理 |
| 2 | PreviewForm | カット指定画面 | フレーム位置でのカットポイント指定 |

## 機能種別

映像編集 / フレーム処理 / スクリプト生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Start | Integer | Yes | 開始フレーム番号 | 0 <= Start < SourceFrames |
| End | Integer | Yes | 終了フレーム番号 | Start < End <= SourceFrames |
| CuttingMode | CuttingMode | Yes | カット処理方式 | mkvmerge/NicAudio/DirectShow |

### 入力データソース

- 画面入力（PreviewFormのトラックバー）
- プロジェクト設定（p.Ranges）
- ソース映像メタデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Ranges | List(Of Range) | カット範囲リスト |
| TrimCode | String | 生成されたTrimスクリプトコード |
| CutFrameCount | Integer | カット後の総フレーム数 |
| CutFrameRate | Double | カット後のフレームレート |

### 出力先

- プロジェクト設定（p.Ranges, p.TrimCode）
- VideoScript（Trimフィルタ）
- 音声ファイル（カット後）
- 字幕ファイル（カット後）

## 処理フロー

### 処理シーケンス

```
1. カット範囲指定
   └─ PreviewFormでフレーム位置を指定してRangeを追加
2. Trimコード生成
   └─ g.UpdateTrim()でスクリプトコード生成
3. 映像カット
   └─ VideoScriptにTrimフィルタを追加
4. 音声カット（p.Ranges.Count > 0の場合）
   └─ CuttingModeに応じて処理
       ├─ mkvmerge: --split parts-frames:で分割
       ├─ NicAudio: AVS Trimで処理
       └─ DirectShow: DirectShowSourceで処理
5. 字幕カット
   └─ mkvmergeでparts-frames分割
```

### フローチャート

```mermaid
flowchart TD
    A[カット開始] --> B[PreviewFormで範囲指定]
    B --> C[Range追加]
    C --> D{複数範囲?}
    D -->|Yes| E[Rangesに追加]
    D -->|No| F[単一Range]
    E --> G[Trimコード生成]
    F --> G
    G --> H[VideoScriptに適用]
    H --> I{音声カット必要?}
    I -->|Yes| J{CuttingMode判定}
    I -->|No| M[エンコード実行]
    J -->|mkvmerge| K1[mkvmerge分割]
    J -->|NicAudio| K2[NicAudio処理]
    J -->|DirectShow| K3[DirectShow処理]
    K1 --> L[字幕カット]
    K2 --> L
    K3 --> L
    L --> M
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-44-01 | フレーム境界 | カットはフレーム単位で行われる | 常時 |
| BR-44-02 | 範囲順序 | Rangesは開始フレーム昇順でソート | 複数範囲指定時 |
| BR-44-03 | 音声同期 | 音声は映像フレームに同期してカット | 音声カット時 |
| BR-44-04 | FPS依存 | RangesBasedOnFPSでFPS変更を追跡 | FPS変更時 |

### 計算ロジック

カットフレーム数の計算：
```
CutFrameCount = Sum(Range.End - Range.Start + 1) for all Ranges
```

mkvmerge分割引数：
```
--split parts-frames:{Range1.Start}-{Range1.End},+{Range2.Start}-{Range2.End},...
```

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

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

本機能はデータベースを使用しない。設定はプロジェクトファイル（.srip）に保存される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CUT-001 | 範囲不正 | End < Start | 範囲指定エラーメッセージ表示 |
| CUT-002 | 範囲重複 | Rangesが重複 | 重複警告表示 |
| CUT-003 | 音声カット失敗 | mkvmerge処理エラー | プロセスエラー表示 |
| CUT-004 | 字幕カット失敗 | mkvextract処理エラー | プロセスエラー表示 |

### リトライ仕様

カット範囲は再指定可能

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

該当なし（ファイルベース処理）

## パフォーマンス要件

- カット範囲指定: 即時応答
- 音声カット処理: ソースサイズに依存
- 字幕カット処理: 数秒以内

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

- 外部ツール（mkvmerge等）のパス検証
- ファイルパスのエスケープ処理

## 備考

- NullEncoderの場合はカット処理がスキップされる
- QSVEnc/VCEEncは直接--trimオプションを使用可能

---

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

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

### 推奨読解順序

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

Rangeクラスとプロジェクト設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Project.vb | `Source/General/Project.vb` | Ranges, TrimCode, CutFrameCount, CuttingMode（61-63, 104-105, 152行目） |
| 1-2 | Misc.vb | `Source/General/Misc.vb` | Rangeクラス定義（検索: "Public Class Range"） |

**読解のコツ**:
- `Ranges As List(Of Range)` がカット範囲のコレクション
- `CuttingMode` はEnum型（mkvmerge, NicAudio, DirectShow）

#### Step 2: Trimコード生成を理解する

g.UpdateTrim()メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | GlobalClass.vb | `Source/General/GlobalClass.vb` | UpdateTrim()メソッド |
| 2-2 | FiltersListView.vb | `Source/Controls/FiltersListView.vb` | ShowCodeEditor()でUpdateTrim呼び出し（190行目） |

**主要処理フロー**:
- **190行目**: `g.UpdateTrim(p.Script)` でTrimコード更新

#### Step 3: 音声カット処理を理解する

Audio.Cut()メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Audio.vb | `Source/General/Audio.vb` | Cut()メソッド（247-280行目付近） |

**主要処理フロー**:
- **248行目**: `If p.Ranges.Count = 0` でカット要否判定
- **256-265行目**: CuttingModeによる分岐処理
- **257行目**: `CuttingMode.mkvmerge` の場合 CutMkvmerge呼び出し
- **259行目**: `CuttingMode.NicAudio` の場合 CutNicAudio呼び出し
- **265行目**: `CuttingMode.DirectShow` の場合

#### Step 4: 字幕カット処理を理解する

Subtitles.Cut()メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Misc.vb | `Source/General/Misc.vb` | Cut(subtitles)メソッド（1714-1789行目） |

**主要処理フロー**:
- **1715行目**: `If p.Ranges.Count = 0` でカット要否判定
- **1732行目**: ffmpegで一時aviファイル作成
- **1760行目**: `--split parts-frames:` でmkvmerge分割

#### Step 5: エンコーダー連携を理解する

QSVEnc/VCEEncの--trimオプション使用を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | QSVEnc.vb | `Source/Encoding/QSVEnc.vb` | --trim生成（1361-1362行目） |

**主要処理フロー**:
- **1361行目**: `If p.Ranges.Count > 0 Then`
- **1362行目**: `--trim {Start}:{End},{Start}:{End},...` 形式で生成

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

```
PreviewForm (カット範囲指定)
    │
    ├─ Project
    │      ├─ Ranges (List(Of Range))
    │      ├─ TrimCode (String)
    │      ├─ CutFrameCount (Integer)
    │      └─ CuttingMode (Enum)
    │
    ├─ GlobalClass.UpdateTrim()
    │      └─ VideoScript.Filters += Trim
    │
    ├─ Audio.Cut()
    │      ├─ CutMkvmerge() → mkvmerge --split
    │      ├─ CutNicAudio() → AVS Trim
    │      └─ CutDirectShow()
    │
    └─ Subtitles.Cut()
           └─ mkvmerge --split parts-frames
```

### データフロー図

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

カット範囲指定 ─────▶ Range作成 ────────▶ Rangesリスト
    │                      │                         │
PreviewFormナビ ───▶ フレーム選択 ───────▶ Start/Endフレーム
    │                      │                         │
    └──────────────────────▶ UpdateTrim() ──────────▶ TrimCode
                               │                         │
                               ▼                         │
                           VideoScript ─────────▶ Trimフィルタ適用
                               │                         │
                               ▼                         │
                           Audio.Cut() ─────────▶ カット済み音声
                               │                         │
                               ▼                         │
                           Subtitles.Cut() ─────▶ カット済み字幕
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Project.vb | `Source/General/Project.vb` | ソース | Ranges, TrimCode, CuttingMode定義（61-63, 104-105, 152行目） |
| Macro.vb | `Source/General/Macro.vb` | ソース | %sel_start%, %sel_end%マクロ展開（522-531行目） |
| Audio.vb | `Source/General/Audio.vb` | ソース | 音声カット処理（36, 247-265行目） |
| Misc.vb | `Source/General/Misc.vb` | ソース | 字幕カット処理（1714-1789行目） |
| QSVEnc.vb | `Source/Encoding/QSVEnc.vb` | ソース | --trim引数生成（1361-1362行目） |
| VCEEnc.vb | `Source/Encoding/VCEEnc.vb` | ソース | Dolby Vision RPUトリム処理（205-206行目） |
| FiltersListView.vb | `Source/Controls/FiltersListView.vb` | ソース | UpdateTrim呼び出し（190行目） |
