# 機能設計書 25-字幕抽出

## 概要

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

### 本機能の処理概要

字幕抽出機能は、コンテナファイル（MKV、MP4、M2TS等）から字幕ストリームを抽出して個別ファイルとして保存する機能である。対応形式はSRT、ASS/SSA、VobSub（IDX+SUB）、PGS（SUP）など。

**業務上の目的・背景**：動画変換において、元ファイルに埋め込まれた字幕を抽出し、編集や別形式への変換、または別のMuxerでの再合成に使用する。特にBlu-rayソースのPGS字幕を抽出してSRTに変換する、または複数言語の字幕を選択的に抽出するケースが多い。

**機能の利用シーン**：
- MKVファイルから特定言語の字幕のみ抽出する場合
- Blu-rayソースからPGS字幕を抽出してOCR変換する場合
- 字幕を編集してから再合成する場合
- 異なる字幕形式に変換する前処理として

**主要な処理内容**：
1. ソースファイルの字幕ストリーム情報をMediaInfoで取得
2. mkvextract/ffmpegで字幕ストリームを抽出
3. 抽出した字幕をSubtitleオブジェクトとして管理
4. Muxer.Init()で自動検出してMuxerに追加

**関連システム・外部連携**：
- mkvextract: MKVからの字幕抽出
- ffmpeg: 汎用字幕抽出
- MediaInfo: 字幕ストリーム情報取得

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | StreamDemuxForm | 主画面 | 字幕ストリーム選択・抽出設定 |
| 9 | MuxerForm | 参照画面 | 抽出した字幕の確認・編集 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SourceFile | String | Yes | 字幕を含むソースファイルパス | ファイル存在、対応形式 |
| SubtitleMode | SubtitleMode | No | 字幕処理モード | Enum値チェック |
| PreferredSubtitles | String | No | 優先字幕言語（カンマ区切り） | 言語コード |

### SubtitleMode Enum

| 値 | 説明 |
|-----|------|
| Disabled | 字幕処理を無効化 |
| PreferredNoMux | 優先言語を抽出するがMuxしない |
| Preferred | 優先言語を抽出してMux |
| All | 全字幕を抽出してMux |
| Dialog | ダイアログで個別選択 |

### 入力データソース

- ソースファイル（MKV、MP4、M2TS等）
- プロジェクト設定（p.SubtitleMode、p.PreferredSubtitles）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ExtractedSubtitle | Subtitle | 抽出された字幕オブジェクト |
| SubtitleFile | String | 抽出された字幕ファイルパス |

### 出力先

- ファイルシステム: 一時ディレクトリに字幕ファイル出力
- Muxer.Subtitles: 字幕オブジェクトリスト

## 処理フロー

### 処理シーケンス

