---
document_type: "reference_doc"
service: "MOMENTRY_CORE"
title: "處理器模組標準化規範"
date: "2026-04-25"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:
  - "處理器模組標準化規範"
ai_query_hints:
  - "查詢 處理器模組標準化規範 的內容"
  - "處理器模組標準化規範 的主要目的是什麼？"
  - "如何操作或實施 處理器模組標準化規範？"
---

# 處理器模組標準化規範

## 概述

本規範定義 Momentry Core 中處理器模組的標準化架構、接口和實現模式。目標是確保所有處理器模組（ASR、OCR、YOLO、Face、Pose、CUT、ASRX、Caption、Story）遵循一致的設計原則，提高代碼可維護性、可測試性和可擴展性。

## 架構原則

### 1. 分層架構
```
┌─────────────────────────────────────────┐
│            Rust API 層                   │
│  (src/core/processor/*.rs)              │
├─────────────────────────────────────────┤
│         Python 執行層                    │
│   (scripts/*_processor.py)              │
├─────────────────────────────────────────┤
│          AI 模型層                       │
│   (Whisper, YOLO, EasyOCR, etc.)        │
└─────────────────────────────────────────┘
```

### 2. 職責分離
- **Rust 層**: 接口定義、錯誤處理、配置管理、結果解析
- **Python 層**: AI 模型調用、數據處理、中間文件管理
- **模型層**: 特定 AI 任務執行

## Rust 模組規範

### 文件結構
```
src/core/processor/
├── mod.rs              # 模組導出
├── executor.rs         # Python 執行器（共享）
├── asr.rs              # ASR 處理器
├── ocr.rs              # OCR 處理器
├── yolo.rs             # YOLO 處理器
├── face.rs             # 人臉檢測處理器
├── pose.rs             # 姿態檢測處理器
├── cut.rs              # 場景切割處理器
├── asrx.rs             # ASRX 處理器
├── caption.rs          # 字幕生成處理器
└── story.rs            # 故事分析處理器
```

### 模組模板

#### 1. 結果結構定義
```rust
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::time::Duration;

use super::executor::PythonExecutor;
use crate::core::config::processor;

// 主要結果結構
#[derive(Debug, Serialize, Deserialize)]
pub struct ModuleResult {
    // 通用字段
    pub processing_time: Option<f64>,
    pub metadata: Option<serde_json::Value>,
    
    // 模組特定字段
    // ...
}

// 數據單元結構
#[derive(Debug, Serialize, Deserialize)]
pub struct DataUnit {
    // 時間或幀相關字段
    pub start: f64,
    pub end: f64,
    pub frame: u64,
    
    // 數據內容
    // ...
}
```

#### 2. 處理函數模板
```rust
pub async fn process_module(
    video_path: &str,
    output_path: &str,
    uuid: Option<&str>,
) -> Result<ModuleResult> {
    // 1. 初始化執行器
    let executor = PythonExecutor::new()?;
    let script_path = executor.script_path("module_processor.py");
    
    // 2. 記錄日誌
    tracing::info!("[MODULE] Starting processing: {}", video_path);
    
    // 3. 執行 Python 腳本
    executor
        .run(
            "module_processor.py",
            &[video_path, output_path],
            uuid,
            "MODULE",
            Some(Duration::from_secs(*processor::MODULE_TIMEOUT_SECS)),
        )
        .await
        .with_context(|| format!("Failed to run {:?}", script_path))?;
    
    // 4. 讀取並解析結果
    let json_str = std::fs::read_to_string(output_path)
        .context("Failed to read module output")?;
    
    let result: ModuleResult = serde_json::from_str(&json_str)
        .context("Failed to parse module output")?;
    
    // 5. 記錄結果摘要
    tracing::info!(
        "[MODULE] Result: processed {} units",
        result.data_units.len()
    );
    
    Ok(result)
}
```

#### 3. 配置管理
```rust
// 在 src/core/config.rs 中添加
pub mod processor {
    use super::*;
    
    pub static MODULE_TIMEOUT_SECS: Lazy<u64> = Lazy::new(|| {
        env::var("MOMENTRY_MODULE_TIMEOUT")
            .unwrap_or_else(|_| "3600".to_string())
            .parse()
            .unwrap_or(3600)
    });
    
    pub static MODULE_CHUNK_SIZE: Lazy<u64> = Lazy::new(|| {
        env::var("MOMENTRY_MODULE_CHUNK_SIZE")
            .unwrap_or_else(|_| "300".to_string())
            .parse()
            .unwrap_or(300)
    });
}
```

