History
連線資訊
| 項目 | 值 |
|---|---|
| 基礎路徑 | https://vas-poc.vurbo.ai/api/v1/sse |
| 協定 | HTTP + Server-Sent Events (SSE) |
| 資料格式 | text/event-stream |
| 認證方式 | Header X-API-Key: {KEY} |
注意:瀏覽器原生 EventSource API 不支援自訂 Header,需使用 fetch API 搭配 ReadableStream,或使用支援 Header 的 SSE 客戶端套件。
端點總覽
| 方法 | 端點 | 說明 |
|---|---|---|
| GET | /api/v1/sse/history/transcribe/{taskId} | 取得歷史對話紀錄 |
GET /api/v1/sse/history/transcribe/{taskId}
功能說明
載入指定任務的完整對話紀錄,包含所有句子和摘要。透過 SSE 串流逐條發送。
與 逐字稿下載 API(
GET /api/v1/tasks/{taskId}/transcript/export)的差異:
- 本端點:漸進式載入用途;以 event stream 逐句推送原始結構資料(JSON 片段),供前端 UI 漸進渲染。
- 逐字稿下載:離線下載用途;一次回傳完整檔案(TXT / SRT / SBV / VTT / CSV),可直接交給字幕軟體或試算表開啟。
使用場景
- 查看錄音詳情頁
- 載入歷史逐字稿
認證方式
Header:X-API-Key(詳見 認證機制)
請求參數
| 參數 | 位置 | 類型 | 必填 | 說明 |
|---|---|---|---|---|
taskId | path | string | 是 | 錄音 ID(UUID) |
請求範例
curl -N "https://vas-poc.vurbo.ai/api/v1/sse/history/transcribe/550e8400-e29b-41d4-a716-446655440000" \
-H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"
// 使用 fetch API(因 EventSource 不支援 Header)
async function connectSSE(taskId, apiKey) {
const response = await fetch(
`https://vas-poc.vurbo.ai/api/v1/sse/history/transcribe/${taskId}`,
{
headers: {
'X-API-Key': apiKey
}
}
);
const reader = response.body.getReader();
// ... 處理 SSE 事件
}
事件序列
1. connected → 連線確認
2. init_metadata → 發送任務元資料
3. init_sentence → 逐條發送句子(重複 N 次)
4. init_summary → 發送摘要
5. init_done → 初始化完成
事件格式
connected
{
"message": "歷史紀錄服務已連線 (recordingId: xxx)"
}
init_metadata
{
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"title": "會議記錄",
"created_at": "2026-02-23T10:00:00Z",
"type": "transcribe",
"has_speaker_diarization": true,
"transcription_languages": ["zh-TW"],
"translation_languages": ["en-US"],
"summary_template": "general",
"summary_language": "zh-TW",
"speaker_aliases": {"speaker_1": "王經理"}
}
| 欄位 | 類型 | 說明 |
|---|---|---|
task_id | string | 任務 ID(UUID) |
title | string | 任務標題 |
created_at | string | 建立時間(ISO 8601) |
type | string | 錄音類型 |
has_speaker_diarization | boolean | 是否啟用說話者辨識 |
transcription_languages | array|null | 轉錄語言陣列(BCP 47,如 ["zh-TW"]),最多 2 個 |
translation_languages | array|null | 翻譯語言陣列(BCP 47,如 ["en-US", "ja-JP"]),最多 8 個 |
summary_template | string|null | 摘要模板 slug(如 general、meeting),未指定時為 null |
summary_language | string|null | 摘要輸出語言(BCP 47,如 zh-TW、en-US),未指定時為 null |
speaker_aliases | object | 「原始說話者 ID → 顯示名」映射;無別名時為 {}(空物件,非陣列)。前端用於 rename 前的撞名預檢(v1.3.12 新增) |
init_sentence
{
"sid": 1,
"origin": "你好",
"translations": {
"en-US": "Hello"
},
"start_time": "00:05",
"speaker_id": "speaker_1",
"speaker_label": "王經理"
}
句子若有翻譯失敗,會額外帶 translation_errors 欄位(僅有失敗時出現),供前端區分「該語言未排程翻譯」(translations 缺 key)vs「翻過但失敗」(translation_errors 有 key):
{
"sid": 5,
"origin": "敏感詞句子",
"translations": {
"en-US": "Sensitive sentence"
},
"translation_errors": {
"ja": "llm_content_filtered"
},
"start_time": "00:25",
"speaker_id": "speaker_1",
"speaker_label": "王經理"
}
句子若曾被使用者編輯過原文(透過 PATCH /api/v1/recordings/{id}/entries/{sid}),會額外帶 original_text_raw 與 original_text_edited_at(僅在編輯後出現):
{
"sid": 7,
"origin": "修正後的文字",
"original_text_raw": "原本的 STT 輸出",
"original_text_edited_at": "2026-05-06T10:30:00.000000Z",
"translations": { "en-US": "Corrected text" },
"start_time": "00:35",
"speaker_id": "speaker_1",
"speaker_label": "王經理"
}
| 欄位 | 類型 | 說明 |
|---|---|---|
sid | number | 句子 ID |
origin | string | 原文內容(被編輯過時為使用者修正後版本) |
translations | object|null | 翻譯文字 map({"語言代碼": "翻譯文字"}),無翻譯時為 null |
translation_errors | object | 可選。翻譯失敗錯誤碼 map({"語言代碼": "error_code"}),無失敗時不出現此欄位 |
original_text_raw | string | 可選。STT 原始輸出文字。僅在被使用者編輯過時出現,前端可用以顯示「已編輯」標記、提供「還原原文」功能 |
original_text_edited_at | string | 可選。原文最近編輯時間(ISO 8601)。與 original_text_raw 同步出現 |
start_time | string | 開始時間(mm:ss) |
speaker_id | string|null | 原始說話者 ID(不可變、永遠穩定,如 speaker_1)。提供給 PATCH /speakers/reassign 作為 target_speaker_id 來源(v1.5.3 翻轉:原為顯示名) |
speaker_label | string|null | 顯示標籤(套 speaker_aliases 後的人類可讀名稱,如 王經理)。無 alias 時等同 speaker_id(v1.5.3 新增取代原 speaker_id 顯示語意) |
前端 detection:以欄位存在性判斷句子是否被編輯過(
'original_text_raw' in data或data.original_text_raw !== undefined),不要比對origin === original_text_raw— 使用者可能編輯後又改回相同字串,那種情況下文字相等但仍應顯示「已編輯」標記。
v1.5.3 命名翻轉:
speaker_id從顯示名翻轉為原始 ID;新增speaker_label為顯示標籤。語者編輯(reassign/merge)一律以speaker_id為定位 key。詳見 V1.5.3 changelog。
init_summary
除摘要文字 text 外,含 mode-aware metadata(mode / template / plain_text / prompt_snapshot),讓客戶端追溯該份摘要對應的 mode + effective slug + 客戶 prompt 內容(custom mode)。
v1.5.5 新增 fallback_level / dropped_segments:當該份摘要實際走過 LLM 服務內容過濾 fallback chain(L2 中性 prompt 或 L3 分段丟段)時才出現,供歷史回放時 audit 與 UI 提示。
範例(L1 直接成功,無 fallback):
{
"text": "摘要內容...",
"mode": "custom",
"template": "acme-meeting-v2",
"plain_text": true,
"prompt_snapshot": "請強調 KPI"
}
範例(L3 觸發,逐字稿被剝除 2 段後產出):
{
"text": "摘要內容(已省略 2 段)...",
"mode": "custom",
"template": "acme-meeting-v2",
"plain_text": true,
"prompt_snapshot": "請強調 KPI",
"fallback_level": 3,
"dropped_segments": [3, 7]
}
| 欄位 | 類型 | 說明 |
|---|---|---|
text | string | 摘要文字 |
mode | string | null | "builtin" / "custom" / null(未生成摘要時為 null) |
template | string | null | effective slug — builtin → 內建模板 slug;custom → 客戶 slug |
plain_text | boolean | 是否為純文字輸出 |
prompt_snapshot | string | null | 僅 custom mode 有值,為客戶原樣傳入的 prompt 內容(重建依據) |
fallback_level | int (omit) | 僅 fallback 觸發時出現(2 或 3)。2=L2 中性 prompt;3=L3 分段丟段。L1 直接成功則 omit |
dropped_segments | int (omit) | 僅 fallback_level=3 時出現,被剝除的逐字稿段 indices(原序整數陣列) |
fallback_level/dropped_segments與prompt_snapshot互補:前者記錄實際執行路徑(是否走 fallback),後者記錄客戶意圖(原 prompt 內容)。即使 fallback 觸發、客戶 prompt 未實際使用,prompt_snapshot仍保留原文作為審計依據。詳見 V1.5.5 changelog – LLM 服務內容過濾自動降級。
init_done
{
"totalSentences": 10
}
| 欄位 | 類型 | 說明 |
|---|---|---|
totalSentences | number | 總句子數 |
邊界情境:無語音內容(V1.3.7)
若任務全程靜音、音量過小、雜訊過多,或辨識語言與實際音檔不符,導致語音辨識引擎未辨識出任何句子,此端點仍以正常事件序列完成(不是 sse_transcript_not_found 錯誤):
init_metadata正常發送init_sentence發送 0 次(無句子)init_summary的text為空字串""init_done的totalSentences為0
此行為適用於 即時錄音(WebSocket 錄音結束)與 檔案匯入(離線處理完成)兩種來源,已與 V1.3.5 匯入流程的「零辨識結果」合法化行為對齊。客戶端應透過 totalSentences === 0 判斷是否顯示「無語音內容」空狀態,而非將其視為錯誤分支。詳見 音檔匯入指南 – 音檔無法辨識時的行為。
特有錯誤碼
| 錯誤碼 | HTTP 狀態碼 | 說明 | 處理建議 |
|---|---|---|---|
recording_not_found | 404 | 找不到錄音 | 確認 taskId 正確 |
sse_transcript_not_found | 404 | 找不到逐字稿 blob | 指定 taskId 的逐字稿檔案不存在或存取失敗(正常流程下不會出現;V1.3.7 後即時錄音靜音亦不會觸發此錯誤) |
前端範例
async function loadHistory(taskId, apiKey) {
const response = await fetch(
`https://vas-poc.vurbo.ai/api/v1/sse/history/transcribe/${taskId}`,
{
headers: {
'X-API-Key': apiKey
}
}
);
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
// 解析 SSE 格式:event: xxx\ndata: {...}\n\n
const events = parseSSE(text);
for (const event of events) {
if (event.type === 'init_metadata') {
console.log('任務資訊:', event.data.title);
} else if (event.type === 'init_sentence') {
console.log(`[${event.data.start_time}] ${event.data.origin}`);
if (event.data.translations) {
console.log(`翻譯:`, event.data.translations);
}
} else if (event.type === 'init_summary') {
console.log('摘要:', event.data.text);
} else if (event.type === 'init_done') {
console.log(`載入完成,共 ${event.data.totalSentences} 句`);
}
}
}
}
版本:V1.5.7 最後更新:2026-05-20