---
document_type: "reference_doc"
service: "MOMENTRY_CORE"
title: "processing_status JSONB 字段規範"
date: "2026-04-27"
version: "V1.2"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:
  - "jsonb"
  - "processing_status"
  - "進度追蹤"
  - "processor"
  - "rule"
  - "agent"
ai_query_hints:
  - "查詢 processing_status JSONB 字段規範的內容"
  - "processing_status JSONB 結構定義"
  - "如何查詢 processing_status JSONB 字段"
  - "pre_chunks_summary 結構說明"
  - "chunks_summary 結構說明"
  - "Agent 進度追蹤字段"
  - "processing_status SQL 查詢範例"
  - "processing_status Rust 實作範例"
---

# processing_status JSONB 字段規範

| 項目 | 內容 |
|------|------|
| 建立者 | OpenCode |
| 建立時間 | 2026-04-27 |
| 文件版本 | V1.2 |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.2 | 2026-04-27 | 從 VARCHAR 改為 JSONB，支持多層級進度追蹤 | OpenCode | GLM-5 |

---

## 概述

從 V1.2 起，`videos` 表的 `processing_status` 字段改為 **JSONB** 格式，支持：
- 多處理器並行進度追蹤
- pre_chunks/chunks 絕計（按 processor 和按 rule）
- Agent 任務狀態追蹤
- Rule 完成狀態記錄

---

## 當前狀態

| 項目 | 狀態 |
|------|------|
| processing_status 字段類型 | ✅ JSONB（默認 `'{}'::jsonb`） |
| VideoRow/VideoRecord 結構體 | ✅ `Option<serde_json::Value>` |
| init_processing_status | ✅ 已實作（初始化 JSONB） |
| update_processor_progress | ✅ 已實作（更新進度） |
| update_processing_status_completed | ✅ 已實作（完成狀態） |

---

## 1. JSONB 結構定義

### 1.1 完整結構

```json
{
  "phase": "PROCESSING" | "COMPLETED" | "FAILED",
  "active_processors": ["ASR", "YOLO"],
  "total_frames": 412343,
  
  "processing_summary": {
    "processors_completed": ["asr", "cut", "yolo", "ocr", "face", "pose"],
    "processors_failed": [],
    "processors_pending": [],
    "duration_secs": {
      "asr": 607.4,
      "yolo": 1200.5
    }
  },
  
  "pre_chunks_summary": {
    "total_records": 25000,
    "by_processor": {
      "asr": {
        "records": 1466,
        "coverage_type": "time-based",
        "avg_segment_length": 4.7
      },
      "cut": {
        "records": 1332,
        "coverage_type": "time-based"
      },
      "yolo": {
        "records": 11000,
        "coverage_type": "frame-based",
        "unique_frames": 412343,
        "coverage_pct": 100.0
      },
      "ocr": {
        "records": 8000,
        "coverage_type": "frame-based",
        "unique_frames": 350000,
        "coverage_pct": 84.8
      },
      "face": {
        "records": 5000,
        "coverage_type": "frame-based",
        "unique_frames": 250000,
        "coverage_pct": 60.7
      },
      "pose": {
        "records": 6000,
        "coverage_type": "frame-based",
        "unique_frames": 300000,
        "coverage_pct": 72.9
      }
    },
    "frame_coverage": {
      "processors_with_full_coverage": ["yolo"],
      "processors_with_partial_coverage": ["ocr", "face", "pose"]
    }
  },
  
  "chunks_summary": {
    "total_chunks": 2798,
    "total_frames_in_chunks": 1260754,
    "by_rule": {
      "rule_1": {
        "triggered": true,
        "chunks_count": 1466,
        "chunk_type": "sentence",
        "source": "pre_chunks(asr + asrx + yolo + face)",
        "metadata_enriched": true
      },
      "rule_3": {
        "triggered": true,
        "chunks_count": 1332,
        "chunk_type": "scene",
        "source": "pre_chunks(cut) + chunks_rule1",
        "scenes_created": 1332
      }
    },
    "by_type": {
      "sentence": 1466,
      "scene": 1332,
      "time": 688
    }
  },
  
  "agents": {
    "5w1h": {
      "status": "running" | "completed" | "pending" | "failed",
      "scenes_processed": 5,
      "scenes_total": 1332,
      "progress_pct": 0.4,
      "started_at": "2026-04-27T05:45:00Z",
      "updated_at": "2026-04-27T05:46:00Z",
      "model": "gemma4",
      "avg_duration_per_scene": 1.2
    },
    "translation": {
      "status": "pending"
    }
  },
  
  "vectorization_summary": {
    "rule_1_vectors": 1466,
    "rule_3_vectors": 1332,
    "total_vectors": 2798,
    "vector_model": "nomic-embed-text-v2-moe:latest",
    "collection": "momentry_rule1"
  },
  
  "progress": {
    "ASR": {
      "current_frame": 1466,
      "total_frames": 412343,
      "percentage": 0.4,
      "status": "completed",
      "started_at": "2026-04-27T05:30:00Z",
      "completed_at": "2026-04-27T05:40:00Z"
    },
    "YOLO": {
      "current_frame": 412343,
      "total_frames": 412343,
      "percentage": 100.0,
      "status": "completed",
      "started_at": "2026-04-27T05:40:00Z",
      "completed_at": "2026-04-27T06:00:00Z"
    }
  }
}
```