#### 4. 測試規範
```rust
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_result_serialization() {
        // 測試序列化/反序列化
    }
    
    #[test]
    fn test_empty_result() {
        // 測試邊界條件
    }
    
    #[tokio::test]
    async fn test_integration() {
        // 集成測試（可選）
    }
}
```

## Python 腳本規範

### 文件命名
```
scripts/
├── module_processor.py      # 主要處理腳本
├── module_utils.py          # 工具函數（可選）
└── module_debug.py          # 調試腳本（可選）
```

### 腳本模板
```python
#!/opt/homebrew/bin/python3.11
"""
模組處理器 - 標準化模板

功能：執行 [模組名稱] 處理
輸入：視頻文件路徑，輸出文件路徑
輸出：JSON 格式的處理結果
"""

import sys
import json
import os
import argparse
import signal
import tempfile
import time
from pathlib import Path
from typing import Dict, Any, List, Optional

# 環境檢查
def check_environment() -> bool:
    """檢查必要的環境和依賴"""
    try:
        # 檢查必要庫
        import required_library
        return True
    except ImportError as e:
        print(f"ERROR: Missing dependency: {e}", file=sys.stderr)
        return False

# 信號處理
def signal_handler(signum, frame):
    """處理中斷信號"""
    print(f"[MODULE] Received signal {signum}, cleaning up...")
    sys.exit(1)

# 主要處理類
class ModuleProcessor:
    def __init__(self, video_path: str, output_path: str):
        self.video_path = video_path
        self.output_path = output_path
        self.start_time = time.time()
        
    def validate_input(self) -> bool:
        """驗證輸入文件"""
        if not os.path.exists(self.video_path):
            print(f"ERROR: Video file not found: {self.video_path}", file=sys.stderr)
            return False
        return True
    
    def process(self) -> Dict[str, Any]:
        """執行處理邏輯"""
        try:
            # 1. 準備工作目錄
            work_dir = tempfile.mkdtemp(prefix="module_")
            
            # 2. 執行核心處理邏輯
            result = self._core_processing(work_dir)
            
            # 3. 添加元數據
            result["metadata"] = {
                "processing_time": time.time() - self.start_time,
                "video_path": self.video_path,
                "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
                "module_version": "1.0.0"
            }
            
            return result
            
        except Exception as e:
            print(f"ERROR: Processing failed: {e}", file=sys.stderr)
            raise
    
    def _core_processing(self, work_dir: str) -> Dict[str, Any]:
        """核心處理邏輯（模組特定）"""
        # 模組特定實現
        return {
            "data_units": [],
            "summary": {}
        }
    
    def save_result(self, result: Dict[str, Any]):
        """保存結果到文件"""
        with open(self.output_path, 'w', encoding='utf-8') as f:
            json.dump(result, f, ensure_ascii=False, indent=2)
        
        print(f"[MODULE] Result saved to: {self.output_path}")

# 命令行接口
def main():
    parser = argparse.ArgumentParser(description="模組處理器")
    parser.add_argument("video_path", help="輸入視頻文件路徑")
    parser.add_argument("output_path", help="輸出 JSON 文件路徑")
    
    args = parser.parse_args()
    
    # 設置信號處理
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    # 環境檢查
    if not check_environment():
        sys.exit(1)
    
    # 執行處理
    processor = ModuleProcessor(args.video_path, args.output_path)
    
    if not processor.validate_input():
        sys.exit(1)
    
    try:
        result = processor.process()
        processor.save_result(result)
        print(f"[MODULE] Processing completed successfully")
        
    except Exception as e:
        print(f"ERROR: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

### 輸出格式規範
```json
{
  "data_units": [
    {
      "id": "unit_1",
      "start": 0.0,
      "end": 2.5,
      "frame": 0,
      "data": {},
      "confidence": 0.95
    }
  ],
  "summary": {
    "total_units": 1,
    "processing_time": 4.7,
    "average_confidence": 0.95
  },
  "metadata": {
    "video_path": "/path/to/video.mp4",
    "module": "module_name",
    "version": "1.0.0",
    "timestamp": "2026-03-27 10:30:00"
  }
}
```

## 配置標準化

### 環境變量
```
# 超時設置
MOMENTRY_ASR_TIMEOUT=3600
MOMENTRY_OCR_TIMEOUT=7200
MOMENTRY_YOLO_TIMEOUT=7200
MOMENTRY_FACE_TIMEOUT=3600
MOMENTRY_POSE_TIMEOUT=3600
MOMENTRY_CUT_TIMEOUT=3600
MOMENTRY_ASRX_TIMEOUT=3600
MOMENTRY_CAPTION_TIMEOUT=1800
MOMENTRY_STORY_TIMEOUT=1800

