# 機能設計書 28-MKV Mux

## 概要

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

### 本機能の処理概要

MKV Mux機能は、エンコード済みビデオ、オーディオ、字幕を含む複数のストリームをMKV（Matroska）コンテナにマルチプレクスする機能である。mkvmergeツールを使用して、高度なメタデータ設定（チャプター、タグ、添付ファイル等）をサポートする。

**業務上の目的・背景**：MKVは柔軟性の高いコンテナ形式であり、複数のビデオ/オーディオ/字幕トラック、チャプター、カバーアート、フォント等の添付ファイルを格納できる。アニメ、映画などの配布形式として広く使用されている。

**機能の利用シーン**：
- 複数の音声トラック（日本語/英語）を含むMKV作成
- 複数の字幕トラックを含むMKV作成
- チャプター情報を埋め込んだMKV作成
- カバーアートやフォントを添付したMKV作成

**主要な処理内容**：
1. ビデオ、オーディオ、字幕ファイルの収集
2. mkvmergeコマンドライン構築
3. メタデータ（タイトル、言語、フラグ等）設定
4. チャプター、タグ、添付ファイルの追加
5. Mux実行とログ出力

**関連システム・外部連携**：
- mkvmerge: MKVToolNixのMuxツール

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | MuxerForm | 主画面 | MKV Mux設定、トラック編集 |
| 1 | MainForm | 参照画面 | Muxer選択 |

## 機能種別

ファイル合成 / データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| VideoFile | String | Yes | ビデオファイルパス | ファイル存在 |
| AudioTracks | List(Of AudioProfile) | No | オーディオトラックリスト | - |
| Subtitles | List(Of Subtitle) | No | 字幕リスト | - |
| ChapterFile | String | No | チャプターファイル（txt/xml） | ファイル存在 |
| TagFile | String | No | タグファイル（xml） | ファイル存在 |
| CoverFile | String | No | カバーアート（jpg/png） | ファイル存在 |
| Attachments | List(Of String) | No | 添付ファイルリスト | 各ファイル存在 |
| Title | String | No | 出力ファイルタイトル | - |
| VideoTrackName | String | No | ビデオトラック名 | - |
| VideoTrackLanguage | Language | No | ビデオトラック言語 | - |
| DAR | String | No | アスペクト比設定 | - |
| TimestampsFile | String | No | タイムスタンプファイル | - |

### 対応入力形式

```
Video: avi, wav, ivf, obu, mp4, m4v, m4a, aac, flv, mov,
       264, h264, avc, 265, h265, hevc, hvc,
       ac3, ec3, eac3, thd+ac3, thd, mkv, mka, webm,
       mp2, mpa, mp3, ogg, ogm, dts, dtsma, dtshr, dtshd,
       mpg, m2v, mpv, vob, mpeg, ts, m2ts, opus, flac
```

### 入力データソース

- エンコード済みファイル（p.VideoEncoder.OutputPath）
- オーディオファイル（p.AudioTracks、p.AudioFiles）
- 字幕ファイル（Muxer.Subtitles）
- プロジェクト設定（p.TempDir内のファイル自動検出）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| TargetFile | String | 出力MKVファイルパス |

### 出力先

- 指定された出力ファイル（p.TargetFile）

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ Muxer.Init()でチャプター、字幕、添付ファイルを自動検出

2. タグファイル生成
   └─ WriteTagfile()でXML形式のタグファイル生成

3. コマンドライン構築
   └─ GetArgs()でmkvmergeコマンドライン生成

4. Mux実行
   └─ Proc経由でmkvmerge起動

5. 結果確認
   └─ 出力ファイル存在確認、MediaInfo出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Muxer.Init]
    B --> C[チャプター/字幕/添付検出]
    C --> D{Tags存在?}
    D -->|Yes| E[WriteTagfile]
    D -->|No| F[GetArgs構築]
    E --> F
    F --> G[ビデオオプション追加]
    G --> H[オーディオオプション追加]
    H --> I[字幕オプション追加]
    I --> J[チャプター/タグ/添付追加]
    J --> K[mkvmerge実行]
    K --> L{出力存在?}
    L -->|Yes| M[MediaInfo出力]
    L -->|No| N[エラーログ]
    M --> Z[終了]
    N --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | 自動検出 | 一時ディレクトリ内のchapters/timestamps/tagsファイルを自動検出 | Init()実行時 |
| BR-28-02 | 添付ファイル | attachment_プレフィックスのファイルを自動添付 | AddAttachmentsToMuxer=True |
| BR-28-03 | カバー自動 | cover.jpg/png/bmpを自動検出して添付 | ファイル存在時 |
| BR-28-04 | チャンク結合 | 複数チャンクエンコード時は + で結合 | GetChunks() > 1 |
| BR-28-05 | カット処理 | NullEncoder+Ranges時は--split parts-framesを使用 | Ranges存在時 |

### mkvmergeコマンドライン構造