---

### 1.2 簡化結構（處理中）

```json
{
  "phase": "PROCESSING",
  "active_processors": ["YOLO", "OCR"],
  "total_frames": 412343,
  "pre_chunks_summary": {
    "total_records": 0,
    "by_processor": {}
  },
  "chunks_summary": {
    "total_chunks": 0,
    "by_rule": {}
  },
  "agents": {},
  "progress": {
    "YOLO": {
      "current_frame": 25000,
      "total_frames": 412343,
      "percentage": 6.0,
      "status": "running"
    },
    "OCR": {
      "current_frame": 0,
      "total_frames": 412343,
      "percentage": 0,
      "status": "pending"
    }
  }
}
```

---

### 1.3 結構（完成狀態）

```json
{
  "phase": "COMPLETED",
  "active_processors": [],
  "total_frames": 412343,
  "processing_summary": {
    "processors_completed": ["asr", "cut", "yolo", "ocr", "face", "pose"],
    "processors_failed": [],
    "processors_pending": []
  },
  "pre_chunks_summary": {
    "total_records": 25000,
    "by_processor": {
      "asr": {"records": 1466},
      "cut": {"records": 1332},
      "yolo": {"records": 11000}
    }
  },
  "chunks_summary": {
    "total_chunks": 2798,
    "by_rule": {
      "rule_1": {"triggered": true, "chunks_count": 1466},
      "rule_3": {"triggered": true, "chunks_count": 1332}
    }
  },
  "agents": {
    "5w1h": {"status": "completed"}
  }
}
```

---

## 2. 字段說明

### 2.1 phase（階段）

| 值 | 說明 | 適用場景 |
|------|------|----------|
| `PROCESSING` | 正在處理 | 處理器/Rule/Agent 執行中 |
| `COMPLETED` | 完成 | 所有處理完成 |
| `FAILED` | 失敗 | 有處理器失敗 |

---

### 2.2 active_processors

**說明**: 正在執行的處理器列表（大寫）。

**範例**:
```json
["ASR", "YOLO", "OCR"]
```

---

### 2.3 processing_summary

**說明**: 處理器完成狀態總覽。

| 字段 | 類型 | 說明 |
|------|------|------|
| `processors_completed` | Array[String] | 已完成的處理器（小寫） |
| `processors_failed` | Array[String] | 失敗的處理器 |
| `processors_pending` | Array[String] | 等待中的處理器 |
| `duration_secs` | Object | 各處理器執行秒數 |

---

### 2.4 pre_chunks_summary

**說明**: 絕計 `pre_chunks` 表的數據（按處理器）。

