# 機能設計書 45-範囲指定カット

## 概要

本ドキュメントは、StaxRipにおける範囲指定カット機能の設計を記述する。この機能は、複数の範囲を指定して映像をカットする機能であり、No.44「フレームカット」の拡張版である。

### 本機能の処理概要

範囲指定カット機能は、映像から複数の不連続な範囲を同時に抽出する機能である。各範囲を個別に指定し、それらを結合して最終的な映像を生成する。

**業務上の目的・背景**：TV録画には複数回のCM挿入があり、本編が複数のセグメントに分断されていることが多い。範囲指定カット機能は、これらの本編セグメントをすべて指定し、CM部分を除去して連続した映像を生成するために必要である。

**機能の利用シーン**：
- TV録画からの複数CM除去
- 複数チャプターの選択的抽出
- インタビュー映像から特定発言のみ抽出
- プレゼンテーション映像の編集

**主要な処理内容**：
1. PreviewFormで複数のカット範囲を順次指定
2. Rangesリストに複数Rangeを追加
3. 各範囲に対するTrimコード生成
4. 複数Trim結果の結合（++演算子）
5. 音声・字幕の同期カット

**関連システム・外部連携**：
- AviSynth+ Trim ++ 結合演算子
- VapourSynth std.Splice関数
- mkvmerge（--split parts-frames:複数範囲）
- マクロ（%sel_start%, %sel_end%）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | MainForm | 主画面 | カット範囲リストの表示 |
| 2 | PreviewForm | カット指定画面 | 複数範囲の指定・編集 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Ranges | List(Of Range) | Yes | カット範囲のリスト | 各Range: 0 <= Start < End <= SourceFrames |
| CuttingMode | CuttingMode | Yes | カット処理方式 | mkvmerge/NicAudio/DirectShow |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Ranges | List(Of Range) | 複数カット範囲リスト |
| TrimCode | String | 結合されたTrimスクリプトコード |
| CutFrameCount | Integer | 全範囲合計のフレーム数 |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 第1範囲指定
   └─ PreviewFormでStart/End指定 → Range(1)追加
2. 第2範囲指定
   └─ PreviewFormでStart/End指定 → Range(2)追加
3. (繰り返し)
   └─ 必要な範囲すべてを追加
4. Trimコード生成
   └─ Trim(R1.Start, R1.End) ++ Trim(R2.Start, R2.End) ++ ...
5. 音声カット
   └─ mkvmerge --split parts-frames:R1,+R2,+R3...
6. 字幕カット
   └─ mkvmerge --split parts-frames:R1,+R2,+R3...
```

### フローチャート

```mermaid
flowchart TD
    A[範囲指定開始] --> B[第1範囲指定]
    B --> C[Rangesに追加]
    C --> D{追加範囲あり?}
    D -->|Yes| E[次の範囲指定]
    E --> C
    D -->|No| F[Ranges確定]
    F --> G[Trimコード生成]
    G --> H[Trim++結合式生成]
    H --> I[VideoScript適用]
    I --> J[音声カット]
    J --> K[字幕カット]
    K --> L[エンコード実行]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-45-01 | 範囲ソート | Rangesは開始フレーム昇順でソート | 複数範囲追加時 |
| BR-45-02 | 重複禁止 | 範囲の重複は警告 | 範囲追加時 |
| BR-45-03 | 結合順序 | 時系列順に結合 | Trimコード生成時 |
| BR-45-04 | mkvmerge形式 | parts-frames:で複数範囲をカンマ+で区切り | mkvmerge使用時 |

### 計算ロジック

AviSynth Trimコード生成：
```
Trim(Range1.Start, Range1.End) ++ Trim(Range2.Start, Range2.End) ++ ...
```

mkvmerge分割引数：
```
--split parts-frames:{R1.Start}-{R1.End},+{R2.Start}-{R2.End},+{R3.Start}-{R3.End}
```