```
1. ソースファイル分析
   └─ MediaInfo.GetSubtitles()で字幕ストリーム一覧取得

2. 抽出対象決定
   └─ SubtitleMode/PreferredSubtitlesに基づきフィルタリング

3. 字幕抽出実行
   └─ mkvextract または ffmpeg で抽出

4. Subtitleオブジェクト生成
   └─ Subtitle.Create()でオブジェクト生成

5. Muxerへの登録
   └─ Muxer.Subtitles.Add()で追加
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SubtitleMode?}
    B -->|Disabled| Z[終了]
    B -->|他| C[MediaInfo.GetSubtitles]
    C --> D{字幕あり?}
    D -->|No| Z
    D -->|Yes| E[PreferredSubtitles判定]
    E --> F{抽出対象あり?}
    F -->|No| Z
    F -->|Yes| G{ソース形式?}
    G -->|MKV| H[mkvextract実行]
    G -->|他| I[ffmpeg実行]
    H --> J[Subtitle.Create]
    I --> J
    J --> K[Muxer.Subtitles.Add]
    K --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-25-01 | 言語フィルタ | PreferredSubtitles指定時は該当言語のみ抽出 | PreferredSubtitles != "" |
| BR-25-02 | 全字幕抽出 | SubtitleMode=Allの場合は全字幕抽出 | SubtitleMode=All |
| BR-25-03 | 自動検出 | Muxer.Init()で一時ディレクトリの字幕を自動検出 | 常時 |
| BR-25-04 | Forced検出 | ファイル名に"forced"を含む場合はForcedフラグ設定 | ファイル名判定 |

### 対応字幕形式

| 形式 | 拡張子 | CodecString | 備考 |
|-----|-------|-------------|------|
| SubRip | .srt | UTF-8, SubRip | テキスト字幕 |
| Advanced SubStation Alpha | .ass | ASS | スタイル付きテキスト |
| SubStation Alpha | .ssa | SSA | スタイル付きテキスト |
| VobSub | .idx + .sub | VobSub | 画像字幕（DVD） |
| PGS | .sup | S_HDMV/PGS, PGS | 画像字幕（Blu-ray） |
| DVB Subtitle | .mks | S_DVBSUB | 放送用字幕 |

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-25-01 | 字幕なし | ソースファイルに字幕が含まれない | 警告なしでスキップ |
| E-25-02 | 抽出失敗 | mkvextract/ffmpegが失敗 | エラーログ出力、続行 |
| E-25-03 | 形式未対応 | 未対応の字幕形式 | スキップ |

### リトライ仕様

リトライ処理なし。

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

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

## パフォーマンス要件

- 抽出時間: 字幕サイズに依存（通常は高速）
- ディスク使用: 抽出字幕ファイル分の一時使用

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

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

## 備考

字幕形式の判定について:
- MediaInfoのCodecStringまたはFormatで形式を特定
- 拡張子だけでなく内部形式を確認して適切な出力形式を決定

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Misc.vb | `Source/General/Misc.vb` | Subtitle クラス（1482-1682行目） |
| 1-2 | Misc.vb | `Source/General/Misc.vb` | Subtitle.Ext プロパティ（1526-1566行目）- 形式判定 |
| 1-3 | Misc.vb | `Source/General/Misc.vb` | Subtitle.Create() 静的メソッド（1576-1682行目） |

**読解のコツ**: SubtitleクラスはPath、Language、CodecString等を保持。Extプロパティで適切な拡張子を返す。

#### Step 2: 字幕情報取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MediaInfo.vb | `Source/General/MediaInfo.vb` | GetSubtitles()メソッド - 字幕ストリーム一覧取得 |
| 2-2 | MediaInfo.vb | `Source/General/MediaInfo.vb` | GetSubtitleCount()メソッド |

#### Step 3: 抽出処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Demux.vb | `Source/General/Demux.vb` | 字幕Demux処理 |
| 3-2 | StreamDemuxForm.vb | `Source/Forms/StreamDemuxForm.vb` | 字幕選択UI |

#### Step 4: Muxerへの統合を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Muxer.vb | `Source/General/Muxer.vb` | Muxer.Init()内の字幕自動検出（178-221行目） |
| 4-2 | Muxer.vb | `Source/General/Muxer.vb` | Muxer.Subtitles プロパティ（84-97行目） |

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

```
ソースファイル読込
    │
    ├─ MediaInfo.GetSubtitles()
    │      └─ 字幕ストリーム一覧取得
    │
    ├─ StreamDemuxForm
    │      └─ ユーザーによる字幕選択
    │
    └─ Demux処理
           ├─ mkvextract (MKV)
           │      └─ tracks {ID}:{outputPath}
           │
           └─ ffmpeg (その他)
                  └─ -map 0:s:{ID} -c copy {outputPath}

Muxer.Init()
    │
    ├─ 一時ディレクトリ内ファイル検索
    │      └─ FileTypes.SubtitleExludingContainers判定
    │
    └─ Subtitle.Create(filePath)
           └─ Muxer.Subtitles.Add()
```

### データフロー図

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

ソースファイル     ───▶   MediaInfo.GetSubtitles  ───▶   字幕ストリーム情報
(MKV/MP4/M2TS)                                            │
      │                                                    ▼
      │                  SubtitleMode判定        ───▶   抽出対象リスト
      │                  PreferredSubtitles               │
      │                                                    ▼
      │                  mkvextract/ffmpeg      ───▶   字幕ファイル
      │                                                  (.srt/.ass/.sup等)
      │                                                    │
      │                                                    ▼
      │                  Subtitle.Create()      ───▶   Subtitleオブジェクト
      │                                                    │
      │                                                    ▼
      └──────────────────────────────────────────▶   Muxer.Subtitles
                                                          リストに追加
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Misc.vb | `Source/General/Misc.vb` | ソース | Subtitle クラス定義 |
| MediaInfo.vb | `Source/General/MediaInfo.vb` | ソース | GetSubtitles()、字幕情報取得 |
| Demux.vb | `Source/General/Demux.vb` | ソース | 字幕抽出処理 |
| Muxer.vb | `Source/General/Muxer.vb` | ソース | Muxer.Subtitles、Init() |
| StreamDemuxForm.vb | `Source/Forms/StreamDemuxForm.vb` | ソース | 字幕選択UI |
| MuxerForm.vb | `Source/Forms/MuxerForm.vb` | ソース | 字幕設定UI |