# 性能設置
MOMENTRY_MODULE_CHUNK_SIZE=300
MOMENTRY_MODULE_BATCH_SIZE=32
MOMENTRY_MODULE_CACHE_ENABLED=true

# 模型設置
MOMENTRY_MODULE_MODEL=base
MOMENTRY_MODULE_DEVICE=cpu
```

### 配置優先級
1. 命令行參數（最高優先級）
2. 環境變量
3. 配置文件
4. 默認值（最低優先級）

## 錯誤處理規範

### Rust 錯誤處理
```rust
use anyhow::{Context, Result};

pub async fn process_module(...) -> Result<ModuleResult> {
    // 使用 .context() 添加上下文
    executor.run(...)
        .await
        .with_context(|| format!("Failed to run module script"))?;
    
    // 使用 anyhow::bail! 進行錯誤返回
    if !condition {
        anyhow::bail!("Condition not met: {}", reason);
    }
}
```

### Python 錯誤處理
```python
def process(self) -> Dict[str, Any]:
    try:
        # 主要邏輯
        result = self._core_processing()
        return result
    except FileNotFoundError as e:
        print(f"ERROR: File not found: {e}", file=sys.stderr)
        raise
    except RuntimeError as e:
        print(f"ERROR: Runtime error: {e}", file=sys.stderr)
        raise
    except Exception as e:
        print(f"ERROR: Unexpected error: {e}", file=sys.stderr)
        raise
```

### 錯誤分類
1. **輸入錯誤**: 文件不存在、格式不支持、權限問題
2. **配置錯誤**: 缺少依賴、環境變量錯誤、模型文件缺失
3. **運行時錯誤**: 內存不足、超時、模型推理錯誤
4. **輸出錯誤**: 結果解析失敗、文件寫入失敗

## 日誌規範

### Rust 日誌
```rust
tracing::info!("[MODULE] Starting processing: {}", video_path);
tracing::debug!("[MODULE] Processing details: {:?}", details);
tracing::warn!("[MODULE] Warning: {}", warning_message);
tracing::error!("[MODULE] Error: {}", error_message);
```

### Python 日誌
```python
import sys

def log_info(message: str):
    print(f"[MODULE] INFO: {message}", file=sys.stderr)

def log_debug(message: str):
    if os.environ.get("MODULE_DEBUG") == "1":
        print(f"[MODULE] DEBUG: {message}", file=sys.stderr)

def log_error(message: str):
    print(f"[MODULE] ERROR: {message}", file=sys.stderr)
```

## 性能監控

### 指標收集
```rust
pub struct ProcessingMetrics {
    pub start_time: std::time::Instant,
    pub end_time: Option<std::time::Instant>,
    pub memory_usage_mb: f64,
    pub cpu_usage_percent: f64,
    pub items_processed: u64,
    pub items_per_second: f64,
}

impl ProcessingMetrics {
    pub fn new() -> Self {
        Self {
            start_time: std::time::Instant::now(),
            end_time: None,
            memory_usage_mb: 0.0,
            cpu_usage_percent: 0.0,
            items_processed: 0,
            items_per_second: 0.0,
        }
    }
    