合計フレーム数：
```
CutFrameCount = Sum(Range.End - Range.Start + 1) for all Ranges
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| RANGES-001 | 範囲重複 | 2つの範囲が重複 | 警告表示、修正を促す |
| RANGES-002 | 範囲逆転 | End < Start | 範囲指定エラー表示 |
| RANGES-003 | 空リスト | Ranges.Count = 0 | カット処理スキップ |

### リトライ仕様

範囲は個別に削除・修正可能

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

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

## パフォーマンス要件

- 範囲追加: 即時応答
- Trimコード生成: 範囲数に比例（通常は即時）

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

- フレーム番号の整数オーバーフロー対策
- mkvmerge引数のエスケープ処理

## 備考

- Ranges.Selectで関数形式クエリ可能
- VapourSynthではstd.Spliceで結合

---

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

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

### 推奨読解順序

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

複数範囲を管理するRangesリストを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Project.vb | `Source/General/Project.vb` | Ranges As List(Of Range)（104行目） |

**読解のコツ**:
- `List(Of Range)` で複数範囲を管理
- 各Rangeオブジェクトは Start と End プロパティを持つ

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

複数範囲のTrim結合を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | GlobalClass.vb | `Source/General/GlobalClass.vb` | UpdateTrim()での ++ 演算子使用 |

**主要処理フロー**:
- AviSynth: `Trim(s1, e1) ++ Trim(s2, e2)` 形式
- VapourSynth: `std.Splice()` 形式

#### Step 3: mkvmergeの複数範囲処理を理解する

mkvmergeでの複数範囲カットを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Misc.vb | `Source/General/Misc.vb` | parts-frames複数範囲生成（1760行目） |

**主要処理フロー**:
- **1760行目**: `p.Ranges.Select(Function(v) v.Start & "-" & v.End).Join(",+")`
- 各範囲を "Start-End" 形式で生成し、",+" で結合

#### Step 4: マクロ展開を理解する

%sel_start%, %sel_end%マクロを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Macro.vb | `Source/General/Macro.vb` | sel_マクロ展開（522-531行目） |

**主要処理フロー**:
- **523行目**: `If proj.Ranges.Count > 0 Then`
- **525行目**: `proj.Ranges(0).Start` で最初の範囲の開始を取得

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

```
PreviewForm (複数範囲指定)
    │
    ├─ Project.Ranges
    │      ├─ Range(0) {Start, End}
    │      ├─ Range(1) {Start, End}
    │      └─ Range(N) {Start, End}
    │
    ├─ GlobalClass.UpdateTrim()
    │      └─ Trim ++ Trim ++ ... 生成
    │
    ├─ Misc.Cut(subtitles)
    │      └─ --split parts-frames:R1,+R2,+R3
    │
    └─ Macro.Expand()
           └─ %sel_start%, %sel_end% 展開
```

### データフロー図

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

範囲1指定 ─────────▶ Range(1)作成 ──────▶ Rangesリスト
範囲2指定 ─────────▶ Range(2)作成 ──────▶     │
範囲N指定 ─────────▶ Range(N)作成 ──────▶     │
    │                      │                         │
    └──────────────────────▶ Trim結合生成 ──────────▶ TrimCode
                               │                         │
                               ▼                         │
                           mkvmerge ────────────▶ カット済み音声/字幕
                               │                         │
                               ▼                         │
                           VideoScript ─────────▶ Trim++フィルタチェーン
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Project.vb | `Source/General/Project.vb` | ソース | Rangesリスト管理（104行目） |
| Misc.vb | `Source/General/Misc.vb` | ソース | 複数範囲のmkvmerge処理（1760行目） |
| Macro.vb | `Source/General/Macro.vb` | ソース | sel_マクロ展開（522-531行目） |
| Audio.vb | `Source/General/Audio.vb` | ソース | 複数範囲の音声カット |
| GlobalClass.vb | `Source/General/GlobalClass.vb` | ソース | UpdateTrim()でTrim結合生成 |
