---
document_type: "architecture_design"
service: "MOMENTRY_CORE"
title: "自實作 ASRX（說話人分離）可行性分析"
date: "2026-04-02"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:

ai_query_hints:
  - "查詢 自實作 ASRX（說話人分離）可行性分析 的內容"
  - "自實作 ASRX（說話人分離）可行性分析 的主要目的是什麼？"
  - "如何操作或實施 自實作 ASRX（說話人分離）可行性分析？"
---

# 自實作 ASRX（說話人分離）可行性分析

**分析日期**: 2026-04-02  
**目標**: 使用聲紋特徵提取實現說話人分離

---

## 🎯 目標定義

**輸入**: 影片音頻（已通過 ASR 轉錄）  
**輸出**: 每個語音段的說話人 ID  
**準確度目標**: 85%+  
**處理時間**: < 5 分鐘（114 分鐘影片）

---

## 📊 技術方案比較

### 方案 1: 聲紋嵌入（Speaker Embedding）⭐

**原理**:
```
音頻 → 聲紋特徵提取 → 嵌入向量 → 聚類 → 說話人 ID
```

**常用模型**:
- **ECAPA-TDNN** (SOTA, 準確度最高)
- **x-vector** (經典，穩定)
- **d-vector** (Google, 輕量)
- **ResNet34** (簡單，快速)

**優點**:
- ✅ 準確度高（85-95%）
- ✅ 成熟方案
- ✅ 有預訓練模型

**缺點**:
- ⚠️ 需要額外模型（50-100MB）
- ⚠️ 需要聚類算法

**實施難度**: ⭐⭐⭐ (中)

---

### 方案 2: 音頻特徵 + 機器學習

**原理**:
```
音頻 → MFCC/Mel 頻譜 → 特徵向量 → ML 模型 → 說話人 ID
```

**特徵提取**:
- MFCC (Mel-frequency cepstral coefficients)
- Mel Spectrogram
- Chroma features
- Spectral contrast

**分類模型**:
- GMM (Gaussian Mixture Model)
- HMM (Hidden Markov Model)
- K-Means 聚類
- DBSCAN 聚類

**優點**:
- ✅ 不需要深度學習模型
- ✅ 輕量級
- ✅ 可解釋性強

**缺點**:
- ❌ 準確度較低（70-80%）
- ❌ 需要手動設計特徵

**實施難度**: ⭐⭐ (低中)

---

### 方案 3: 端到端說話人分離

**原理**:
```
音頻 → 神經網絡 → 說話人標籤（序列到序列）
```

**模型**:
- **SpeakerNet**
- **DiarizationNet**
- **EEND** (End-to-End Neural Diarization)

**優點**:
- ✅ 準確度最高（90%+）
- ✅ 端到端訓練
- ✅ 可處理重疊說話

**缺點**:
- ❌ 模型大（200MB+）
- ❌ 需要大量訓練數據
- ❌ 實施複雜

**實施難度**: ⭐⭐⭐⭐⭐ (高)

---

## 🔍 推薦方案：聲紋嵌入 + 聚類

### 技術架構

```
音頻輸入
    ↓
[1] 語音活動檢測 (VAD)
    ↓
[2] 語音片段提取 (1-3 秒/段)
    ↓
[3] 聲紋特徵提取 (ECAPA-TDNN)
    ↓
[4] 嵌入向量 (192-512 維)
    ↓
[5] 降維 (PCA, 可選)
    ↓
[6] 聚類 (Spectral Clustering / Agglomerative)
    ↓
[7] 說話人 ID 分配
    ↓
輸出結果
```

---

### 核心組件

#### 1. 語音活動檢測 (VAD)

**選項**:
- **WebRTC VAD** (快速，準確)
- **pyannote VAD** (準確，慢)
- **Silero VAD** (準確，快速) ⭐

**推薦**: Silero VAD
- GitHub: https://github.com/snakers4/silero-vad
- 模型大小：~2MB
- 準確度：95%+
- 速度：實時

---

#### 2. 聲紋特徵提取

**選項**:
- **speechbrain** (ECAPA-TDNN) ⭐
- **resemblyzer** (輕量)
- **TorchAudio** (內建模組)

**推薦**: SpeechBrain ECAPA-TDNN
- GitHub: https://github.com/speechbrain/speechbrain
- 模型大小：~80MB
- 嵌入維度：192 維
- 準確度：90%+ (VoxCeleb1)