#### 2.4.1 by_processor 字段

| 字段 | 類型 | 說明 | 適用處理器 |
|------|------|------|------------|
| `records` | Integer | 處理器產生的記錄數 | 所有 |
| `coverage_type` | String | `time-based` 或 `frame-based` | 所有 |
| `avg_segment_length` | Float | 平均段落長度（秒） | ASR |
| `unique_frames` | Integer | 唯一帧數 | YOLO/OCR/Face/Pose |
| `coverage_pct` | Float | 覆盖率百分比 | YOLO/OCR/Face/Pose |

#### 2.4.2 coverage_type 說明

| 處理器 | coverage_type | 說明 |
|------|---------------|------|
| ASR | `time-based` | 時間段落（start_time → end_time） |
| CUT | `time-based` | 時間段落（cut_time） |
| YOLO | `frame-based` | 單帧檢測結果 |
| OCR | `frame-based` | 單帧 OCR 文字 |
| Face | `frame-based` | 單帧人臉檢測 |
| Pose | `frame-based` | 單帧姿態估計 |

---

### 2.5 chunks_summary

**說明**: 絕計 `chunks` 表的數據（按 Rule）。

#### 2.5.1 by_rule 字段

| 字段 | 類型 | 說明 |
|------|------|------|
| `triggered` | Boolean | Rule 是否觸發 |
| `chunks_count` | Integer | Rule 產生的 chunks 數 |
| `chunk_type` | String | Chunk 類型（sentence/scene/time） |
| `source` | String | Rule 數據源描述 |
| `metadata_enriched` | Boolean | 是否包含 YOLO/Face metadata |

#### 2.5.2 by_type 字段

| chunk_type | 說明 | 來源 Rule |
|------------|------|-----------|
| `sentence` | 語句 Chunk | Rule 1（ASR + metadata） |
| `scene` | 場景 Chunk | Rule 3（CUT + Rule 1） |
| `time` | 時間 Chunk | Rule 5（時間分段） |

---

### 2.6 agents

**說明**: Agent 任務狀態。

| 字段 | 類型 | 說明 |
|------|------|------|
| `status` | String | `pending` / `running` / `completed` / `failed` |
| `scenes_processed` | Integer | 已處理場景數 |
| `scenes_total` | Integer | 總場景數 |
| `progress_pct` | Float | 進度百分比 |
| `started_at` | String | 開始時間（ISO 8601） |
| `updated_at` | String | 更新時間（ISO 8601） |
| `model` | String | 使用模型（gemma4） |
| `avg_duration_per_scene` | Float | 平均處理時間（秒） |

---

### 2.7 vectorization_summary

**說明**: 向量化統計。

| 字段 | 類型 | 說明 |
|------|------|------|
| `rule_1_vectors` | Integer | Rule 1 向量數 |
| `rule_3_vectors` | Integer | Rule 3 向量數 |
| `total_vectors` | Integer | 總向量數 |
| `vector_model` | String | 向量模型名稱 |
| `collection` | String | Qdrant Collection 名稱 |

---

### 2.8 progress

**說明**: 各處理器詳細進度。

| 字段 | 類型 | 說明 |
|------|------|------|
| `current_frame` | Integer | 當前處理帧數 |
| `total_frames` | Integer | 總帧數 |
| `percentage` | Float | 進度百分比 |
| `status` | String | `pending` / `running` / `completed` / `failed` |
| `started_at` | String | 開始時間（ISO 8601） |
| `completed_at` | String | 完成時間（ISO 8601） |

---

## 3. SQL 查詢範例

### 3.1 基本查詢

```sql
-- 取得處理狀態
SELECT 
  uuid,
  processing_status->>'phase' as phase,
  processing_status->'active_processors' as active_processors,
  processing_status->'pre_chunks_summary'->>'total_records' as pre_chunks_count,
  processing_status->'chunks_summary'->>'total_chunks' as chunks_count,
  processing_status->'agents'->'5w1h'->>'status' as agent_5w1h_status
FROM videos 
WHERE uuid = '384b0ff44aaaa1f14cb2cd63b3fea966';
```