```
mkvmerge -o {output}
  [--language 0:{lang}]
  [--track-name "0:{name}"]
  [--aspect-ratio 0:{dar}]
  [--default-duration 0:{fps}fps]
  [--timestamps 0:{timestamps}]
  {video}
  [+ {chunk2} + {chunk3} ...]

  [--no-video --no-subs --no-chapters ...]
  [--audio-tracks {id}]
  [--language {id}:{lang}]
  [--track-name "{id}:{name}"]
  [--sync {id}:{delay}]
  [--default-track-flag {id}:{0|1}]
  {audio}

  [字幕オプション...]

  [--chapters {chapterfile}]
  [--attach-file {cover}]
  [--title "{title}"]
  [--split parts-frames:{ranges}]
  [--global-tags {tagfile}]
  [--engage append_and_split_flac]
  [--ui-language en]
  [{additional}]
  [--attachment-name {name} --attach-file {attachment}]
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-28-01 | 出力失敗 | MKV出力ファイルが生成されない | エラーログ出力 |
| E-28-02 | 警告 | mkvmerge終了コード1（警告あり） | 警告として続行 |

### リトライ仕様

リトライ処理なし。mkvmerge終了コード0または1を許容。

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

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

## パフォーマンス要件

- Mux処理は高速（ストリームコピー）
- 処理時間は入力ファイルサイズに依存

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

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

## 備考

MKV特有機能:
- **Compression**: zlib/none/autoで字幕圧縮を制御
- **Engage**: append_and_split_flacでFLAC結合時の互換性確保
- **Global Tags**: NFOファイルからのメタデータ自動取得

---

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

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

### 推奨読解順序

#### Step 1: クラス構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Muxer.vb | `Source/General/Muxer.vb` | Muxer基底クラス（12-291行目） |
| 1-2 | Muxer.vb | `Source/General/Muxer.vb` | MkvMuxer クラス（624-986行目） |

**読解のコツ**: MkvMuxerはMuxer基底クラスを継承。OutputExt="mkv"を返す。

#### Step 2: 初期化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Muxer.vb | `Source/General/Muxer.vb` | Muxer.Init()（157-276行目）- 自動検出 |
| 2-2 | Muxer.vb | `Source/General/Muxer.vb` | MkvMuxer.Init()（651-668行目）- カバー追加 |

**主要処理**:
- NFOファイルからタグ取得（165-176行目）
- 字幕自動検出（178-221行目）
- チャプター/タイムスタンプ検出（223-259行目）
- 添付ファイル検出（248-258行目）

#### Step 3: コマンドライン生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Muxer.vb | `Source/General/Muxer.vb` | MkvMuxer.GetArgs()（720-896行目） |
| 3-2 | Muxer.vb | `Source/General/Muxer.vb` | AddAudioArgs()（899-966行目） |

**主要処理フロー**:
1. 出力パス設定（721行目）
2. ビデオトラック設定（726-777行目）
3. オーディオトラック設定（779-785行目）
4. 字幕トラック設定（789-819行目）
5. チャプター設定（821-861行目）
6. タグ/添付ファイル設定（863-894行目）

#### Step 4: Mux実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Muxer.vb | `Source/General/Muxer.vb` | MkvMuxer.Mux()（670-689行目） |

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

```
MkvMuxer.Mux()
    │
    ├─ WriteTagfile()
    │      └─ Tags → XML形式のタグファイル生成
    │
    ├─ GetArgs()
    │      ├─ -o {output}
    │      ├─ ビデオオプション
    │      │      ├─ --language, --track-name
    │      │      ├─ --aspect-ratio
    │      │      └─ --default-duration
    │      │
    │      ├─ AddAudioArgs() [各オーディオ]
    │      │      ├─ --audio-tracks
    │      │      ├─ --language, --track-name
    │      │      ├─ --aac-is-sbr
    │      │      ├─ --reduce-to-core
    │      │      └─ --sync (delay)
    │      │
    │      ├─ 字幕オプション
    │      │      ├─ --subtitle-tracks
    │      │      ├─ --language, --track-name
    │      │      └─ --default/forced/commentary flags
    │      │
    │      ├─ --chapters
    │      ├─ --attach-file (cover)
    │      ├─ --title
    │      ├─ --split parts-frames (カット時)
    │      ├─ --global-tags
    │      ├─ --engage append_and_split_flac
    │      └─ --attachment-name / --attach-file
    │
    └─ Proc.Start()
           └─ mkvmerge実行
```

### データフロー図

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

ビデオファイル     ───▶   GetArgs()             ───▶   mkvmergeコマンド
オーディオ[]               コマンドライン構築            ライン
字幕[]                                                    │
      │                                                    ▼
チャプター         ───▶   WriteTagfile()        ───▶   _tags.xml
タグ[]                    XML生成                        │
      │                                                    │
カバー             ───▶                                   │
添付ファイル[]                                             │
      │                                                    ▼
      └──────────────────────────────────────────▶   mkvmerge
                                                          │
                                                          ▼
                                                     MKVファイル
                                                     (p.TargetFile)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Muxer.vb | `Source/General/Muxer.vb` | ソース | Muxer基底クラス、MkvMuxer |
| MuxerForm.vb | `Source/Forms/MuxerForm.vb` | ソース | MKV Mux設定UI |
| Package.vb | `Source/General/Package.vb` | ソース | mkvmergeパッケージ定義 |
| MediaInfo.vb | `Source/General/MediaInfo.vb` | ソース | 出力ファイル情報取得 |