**程式碼範例**:
```python
from speechbrain.inference.speaker import EncoderClassifier

# 載入模型
classifier = EncoderClassifier.from_hparams(
    source="speechbrain/spkrec-ecapa-voxceleb"
)

# 提取聲紋嵌入
embeddings = classifier.encode_batch(audio_waveform)
# 輸出：[batch_size, 192]
```

---

#### 3. 聚類算法

**選項**:
- **Spectral Clustering** (準確度高) ⭐
- **Agglomerative Clustering** (穩定)
- **DBSCAN** (自動決定聚類數)
- **K-Means** (需要指定 K)

**推薦**: Spectral Clustering
- 準確度高
- 自動決定聚類數
- 適合聲紋數據

**程式碼範例**:
```python
from sklearn.cluster import SpectralClustering

# 計算相似度矩陣
similarity_matrix = cosine_similarity(embeddings)

# 譜聚類
clustering = SpectralClustering(
    n_clusters=None,  # 自動決定
    affinity='precomputed',
    assign_labels='kmeans'
)
speaker_labels = clustering.fit_predict(similarity_matrix)
```

---

## 💻 實作計畫

### 階段 1: 基礎架構（2-3 小時）

**任務**:
1. 安裝依賴
   ```bash
   pip install speechbrain silero-vad scikit-learn
   ```

2. 創建基礎腳本
   - `vad_processor.py` - 語音活動檢測
   - `speaker_encoder.py` - 聲紋特徵提取
   - `speaker_cluster.py` - 聚類算法

3. 測試短影片（2-3 分鐘）

---

### 階段 2: 整合測試（2-3 小時）

**任務**:
1. 整合 VAD + 聲紋 + 聚類
2. 測試長影片（114 分鐘）
3. 優化效能

**預期結果**:
- 準確度：80-85%
- 處理時間：< 10 分鐘

---

### 階段 3: 優化與驗證（2-3 小時）

**任務**:
1. 調整聚類參數
2. 添加後處理（平滑說話人標籤）
3. 與 pyannote.audio 比較準確度

**預期結果**:
- 準確度：85%+
- 處理時間：< 5 分鐘

---

## 📊 預期效能

### 準確度預估

| 場景 | 預期準確度 | 說明 |
|------|-----------|------|
| **雙人對話** | 90-95% | 清晰區分 |
| **三人會議** | 85-90% | 良好區分 |
| **多人會議** | 80-85% | 基本區分 |
| **重疊說話** | 70-80% | 較困難 |

---

### 處理時間預估

**114 分鐘影片**:

| 階段 | 預估時間 | 說明 |
|------|---------|------|
| VAD | ~2 分鐘 | 實時處理 |
| 聲紋提取 | ~5 分鐘 | GPU 加速 |
| 聚類 | ~1 分鐘 | 快速 |
| **總計** | **~8 分鐘** | 7.6x 實時 |

**優化後**（並行處理）:
- **總計**: ~5 分鐘（13x 實時）

---

## 🔧 實作細節

### 腳本結構

```
scripts/
├── asrx_self/
│   ├── __init__.py
│   ├── vad.py              # 語音活動檢測
│   ├── speaker_encoder.py  # 聲紋特徵提取
│   ├── speaker_cluster.py  # 聚類算法
│   ├── post_process.py     # 後處理
│   └── main.py             # 主流程
├── test_asrx_self.py       # 測試腳本
└── compare_asrx.py         # 與 pyannote 比較
```

---

### 主流程程式碼