---

### 3.2 更新進度

```sql
-- 更新處理器進度
UPDATE videos 
SET processing_status = jsonb_set(
  processing_status,
  '{progress,YOLO}',
  '{"current_frame": 25000, "percentage": 6.0, "status": "running"}'::jsonb
)
WHERE uuid = '384b0ff44aaaa1f14cb2cd63b3fea966';

-- 添加 Agent 狀態
UPDATE videos 
SET processing_status = jsonb_set(
  processing_status,
  '{agents,5w1h}',
  '{"status": "running", "scenes_processed": 5}'::jsonb
)
WHERE uuid = '384b0ff44aaaa1f14cb2cd63b3fea966';
```

---

### 3.3 絕計查詢

```sql
-- 查詢 pre_chunks 按處理器絕計
SELECT 
  uuid,
  processing_status->'pre_chunks_summary'->'by_processor'->'yolo'->>'records' as yolo_records,
  processing_status->'pre_chunks_summary'->'by_processor'->'yolo'->>'coverage_pct' as yolo_coverage
FROM videos 
WHERE processing_status->>'phase' = 'COMPLETED';

-- 查詢 chunks 按 Rule 絕計
SELECT 
  uuid,
  processing_status->'chunks_summary'->'by_rule'->'rule_1'->>'chunks_count' as rule1_chunks,
  processing_status->'chunks_summary'->'by_rule'->'rule_3'->>'chunks_count' as rule3_chunks
FROM videos 
WHERE processing_status->>'phase' = 'COMPLETED';
```

---

### 3.4 查詢 Agent 進度

```sql
-- 查詢 5W1H Agent 進度
SELECT 
  uuid,
  processing_status->'agents'->'5w1h'->>'status' as status,
  processing_status->'agents'->'5w1h'->>'scenes_processed' as processed,
  processing_status->'agents'->'5w1h'->>'scenes_total' as total,
  processing_status->'agents'->'5w1h'->>'progress_pct' as progress
FROM videos 
WHERE processing_status->'agents'->'5w1h'->>'status' = 'running';
```

---

## 4. Rust 實作範例

### 4.1 初始化 processing_status

```rust
pub async fn init_processing_status(
    &self,
    uuid: &str,
    processors: Vec<&str>,
    total_frames: u64,
) -> Result<()> {
    let progress: serde_json::Map<String, serde_json::Value> = processors
        .iter()
        .map(|p| {
            (p.to_uppercase(), serde_json::json!({
                "current_frame": 0,
                "total_frames": total_frames,
                "percentage": 0,
                "status": "pending"
            }))
        })
        .collect();
    
    let status = serde_json::json!({
        "phase": "PROCESSING",
        "active_processors": processors.iter().map(|p| p.to_uppercase()).collect::<Vec<_>>(),
        "total_frames": total_frames,
        "processing_summary": {
            "processors_completed": [],
            "processors_failed": [],
            "processors_pending": processors.iter().map(|p| p.to_lowercase()).collect::<Vec<_>>()
        },
        "pre_chunks_summary": {
            "total_records": 0,
            "by_processor": {}
        },
        "chunks_summary": {
            "total_chunks": 0,
            "by_rule": {}
        },
        "agents": {},
        "progress": progress
    });
    
    sqlx::query(&format!(
        "UPDATE {} SET processing_status = $1 WHERE uuid = $2",
        schema::table_name("videos")
    ))
    .bind(&status)
    .bind(uuid)
    .execute(&self.pool)
    .await?;
    
    Ok(())
}
```

---

### 4.2 更新處理器進度

