# 機能設計書 23-オーディオカット

## 概要

本ドキュメントは、StaxRipのオーディオカット機能について、その処理内容、入出力仕様、および実装詳細を記載した設計書である。

### 本機能の処理概要

オーディオカット機能は、ビデオのカット編集（トリミング・範囲指定）に連動して、オーディオトラックの該当部分を切り出す機能である。プロジェクトで設定されたRanges（フレーム範囲）に基づき、ffmpegを使用して正確なタイムコードでオーディオをカットする。

**業務上の目的・背景**：動画編集においてビデオの一部を切り出す場合、対応するオーディオも同期してカットする必要がある。特にCM除去、不要シーンの削除、複数セグメントの結合などで本機能が必要となる。

**機能の利用シーン**：
- 放送録画からCM部分を除去する場合
- 映画のオープニング/エンディングをカットする場合
- 複数の範囲を選択して結合する場合

**主要な処理内容**：
1. プロジェクトのRanges設定からカット範囲（フレーム番号）を取得
2. フレーム番号をタイムコード（秒）に変換
3. ffmpegでセグメントごとにオーディオを切り出し
4. 複数セグメントの場合は結合処理

**関連システム・外部連携**：
- FFmpeg: オーディオカット処理エンジン
- AviSynth/VapourSynth: フレームレート情報の取得

**権限による制御**：本機能に権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | MainForm | 主画面 | カット範囲設定（Cutting機能） |
| 15 | PreviewForm | 参照画面 | フレーム範囲の視覚的選択 |

## 機能種別

データ変換 / ファイル操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Ranges | List(Of Range) | Yes | カット範囲（フレーム番号のStart/End） | 空でないこと |
| CutFrameRate | Double | Yes | カット計算用フレームレート | 正の値 |
| SourceFile | String | Yes | ソースオーディオファイルパス | ファイル存在 |

### 入力データソース

- プロジェクト設定（p.Ranges）
- スクリプト情報（p.Script.GetFramerate）
- オーディオプロファイル（AudioProfile.File）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CutAudioFile | String | カット済みオーディオファイルパス |

### 出力先

- ファイルシステム: 一時ディレクトリにカット済みオーディオファイル出力

## 処理フロー

### 処理シーケンス

```
1. Ranges取得
   └─ p.Rangesからフレーム範囲リストを取得

2. タイムコード変換
   └─ 各Range.Start/Endをフレームレートで秒に変換

3. セグメント処理
   └─ 各範囲に対してffmpeg -ss/-toでカット

4. 結合処理（複数範囲時）
   └─ ffmpeg concatで複数セグメントを結合

5. 一時ファイル削除
   └─ 中間セグメントファイルをクリーンアップ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{Ranges存在?}
    B -->|No| Z[終了（カット不要）]
    B -->|Yes| C[フレーム→秒変換]
    C --> D{複数Range?}
    D -->|No| E[単一セグメントカット]
    D -->|Yes| F[複数セグメントカット]
    E --> G[出力ファイル設定]
    F --> H[concatファイル生成]
    H --> I[ffmpeg concat実行]
    I --> J[中間ファイル削除]
    J --> G
    G --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | フレーム同期 | オーディオカット位置はビデオフレームと同期 | 常時 |
| BR-23-02 | 範囲ソート | Rangesは開始フレーム順にソート | 複数Range時 |
| BR-23-03 | オーバーラップ禁止 | 重複する範囲は許可しない | 複数Range時 |

### 計算ロジック

**フレームからタイムコード変換**:
```
StartSeconds = Range.Start / CutFrameRate
EndSeconds = Range.End / CutFrameRate
```

**ffmpegカットコマンド**:
```
ffmpeg -i input.audio -ss {StartSeconds} -to {EndSeconds} -c copy output.audio
```

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-23-01 | 無効範囲 | Start >= End | エラーメッセージ表示 |
| E-23-02 | 出力失敗 | ffmpegが出力ファイル生成に失敗 | ジョブ中断 |

### リトライ仕様

リトライ処理なし。

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

トランザクション制御なし。

## パフォーマンス要件

- 処理時間: -c copy使用時は非常に高速（再エンコードなし）
- ディスク使用: 中間ファイル生成による一時的なディスク使用

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

外部プロセス（ffmpeg）の実行はPackage経由で制御。

## 備考

- カット位置はフレーム単位で指定されるが、オーディオはサンプル単位のため微小なずれが生じる可能性がある
- -c copy使用時はキーフレーム単位での切断となるため、正確なカット位置にはならない場合がある
- 正確なカットが必要な場合は再エンコードが必要

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Misc.vb | `Source/General/Misc.vb` | Range クラス（69-89行目）- Start/End プロパティ |
| 1-2 | Project.vb | `Source/General/Project.vb` | p.Ranges プロパティ - カット範囲リスト |
| 1-3 | Project.vb | `Source/General/Project.vb` | p.CutFrameRate プロパティ - フレームレート |

**読解のコツ**: Rangeクラスはフレーム番号でStart/Endを保持する単純な構造。

#### Step 2: カット処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AudioProfile.vb | `Source/General/AudioProfile.vb` | Cut処理部分（エンコード前にカット適用） |
| 2-2 | Muxer.vb | `Source/General/Muxer.vb` | MkvMuxer.GetArgs()内のRanges処理（871-873行目） |

**主要処理フロー**:
1. Rangesの存在確認
2. フレーム番号を秒に変換
3. ffmpegでセグメントカット
4. 複数セグメントの結合

#### Step 3: ビデオカットとの連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Muxer.vb | `Source/General/Muxer.vb` | --split parts-frames オプション（871-873行目） |

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

```
エンコード処理
    │
    ├─ ビデオエンコード
    │      └─ p.Ranges使用（AviSynth Trim/VapourSynth Trim）
    │
    └─ オーディオ処理
           │
           ├─ AudioProfile.GetCommandLine()
           │      └─ Ranges考慮したカット処理
           │
           └─ Muxer.Mux()
                  └─ MkvMuxer: --split parts-frames
                  └─ 他Muxer: 事前カット済みオーディオ使用
```

### データフロー図

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

p.Ranges          ───▶   フレーム→秒変換     ───▶   タイムコード
(フレーム番号)                                        (ss/to値)
      │                                                  │
      │                                                  ▼
ソースオーディオ   ───▶   ffmpeg              ───▶   セグメント1
ファイル                  -ss {start} -to {end}        セグメント2
                          -c copy                       ...
                                                         │
                                                         ▼
                         ffmpeg concat        ───▶   カット済み
                         (複数セグメント時)           オーディオ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Misc.vb | `Source/General/Misc.vb` | ソース | Range クラス定義 |
| Project.vb | `Source/General/Project.vb` | ソース | Ranges/CutFrameRate プロパティ |
| AudioProfile.vb | `Source/General/AudioProfile.vb` | ソース | オーディオカット処理 |
| Muxer.vb | `Source/General/Muxer.vb` | ソース | Muxer側でのRanges処理 |
| MainForm.vb | `Source/Forms/MainForm.vb` | ソース | カット設定UI |