    pub fn record_completion(&mut self, items_processed: u64) {
        self.end_time = Some(std::time::Instant::now());
        self.items_processed = items_processed;
        
        let duration = self.end_time.unwrap().duration_since(self.start_time);
        self.items_per_second = items_processed as f64 / duration.as_secs_f64();
    }
}
```

### 性能報告
```json
{
  "performance": {
    "processing_time_seconds": 4.7,
    "memory_usage_mb": 512.5,
    "cpu_usage_percent": 45.2,
    "items_processed": 8,
    "items_per_second": 1.7,
    "throughput_mb_per_second": 10.5
  }
}
```

## 測試規範

### 單元測試
```rust
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_result_structure() {
        // 測試數據結構
    }
    
    #[test]
    fn test_serialization() {
        // 測試序列化
    }
    
    #[test]
    fn test_edge_cases() {
        // 測試邊界條件
    }
}
```

### 集成測試
```rust
#[tokio::test]
async fn test_module_integration() {
    // 使用測試文件進行集成測試
    let test_video = "test_data/sample.mp4";
    let output_file = tempfile::NamedTempFile::new().unwrap();
    
    let result = process_module(test_video, output_file.path().to_str().unwrap(), None)
        .await
        .expect("Processing should succeed");
    
    assert!(!result.data_units.is_empty());
}
```

### Python 測試
```python
def test_module_processor():
    """測試 Python 處理器"""
    processor = ModuleProcessor("test.mp4", "output.json")
    
    # 測試輸入驗證
    assert not processor.validate_input()  # 文件不存在
    
    # 測試處理邏輯
    with tempfile.NamedTemporaryFile() as tmp:
        processor = ModuleProcessor("real_test.mp4", tmp.name)
        result = processor.process()
        assert "data_units" in result
        assert "metadata" in result
```

## 文檔規範

### Rust 文檔
```rust
/// ASR 處理器模組
/// 
/// 提供自動語音識別功能，支持多種語言和大文件處理。
/// 
/// # 示例
/// ```
/// use momentry_core::processor::asr;
/// 
/// let result = asr::process_asr("video.mp4", "output.json", None).await?;
/// println!("識別到 {} 個語音片段", result.segments.len());
/// ```
pub mod asr {
    // ...
}
```

### Python 文檔
```python
"""
模組處理器

提供 [功能描述] 功能。

使用示例：
    python module_processor.py input.mp4 output.json

參數：
    video_path: 輸入視頻文件路徑
    output_path: 輸出 JSON 文件路徑

輸出格式：
    詳見輸出格式規範部分。
"""
```

## 遷移指南

### 現有模組標準化步驟
1. **分析現有代碼**: 識別不符合規範的部分
2. **創建備份**: 備份原始文件
3. **重構 Rust 模組**: 按照模板重構
4. **重構 Python 腳本**: 按照模板重構
5. **更新配置**: 統一配置管理
6. **添加測試**: 補充單元和集成測試
7. **更新文檔**: 更新 API 文檔和使用說明
8. **驗證功能**: 確保功能正常

### 兼容性保證
- 保持現有 API 不變
- 逐步遷移，不中斷現有功能
- 提供遷移工具和文檔

## 附錄

### A. 模組分類

| 模組 | 功能 | 主要技術 | 輸出類型 |
|------|------|----------|----------|
| ASR | 語音識別 | Whisper | 時間段文本 |
| OCR | 文字識別 | EasyOCR | 幀級文字 |
| YOLO | 物體檢測 | YOLOv8 | 幀級物體 |
| Face | 人臉檢測 | OpenCV | 幀級人臉 |
| Pose | 姿態檢測 | OpenPose | 幀級姿態 |
| CUT | 場景切割 | PySceneDetect | 場景邊界 |
| ASRX | 語音增強 | WhisperX | 說話人分離 |
| Caption | 字幕生成 | BLIP | 幀級描述 |
| Story | 故事分析 | 自定義 | 故事結構 |

### B. 性能基準

| 模組 | 平均處理時間 | 內存使用 | CPU 使用 |
|------|--------------|----------|----------|
| ASR | 4.7s (小文件) | 1.2GB | 45% |
| OCR | 12.3s (小文件) | 800MB | 35% |
| YOLO | 8.5s (小文件) | 1.5GB | 60% |
| Face | 3.2s (小文件) | 500MB | 25% |

### C. 常見問題

1. **依賴問題**: 確保 Python 環境正確設置
2. **內存不足**: 調整 chunk_size 參數
3. **超時錯誤**: 增加 timeout 設置或優化算法
4. **模型加載慢**: 啟用模型緩存

---

*版本: 1.0.0*
*更新日期: 2026-03-27*
*負責人: Warren (Technical Lead)*
*狀態: 草案*