```python
#!/opt/homebrew/bin/python3.11
"""
自實作 ASRX - 說話人分離
使用聲紋嵌入 + 譜聚類
"""

import torch
import numpy as np
from speechbrain.inference.speaker import EncoderClassifier
from silero_vad import load_silero_vad, read_audio
from sklearn.cluster import SpectralClustering
from sklearn.metrics.pairwise import cosine_similarity

class SelfASRX:
    def __init__(self):
        # 載入 VAD 模型
        self.vad = load_silero_vad()
        
        # 載入聲紋模型
        self.speaker_encoder = EncoderClassifier.from_hparams(
            source="speechbrain/spkrec-ecapa-voxceleb"
        )
    
    def process(self, audio_path):
        """處理音頻文件"""
        
        # 1. VAD - 提取語音片段
        speech_segments = self.extract_speech_segments(audio_path)
        
        # 2. 聲紋特徵提取
        embeddings = []
        for segment in speech_segments:
            emb = self.speaker_encoder.encode_batch(segment)
            embeddings.append(emb)
        
        embeddings = np.vstack(embeddings)  # [n_segments, 192]
        
        # 3. 譜聚類
        similarity = cosine_similarity(embeddings)
        
        # 自動決定聚類數（使用特徵值間隙）
        n_speakers = self.estimate_n_speakers(similarity)
        
        clustering = SpectralClustering(
            n_clusters=n_speakers,
            affinity='precomputed',
            random_state=42
        )
        speaker_labels = clustering.fit_predict(similarity)
        
        # 4. 後處理（平滑標籤）
        speaker_labels = self.smooth_labels(speaker_labels)
        
        return speaker_labels, n_speakers
    
    def extract_speech_segments(self, audio_path):
        """使用 VAD 提取語音片段"""
        # 實作 VAD 邏輯
        pass
    
    def estimate_n_speakers(self, similarity):
        """估計說話人數量"""
        # 使用特徵值間隙方法
        pass
    
    def smooth_labels(self, labels, window=3):
        """平滑說話人標籤"""
        # 中值濾波
        pass

if __name__ == "__main__":
    asrx = SelfASRX()
    labels, n_speakers = asrx.process("audio.wav")
    print(f"檢測到 {n_speakers} 個說話人")
    print(f"標籤：{labels}")
```

---

## 📈 與現有方案比較

| 方案 | 準確度 | 處理時間 | 模型大小 | 實施難度 |
|------|--------|---------|---------|---------|
| **pyannote.audio** | 90-95% | ~10 分鐘 | ~100MB | ⭐ (簡單) |
| **自實作 (ECAPA)** | 85-90% | ~5 分鐘 | ~80MB | ⭐⭐⭐ (中) |
| **自實作 (MFCC)** | 70-80% | ~3 分鐘 | ~10MB | ⭐⭐ (低中) |
| **Face + ASR** | 66% | ~2 分鐘 | 無額外 | ⭐ (簡單) |

---

## ✅ 可行性評估

### 技術可行性：✅ 高

- ✅ 有成熟開源模型
- ✅ 有預訓練權重
- ✅ 技術文檔完善

### 經濟可行性：✅ 高

- ✅ 開源免費
- ✅ 不需要雲端 API
- ✅ 本地運行

### 時間可行性：⚠️ 中

- ⏱️ 實施時間：6-9 小時
- ⏱️ 測試時間：2-3 小時
- ⏱️ 優化時間：2-3 小時
- **總計**: 10-15 小時

### 準確度可行性：✅ 高

- ✅ 預期 85-90%
- ✅ 接近 pyannote.audio（90-95%）
- ✅ 遠勝 Face+ASR（66%）

---

## 🎯 最終建議

### 推薦實施

**理由**:
1. ✅ 準確度可達 85-90%
2. ✅ 處理時間 5-8 分鐘
3. ✅ 不需要 HuggingFace token
4. ✅ 完全本地運行
5. ✅ 可自定義優化

**實施步驟**:
1. 安裝 speechbrain + silero-vad
2. 創建基礎腳本
3. 測試短影片
4. 優化長影片
5. 與 pyannote 比較

---

### 不推薦的情況

**如果**:
- ❌ 需要 95%+ 準確度
- ❌ 需要處理重疊說話
- ❌ 時間非常緊張（<1 小時）

**建議**: 使用 pyannote.audio（需 HuggingFace token）

---

## 📋 下一步行動

### 立即實施

```bash
# 1. 安裝依賴
pip install speechbrain silero-vad scikit-learn

# 2. 創建目錄結構
mkdir -p scripts/asrx_self

# 3. 創建基礎腳本
# (見上方程式碼範例)

# 4. 測試
python3 scripts/asrx_self/main.py test_audio.wav
```

### 預期時間表

| 時間 | 任務 | 交付 |
|------|------|------|
| 第 1-2 小時 | 安裝 + 基礎架構 | 可運行腳本 |
| 第 3-4 小時 | 整合測試 | 短影片結果 |
| 第 5-6 小時 | 長影片測試 | 長影片結果 |
| 第 7-8 小時 | 優化 + 文檔 | 完整報告 |

---

**結論**: ✅ **建議實施**

自實作 ASRX 在技術、經濟、準確度上都可行，預期可達 85-90% 準確度，處理時間 5-8 分鐘，是值得投入的改進方向。

---

**報告完成**: 2026-04-02
**建議**: 立即開始實施
