---
document_type: "spec"
service: "MOMENTRY_CORE"
title: "CUT Processor (Scene Cut Detection) V1.0.0"
date: "2026-05-03"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
parent: "PROCESSOR_SELECTION_V1.0.0.md"
tags:
  - "momentry"
  - "core"
  - "processor"
  - "cut"
  - "scene-detection"
  - "pyscenedetect"
  - "v1.0.0"
ai_query_hints:
  - "CUT 場景檢測的輸出結構與檔案後綴規則"
  - "CUT 的 cut_count 與 cut_max_duration 用途"
  - "長影片動態調度如何將 Face 移到 ASR 前"
  - "CUT 與 Scene 的執行階段（register 同步）"
  - "CUT 輸出 JSON 結構（start_time/end_time）"
related_documents:
  - "PROCESSORS/SCENE_V1.0.0.md"
  - "PROCESSOR_SELECTION_V1.0.0.md"
  - "PROCESSORS/ASR_V1.0.0.md"
  - "PROCESSORS/FACE_V1.0.0.md"
  - "CHUNK_DEFINITION_V1.0.0.md"
---

# CUT Processor (Scene Cut Detection) V1.0.0

| 項目 | 內容 |
|------|------|
| 建立者 | OpenCode |
| 建立時間 | 2026-05-03 |
| 文件版本 | V1.0 |

**狀態**: ✅ 100% | **模型**: PySceneDetect (ContentDetector) | **GPU**: 否

## 關鍵術語定義

| 術語 | 定義 |
|------|------|
| CUT | 場景切換檢測，使用 PySceneDetect ContentDetector |
| scene boundary | 場景邊界，以 start_time/end_time 定義 |
| cut_count | 場景數量，register 階段寫入 DB |
| cut_max_duration | 最長場景秒數，用於長影片動態調度 |
| ContentDetector | 基於幀差異的場景切換檢測演算法 |

---

## 選型過程

無 ML 模型，基於幀差異的場景切換檢測。門檻值 threshold=27 為實驗最佳值。

---

## 輸出結構

CUT 產出 `{file_uuid}.cut.json`，結構如下：

```json
{
  "scenes": [
    { "start_time": 0.0, "end_time": 120.5 },
    { "start_time": 120.5, "end_time": 245.0 }
  ]
}
```

---

## 執行階段

CUT 在 **register 階段同步執行**（`register_single_file`），不做 worker pipeline 排程。完成後寫入 DB 欄位：
- `cut_done: bool` — 是否完成
- `cut_count: i32` — 場景數量
- `cut_max_duration: f64` — 最長場景秒數

---

## 狀態後綴

| 後綴 | 意義 | 行為 |
|------|------|------|
| `.cut.json` | 完成 | 直接載入使用 |
| `.cut.json.tmp` | 執行中 | 跳過、等待 |
| `.cut.json.err` | 失敗 | 跳過、不重試 |

---

## 長影片動態調度

當 `cut_count ≤ 3 && cut_max_duration > 600s`（如會議紀錄長鏡頭），Worker 自動調整 pipeline 順序：
- **Face 移到 ASR 前面**，先用 face detection 找出人物進出點
- 後續可用 face 分佈切分長 scene，輔助 ASR 分段

---

## 效能實測

**ExaSAN 159.6s 影片**:
| 指標 | 值 |
|------|-----|
| 處理時間 | 0.08s |
| 即時倍率 | 2036.5x（最快的 processor） |
| 輸出 | 52 bytes |

**Charade 長片（6879s, 412343 幀）**:
| 指標 | 值 |
|------|-----|
| 場景數 | 1331 |
| 輸出 | 217 KB |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-05-03 | 初始版本 | OpenCode | deepseek-chat |

---

## 資源預估

| 資源 | 值 |
|------|-----|
| CPU | 0.5 |
| 記憶體 | 512 MB |
| GPU | 不使用 |

---

## Swift AVFoundation 替代評估

### POC 目標

使用 AVFoundation 逐幀 histogram 分析取代 Python PySceneDetect（ContentDetector），目標利用 ANE 加速。

### 測試結果（Charade 60s clip, 3597 frames, 59.9fps）

| 指標 | Python PySceneDetect | Swift AVFoundation (luminance histogram) |
|------|---------------------|------------------------------------------|
| **Scenes 偵測** | **3** ✅ 合理 | **63** ❌ 過度敏感 |
| **處理時間** | **7.93s** | 15.42s |
| **RTF** | **0.132** (7.6x) | 0.257 (3.9x) |
| **記憶體** | ~512MB | 極低（系統框架） |
| **演算法** | ContentDetector（adaptive threshold + frame normalization） | 單純 histogram diff（64 bins luminance） |

### 問題分析

1. **準確度** — 63 vs 3 scenes。簡單的 luminance histogram diff 對 camera movement、lighting change 過度敏感。PySceneDetect 的 ContentDetector 使用 adaptive threshold + 幀正規化，穩定性高很多。
2. **速度** — 15.42s vs 7.93s。AVAssetReader 必須 sequential decode 所有 frames，無法像 ffmpeg 那樣 efficient frame skipping。

### 選型結論

| 項目 | 方案 |
|------|------|
| **Scene Cut Detection** | Python PySceneDetect **維持現狀** |

### 相關檔案

```
scripts/swift_processors/swift_cut_test.swift
```

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-05-03 | 初始版本 | OpenCode | deepseek-chat |
| V1.1 | 2026-05-04 | 新增 Swift AVFoundation 替代評估記錄 | OpenCode | deepseek-chat |
| 依賴 | 無 |