```rust
pub async fn update_processor_progress(
    &self,
    uuid: &str,
    processor: &str,
    current_frame: u64,
    total_frames: u64,
    status: &str,
) -> Result<()> {
    let processor_key = processor.to_uppercase();
    let percentage = if total_frames > 0 {
        ((current_frame as f64 / total_frames as f64) * 100.0).round() as u32
    } else {
        0
    };
    
    let progress_update = serde_json::json!({
        "current_frame": current_frame,
        "total_frames": total_frames,
        "percentage": percentage,
        "status": status
    });
    
    sqlx::query(&format!(
        "UPDATE {} SET processing_status = jsonb_set(
            processing_status,
            '{{progress,{}}}',
            $1::jsonb
        ) WHERE uuid = $2",
        schema::table_name("videos"),
        processor_key
    ))
    .bind(&progress_update)
    .bind(uuid)
    .execute(&self.pool)
    .await?;
    
    Ok(())
}
```

---

### 4.3 更新完成狀態

詳見 `src/core/db/postgres_db.rs:update_processing_status_completed()`。

---

## 5. 版本對照

### 5.1 V1.0（VARCHAR）vs V1.2（JSONB）

| 項目 | V1.0（VARCHAR） | V1.2（JSONB） |
|------|-----------------|---------------|
| 字段類型 | VARCHAR(50) | JSONB |
| 默認值 | `'REGISTERED'` | `'{}'::jsonb` |
| 狀態表示 | 單一狀態字串 | 多層級結構 |
| 處理器進度 | ❌ 不支持 | ✅ 支持（progress 字段） |
| Agent 狀態 | ❌ 不支持 | ✅ 支持（agents 字段） |
| pre_chunks/chunks 絕計 | ❌ 不支持 | ✅ 支持 |
| Rule 絕計 | ❌ 不支持 | ✅ 支持 |

---

### 5.2 遷移步驟

```sql
-- Step 1: 修改字段類型
ALTER TABLE videos 
ALTER COLUMN processing_status TYPE JSONB 
USCASE processing_status::text::jsonb;

-- Step 2: 設置默認值
ALTER TABLE videos 
ALTER COLUMN processing_status SET DEFAULT '{}'::jsonb;

-- Step 3: 初始化現有記錄（可選）
UPDATE videos 
SET processing_status = '{"phase": "COMPLETED"}'::jsonb
WHERE processing_status IS NULL OR processing_status = '{}'::jsonb;
```

---

## 6. 相關文件

| 文件 | 說明 |
|------|------|
| `JOB_WORKER_IMPLEMENTATION_PLAN.md` | Worker 實作計畫（B.1.2 JSONB 章節） |
| `VIDEO_PROCESSING_SPEC.md` | Video 解析行為規範（SQL 映射） |
| `PROCESSING_PIPELINE.md` | Pipeline 狀態追蹤 |
| `AGENT_SPEC.md` | Agent 設計規範（Agent 進度追蹤） |

---

## 7. 檔案位置

| 類型 | 路徑 | 說明 |
|------|------|------|
| Rust 實作 | `src/core/db/postgres_db.rs` | processing_status 相關函數 |
| VideoRow 結構體 | `src/core/db/postgres_db.rs` | `processing_status: Option<serde_json::Value>` |
| VideoRecord 結構體 | `src/core/db/video.rs` | `processing_status: Option<serde_json::Value>` |

---

## 8. 常用指令

### 8.1 查詢處理狀態

```bash
# 查詢 UUID 的處理狀態
psql -d momentry -c "SELECT uuid, processing_status->>'phase' FROM videos WHERE uuid = '384b0ff44aaaa1f14cb2cd63b3fea966';"

# 查詢所有處理中的視頻
psql -d momentry -c "SELECT uuid, processing_status->'active_processors' FROM videos WHERE processing_status->>'phase' = 'PROCESSING';"
```

---

### 8.2 更新 JSONB 字段

```bash
# 更新處理器進度（範例）
psql -d momentry -c "UPDATE videos SET processing_status = jsonb_set(processing_status, '{progress,ASR}', '{\"percentage\": 50}'::jsonb) WHERE uuid = '384b0ff44aaaa1f14cb2cd63b3fea966';"
```

---

## 版本資訊

- 版本: V1.2
- 建立日期: 2026-04-27
- 文件更新: 2026-04-27
