WebSocket API

WebSocket 回應事件

概述

所有 WebSocket 可能收到的回應事件格式參考。關於連線與認證方式,請參考 連線與認證;關於請求操作,請參考 Voice Translation Actions。


目錄

  1. session_started - Session 啟動成功
  2. resume_ok - 斷線續接成功
  3. result - 辨識/翻譯結果
  4. status - 通用狀態回應
  5. task_complete - 任務處理完成
  6. config_updated - 設定更新完成
  7. tts_ready - TTS 語音就緒
  8. tts_error - TTS 合成失敗
  9. viewer_count - 觀眾人數更新
  10. broadcast_phase_changed - 廣播階段變更
  11. broadcast_recording_ready - 廣播錄音就緒
  12. speaker_renamed - 說話者重命名
  13. speaker_reassigned - 語者身份修改
  14. speakers_merged - 語者合併
  15. language_switch_start - 語言切換開始
  16. batch_retranslation - 批次重翻結果
  17. language_switch_done - 語言切換完成
  18. translation_language_removed - 翻譯語言已移除
  19. tts_mode_changed - TTS 模式變更
  20. language_switched - 互譯語言切換完成
  21. tts_updated - 互譯 TTS 設定更新
  22. conversation_mode_changed - 對話模式變更
  23. speaker_language_changed - 用戶語言變更
  24. speaking_speed_changed - 語速變更
  25. summary_updated - 摘要設定更新
  26. segment_uploaded - 音訊分段上傳完成
  27. stt_event - STT 連線狀態事件
  28. channel_status - 聲道狀態變更
  29. segment_discarded - 句子作廢
  30. viewer_joined - 觀眾加入事件
  31. viewer_left - 觀眾離開事件
  32. error - 錯誤事件
  33. upload_error - 上傳錯誤
  34. speakers_auto_merged - 說話者自動合併
  35. summary_done - 摘要生成完成
  36. summary_error - 摘要生成失敗或未產生

session_started

說明

當 start action 成功後,伺服器回傳包含完整 Session 初始資訊的事件。前端可透過 recording_type 區分錄音類型。

一般錄音(transcribe / conversation / record)

{
  "type": "voice-translation",
  "data": {
    "action": "session_started",
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "task_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "recording_type": "transcribe",
    "recognition_mode": "single",
    "resume_token": "L0VBAwIy...(43 字元)",
    "resume_grace_seconds": 45,
    "server_time": 1749550000000,
    "message": "語音辨識已開始"
  }
}

廣播模式(broadcast)

{
  "type": "voice-translation",
  "data": {
    "action": "session_started",
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "task_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "recording_type": "broadcast",
    "recognition_mode": "multi_speaker",
    "phase": "standby",
    "viewer_count": 0,
    "queue_count": 0,
    "peak_viewers": 0,
    "total_viewers": 0,
    "resume_token": "L0VBAwIy...(43 字元)",
    "resume_grace_seconds": 45,
    "server_time": 1749550000000,
    "message": "語音辨識已開始"
  }
}

多聲道模式(multi_channel)

多聲道(實體聲道分離)場次的 session_started 額外帶 channel_mode 與 channels[],回傳伺服器實際生效的聲道設定快照。

{
  "type": "voice-translation",
  "data": {
    "action": "session_started",
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "task_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "recording_type": "transcribe",
    "recognition_mode": "multi_channel",
    "channel_mode": "per_channel",
    "channels": [
      {
        "channel_id": 1,
        "speaker_name": "主持人",
        "transcription_languages": ["zh-TW"],
        "status": "preparing"
      },
      {
        "channel_id": 2,
        "speaker_name": "與談人",
        "transcription_languages": ["en-US"],
        "status": "preparing"
      }
    ],
    "resume_token": "L0VBAwIy...(43 字元)",
    "resume_grace_seconds": 45,
    "server_time": 1749550000000,
    "message": "語音辨識已開始"
  }
}

欄位說明

欄位類型說明
session_idstring會話 ID(WS 連線層級,連線結束即失效)
task_idstring任務 ID(與 REST /api/v1/tasks/{taskId} 及 Webhook data.task_id 為同一識別碼)
recording_typestring錄音類型:transcribe、conversation、record、broadcast
recognition_modestring辨識模式:single、multi_speaker、multi_language、multi_channel
channel_modestring多聲道子模式(僅 multi_channel 場次出現):per_channel(每路聲道獨立辨識)或 shared(各路輪流發言、共用一條辨識)
channelsobject[]聲道設定快照(僅 multi_channel 場次出現),每路元素欄位如下
channels[].channel_idint聲道編號(1–8,場內唯一)
channels[].speaker_namestring該路綁定的語者名稱(未設定時不出現)
channels[].transcription_languagesstring[]該路綁定的轉錄語言(恰 1 個)
channels[].statusstring該路狀態:preparing / ready / removed / error,狀態機詳見 channel_status
resume_tokenstring斷線續接權杖(43 字元)。斷線後於 resume_grace_seconds 寬限期內,重連時帶它即可接回原會話;於 session_started 預先發送,請保存到本次會話結束
resume_grace_secondsint重連寬限秒數(預設 45)。為 wall-clock 真實時間,斷線後持續倒數
server_timeint64伺服器當下 unix 毫秒。前端可用「(server_time, 收到當下的 client 時間)」估算時鐘偏差作為參考;但 grace 倒數仍以 client wall-clock 為準
messagestring狀態描述訊息
phasestring廣播階段:standby 或 live(僅廣播模式)
viewer_countint目前在線觀眾數(僅廣播模式)
queue_countint排隊等待中的觀眾數(僅廣播模式)
peak_viewersint本次廣播峰值觀眾數(僅廣播模式)
total_viewersint累計曾連線的觀眾總數(僅廣播模式)

ID 對齊提示:WebSocket、REST、Webhook 三個介面以 task_id(UUID)作為任務的統一識別碼。session_id 是 WS 連線層級的識別碼,與 task 不同概念。

多聲道場次請驗證 channel_mode:多聲道 start 成功時,session_started 一定帶 channel_mode 與 channels[];若回應沒有這兩個欄位,代表本次連線未以多聲道模式啟動(例如服務正在版本更新、本次連線的服務版本尚未支援多聲道),請立即停止並重新連線,不要當作多聲道場次繼續送音訊。


resume_ok

說明

斷線後於 resume_grace_seconds 寬限期內,以 resume_token 重連成功時,伺服器回傳的事件。收到後請像 start 之後一樣重新開始送音訊流(WebM/Opus 須送全新容器、PCM 直接續送),並依 server_last_sid / server_last_offset_ms 對齊本地內容。若 is_paused 為 true,代表斷線前處於暫停狀態,請續接後維持暫停(重開音訊流後立即暫停、不送音訊),不要逕自恢復錄音。完整續接握手流程請參考 連線與認證。

{
  "type": "voice-translation",
  "data": {
    "action": "resume_ok",
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "task_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "recording_type": "transcribe",
    "recognition_mode": "single",
    "server_last_sid": 42,
    "server_last_offset_ms": 125000,
    "server_recording_ms": 127500,
    "is_paused": false,
    "settings": { ... },
    "message": "已續接原會話"
  }
}

欄位說明

欄位類型說明
session_idstring會話 ID(WS 連線層級,連線結束即失效)
task_idstring任務 ID(與原會話相同,續接後維持同一識別碼)
recording_typestring錄音類型:transcribe、conversation、record、broadcast
recognition_modestring辨識模式:single、multi_speaker、multi_language、multi_channel
server_last_sidint伺服器目前最後一個句子編號(sid)。前端應忽略 sid ≤ 此值的重複訊息
server_last_offset_msint64斷點對應的逐字稿時間軸位置(毫秒),基於已處理的音訊長度(非 wall-clock;斷線期間音訊時間軸凍結)。前端用它把重連後的新內容接在正確的時間軸位置
server_recording_msint64續接後逐字稿時間軸實際接續的錄音頭時間(毫秒,含靜音)。前端用它把錄音秒數標頭對齊到逐字稿所用的同一條時間軸。與 server_last_offset_ms 的差值即為斷點前最後一句定稿之後、尚未產出逐字稿的尾端音訊(靜音或未斷句的語音)。省略時為 0
is_pausedbool續接後伺服器認定的暫停狀態:true=斷線前已暫停,前端應維持暫停(重開音訊流後立即暫停、不送音訊);false=正常錄音中。供斷網重連與整頁 refresh 後對齊暫停 UI。省略時視為 false(向下相容舊版伺服器)
settingsobjectsession 目前持有的本次錄音設定(state reconcile 用,v1.6.4 新增);詳見連線文件
messagestring狀態描述訊息(固定為「已續接原會話」)

注意:兩種時間不可混用:逐字稿時間軸(server_last_offset_ms)基於音檔、斷線時凍結;grace 重連窗口(resume_grace_seconds)是 wall-clock 真實時間、斷線時持續倒數。判斷「還能不能重連」必須用 wall-clock,不能用音檔時間位置。

多聲道模式(multi_channel):settings 內含 channel_mode 與 channels[](欄位同 session_started 的 channels[])。斷線續接不會重新驗證 start 參數,前端請以這份快照確認伺服器仍在多聲道模式、各路語言綁定未變,並依各路 status 還原狀態顯示——續接後尚在準備中的路為 preparing,約 4 秒後開始出字(期間講話不會丟失,只是延遲出字)。


result

說明

語音辨識與翻譯結果。一個 result 事件可能包含 origin(辨識結果)和/或 translations(翻譯結果)。

origin(語音辨識結果)

{
  "type": "voice-translation",
  "data": {
    "action": "result",
    "origin": {
      "sid": 1,
      "language": "zh-TW",
      "text": "你好,很高興認識你",
      "is_final": true,
      "speaker_id": "0",
      "detected_language": "zh-TW",
      "start_time": "00:05"
    }
  }
}

origin 欄位說明

欄位類型說明
sidint句子編號,從 1 開始
languagestring來源語言代碼。互譯模式與多語轉錄模式下為系統判定的語言——多語模式逐句判定(同一場錄音中會隨每句實際語言變動),判定不可信時維持設定值、欄位不留空
textstring辨識出的文字
is_finalboolean是否為最終結果
speaker_idstring說話者原始 ID
speaker_labelstring(多人模式)顯示標籤(套 alias 後;無 alias 時等於 speaker_id)
detected_languagestring偵測到的語言。互譯模式下由系統自動判定
start_timestring句子開始時間(mm:ss);廣播 standby 階段不送此欄位,進 live 後從 00:00 起算
channel_idint(多聲道模式)該句來源的聲道編號;僅 multi_channel 場次出現,每句必帶

多聲道模式(multi_channel):origin 每句帶 channel_id,且 speaker_id 格式固定為 channel_{N}(N 為聲道編號,如 channel_3)——語者身分由實體聲道決定、整場穩定不變,不經模型推斷。speaker_label 為顯示名稱:經 rename_speaker 改過時用新名稱,否則為該路設定的 speaker_name,兩者皆無時等於 speaker_id。

translations(翻譯結果)

{
  "type": "voice-translation",
  "data": {
    "action": "result",
    "translations": {
      "en-US": {
        "sid": 1,
        "text": "Hello, nice to meet you",
        "is_final": true
      }
    }
  }
}

translations 欄位說明

翻譯結果以語言代碼為 key,每個語言的翻譯物件包含:

欄位類型說明
sidint句子編號
textstring翻譯後的文字
is_finalboolean是否為最終結果
is_retranslationboolean是否為重新翻譯結果(僅 retranslate 時)
speaker_idstring(多人模式)原始語者 ID(自 v1.5.3 與 origin 對齊)
speaker_labelstring(多人模式)顯示標籤(套 alias 後;無 alias 時等於 speaker_id)

多語言翻譯(v1.6.7):translation_languages 指定多個語言時,每個語言各回一則獨立的 result 事件——同一 sid 會收到 N 則 result,每則的 translations 僅含單一語言 key,不會在一則事件中合併多語言。客戶端需以「sid + 語言代碼」累積譯文、不可互相覆蓋;各語言到達順序不固定(並行翻譯)。

多聲道模式(multi_channel):translations 不帶 channel_id。請以 sid 對回同句的 origin,即可取得該句的聲道與語者資訊。

重要:retranslate action 的成功回應走獨立的 action: "translation" 事件(非 result),payload 結構與本表相同。詳見 voice-translation.md retranslate 成功回應。


status

說明

通用狀態回應,用於 pause、resume、stop、set_name、tts_stop、start_speaking 等操作的確認。

{
  "type": "voice-translation",
  "data": {
    "action": "status",
    "status": "paused",
    "message": "語音辨識已暫停"
  }
}

欄位說明

欄位類型說明
statusstring機器可讀的錄音生命週期狀態:live(恢復)/ paused(暫停)/ ended(停止)。僅 pause / resume / stop 帶此欄位;set_name 等不帶。ended 一定在 task_complete 之前送出。
messagestring狀態顯示文字(不保證格式,請勿解析;一律以 status 欄位判斷狀態)

浮動字幕消費端(SSE 浮動字幕)應依 status 動作:paused → 凍結、ended → 關閉視窗、live → 恢復。


task_complete

說明

當 stop 後音檔和逐字稿上傳完成時觸發。task_id 可用於後續 REST API 查詢任務詳情。

  • 一定在 status: "ended" 之後送出。
  • 逐字稿含摘要,所以本事件要等標題與摘要生成完成。通常數秒到數十秒;摘要較長或服務較慢時會更久,最長約 8 分鐘。
  • 同時錄音名額在送出本事件的當下釋放:收到後即可開始下一場錄音。
  • 判斷錄音是否完成,建議同時支援 Webhook 或 REST 查詢,不要只依賴本事件。
  • 錄音因為長時間沒有語音而自動結束時,同樣會收到本事件。
{
  "type": "voice-translation",
  "data": {
    "action": "task_complete",
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "message": "任務處理完成"
  }
}

整場沒有收到音訊的錄音:不論是送出 stop、點數不足或自動結束,只要整場沒有收到任何音訊,仍會依序收到 status: "ended" 與本事件,並帶 noAudio: true。這筆錄音沒有逐字稿與音檔,狀態為 failed,同時送出 recording.failed Webhook(failure_source 為 no_audio);請不要再去讀取逐字稿,改提示使用者沒有收到聲音。已經過的分鐘照常計費。

{
  "type": "voice-translation",
  "data": {
    "action": "task_complete",
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "noAudio": true,
    "message": "任務處理完成"
  }
}

廣播在預備階段就結束(還沒開播)時,只會收到 status: "ended",不會收到本事件:預備階段不建立錄音。

欄位說明

欄位類型說明
task_idstringRecording UUID,可用於後續 API 查詢
noAudioboolean只在整場沒有收到任何音訊時出現,值一定是 true;有錄到音訊時不帶這個欄位
messagestring狀態描述

config_updated

說明

設定更新完成事件,在 config action 成功後觸發。

注意:僅在設定被接受時觸發。設定被拒絕時回傳的是 type: "error",客戶端需一併監聽,否則會誤判為無回應。

{
  "type": "voice-translation",
  "data": {
    "action": "config_updated",
    "updated": ["terminology", "fuzzy_correction", "translation_dict"],
    "message": "設定已更新"
  }
}

欄位說明

欄位類型說明
updatedstring[]已更新的設定類型:terminology、fuzzy_correction、translation_dict
messagestring狀態訊息
terminology_effectivestring(可選)錄製中更新術語庫時出現,值為 "next_turn":新術語從下一句生效。初始 config 不會出現
unknown_languagesstring[](可選)無法辨識的字庫語言代碼(例如 zh、chinese)。這些字庫不會生效,但 config 仍算成功
inactive_languagesstring[](可選)代碼合法、但本場錄音沒有使用的語言。錄音尚未開始時不會出現(此時語言清單還沒定案)
inactive_dict_languagesstring[](可選)同上,但針對翻譯字典的目標語言
homophone_conflictsobject[](可選)字庫中讀音相同的術語組合,每筆含 languages 與 terms。錄音尚未開始時不會出現(此時語言清單還沒定案)

homophone_conflicts 怎麼看:兩個讀音相同的術語同時登記時(例如「公事包」與「公式包」), 逐字稿出現讀音相同的第三種寫法,系統只能改成其中一個,改成哪一個不保證。 兩個術語本身都仍然生效,不確定的只有「沒登記過的同音錯字歸誰」。

這是警告不是錯誤 —— 字庫照樣收下、config 照樣成功。 若這組術語對你很重要,建議用 fuzzy_correction 明確列出該錯字對應到哪一個術語。

languages 是共用同一份術語索引的所有語言。中文各地區代碼(zh-TW/zh-CN/zh-HK 等) 在字庫比對上視為同一群,所以它們共用一筆衝突,而不是各報一次。

"homophone_conflicts": [
  { "languages": ["zh-TW"], "terms": ["公事包", "公式包"] }
]

tts_ready

說明

TTS 語音合成完成事件。包含音訊資料和 Word Boundary 資訊(可用於卡拉 OK 效果)。

{
  "type": "voice-translation",
  "data": {
    "action": "tts_ready",
    "sid": 1,
    "language": "en-US",
    "transcript": "你好,很高興認識你",
    "text": "Hello, nice to meet you",
    "audio": "Base64EncodedMP3...",
    "format": "mp3",
    "duration_ms": 2500,
    "boundaries": [
      {"offset_ms": 0, "duration_ms": 350, "text_offset": 0, "word_length": 5, "text": "Hello", "boundary_type": "WordBoundary"},
      {"offset_ms": 350, "duration_ms": 100, "text_offset": 5, "word_length": 1, "text": ",", "boundary_type": "PunctuationBoundary"},
      {"offset_ms": 500, "duration_ms": 250, "text_offset": 7, "word_length": 4, "text": "nice", "boundary_type": "WordBoundary"},
      {"offset_ms": 750, "duration_ms": 200, "text_offset": 12, "word_length": 2, "text": "to", "boundary_type": "WordBoundary"},
      {"offset_ms": 950, "duration_ms": 350, "text_offset": 15, "word_length": 4, "text": "meet", "boundary_type": "WordBoundary"},
      {"offset_ms": 1300, "duration_ms": 300, "text_offset": 20, "word_length": 3, "text": "you", "boundary_type": "WordBoundary"}
    ]
  }
}

欄位說明

欄位類型說明
sidint句子編號
languagestringTTS 語言
transcriptstring原始逐字稿(STT 識別結果)
textstring翻譯文字(TTS 合成來源)
audiostringBase64 編碼的 MP3 音訊
formatstring音訊格式(固定為 mp3)
duration_msint音訊總時長(毫秒)
boundariesarrayWord Boundary 陣列

Word Boundary 欄位說明

欄位類型說明
offset_msint該字詞在音訊中的起始時間(毫秒)
duration_msint該字詞持續時間(毫秒)
text_offsetint在原文字串中的位置(字元索引)
word_lengthint字詞長度(字元數)
textstring字詞內容
boundary_typestring邊界類型,常見值:WordBoundary、PunctuationBoundary、SentenceBoundary 等

tts_error

說明

TTS 合成失敗事件。

{
  "type": "voice-translation",
  "data": {
    "action": "tts_error",
    "sid": 1,
    "language": "en-US",
    "error": "translation_not_found",
    "message": "No translation available for language: en-US"
  }
}

欄位說明

欄位類型說明
sidint句子編號
languagestringTTS 語言
errorstring錯誤碼
messagestring錯誤訊息
transcriptstring對應原始逐字稿,便於前端定位失敗位置。此欄位一律存在,找不到句子時為空字串 ""

TTS 錯誤碼

錯誤碼說明
sentence_not_found找不到指定的句子(tts_play 帶的 sid 不存在)
translation_not_found找不到該語言的翻譯
tts_invalid_language不支援的 TTS 語言
tts_invalid_voice語音名稱無效
tts_connection_failed語音合成服務連線失敗
tts_timeout語音合成逾時
tts_synthesis_failed語音合成失敗

viewer_count

廣播模式專用

說明

廣播進行中,觀眾人數有變動時會推送此事件給主講者;更新頻率最快約每 3 秒一次。

{
  "type": "voice-translation",
  "data": {
    "action": "viewer_count",
    "viewer_count": 45,
    "queue_count": 8,
    "peak_viewers": 50,
    "total_viewers": 123
  }
}

欄位說明

欄位類型說明
viewer_countint目前在線觀眾數
queue_countint排隊等待中的觀眾數
peak_viewersint本次廣播峰值觀眾數
total_viewersint累計曾連線的觀眾總數

注意:此事件僅在觀眾人數或排隊人數有變動時才會推送,避免不必要的訊息傳輸。


broadcast_phase_changed

說明

當廣播階段從預備(standby)切換到正式(live)時觸發。

{
  "type": "voice-translation",
  "data": {
    "action": "broadcast_phase_changed",
    "phase": "live",
    "message": "廣播已開始"
  }
}

欄位說明

欄位類型說明
phasestring新的階段:standby 或 live
messagestring狀態描述訊息

broadcast_recording_ready

說明

廣播正式開播(live)後觸發,帶回本場廣播定案後的 task_id。

  • start 時直接指定正式開播(broadcast_phase: "live",預設)時,本事件一定在 session_started 之後送達。
  • 主講者斷線後,在寬限期內用同一個 broadcast_token 重新 start(接管),新連線收到的本事件會帶新的 task_id。同一場廣播因此會有接管前、接管後兩筆錄音,各自完成、各自送出完成通知。

session_started 帶的 task_id 是連線階段的初始值,不是本場廣播的最終 ID。不論是經預備階段(standby)轉正式開播、或 start 時直接指定正式開播(broadcast_phase: "live",預設),都會在開播後收到本事件。後續操作(例如換取浮動字幕 Feed Token)須以本事件的 task_id 為準——使用初始值會查無資料。

{
  "type": "voice-translation",
  "data": {
    "action": "broadcast_recording_ready",
    "task_id": "3f9a1c2e-..."
  }
}

欄位說明

欄位類型說明
task_idstring本場廣播定案後的錄音 ID(正式開播後有效)

speaker_renamed

說明

全域重命名說話者完成事件。

{
  "type": "voice-translation",
  "data": {
    "action": "speaker_renamed",
    "speaker_id": "Guest-1",
    "new_label": "王經理",
    "affected_sids": [1, 3, 5, 8]
  }
}

欄位說明

欄位類型說明
speaker_idstring解析後的原始語者 ID(即使輸入是顯示標籤,事件回傳仍是原始 ID)
new_labelstring新顯示標籤
affected_sidsint[]受影響的句子編號列表

speaker_reassigned

說明

修改單句語者身份完成事件。

{
  "type": "voice-translation",
  "data": {
    "action": "speaker_reassigned",
    "sid": 5,
    "old_speaker_id": "Guest-1",
    "new_speaker_id": "Guest-2",
    "new_speaker_label": "李小華"
  }
}

欄位說明

欄位類型說明
sidint修改的句子編號
old_speaker_idstring原始語者 ID
new_speaker_idstring新的原始語者 ID
new_speaker_labelstring新語者顯示標籤(套用 speaker_aliases 後;無 alias 時等於 new_speaker_id)

speakers_merged

說明

語者合併完成事件。合併後,該 source 語者未來產生的辨識結果也會自動轉換為 target 語者(僅限當前辨識工作:連線中斷後恢復會重新編號,屆時需重新合併)。

{
  "type": "voice-translation",
  "data": {
    "action": "speakers_merged",
    "source_speaker_id": "Guest-2",
    "target_speaker_id": "Guest-1",
    "affected_sids": [3, 5, 7]
  }
}

欄位說明

欄位類型說明
source_speaker_idstring被合併的原始語者 ID
target_speaker_idstring合併目標的原始語者 ID
affected_sidsnumber[]受影響的句子 ID 列表:原屬來源語者的句子,加上顯示名稱因合併而改變的目標語者原有句子(例如來源語者的自訂名稱轉給目標語者時)

若需取得 target 語者顯示標籤,請查詢 speaker_aliases 或下次 init_metadata 事件。


language_switch_start

說明

語言切換開始事件,在 switch_language action 觸發後送出。

{
  "type": "voice-translation",
  "data": {
    "action": "language_switch_start",
    "translation_language": "ja-JP",
    "translation_languages": ["en-US", "ja-JP"],
    "total_segments": 15
  }
}

欄位說明

欄位類型說明
translation_languagestring本次操作的單一語言(置換的新目標,或 op:add 新增的語言)
translation_languagesstring[]當前完整翻譯語言集的權威快照。多語場次 op:add 時為「含既有語言的完整集」,消費端應直接以此覆寫本地語言集,不要從 translation_language 推測是「附加」或「置換」(1→2 附加時只看單一語言會誤判為置換而洗掉既有語言)。
total_segmentsint需要重新翻譯的句子數

batch_retranslation

說明

批次重翻結果事件,在語言切換過程中逐句送出。

{
  "type": "voice-translation",
  "data": {
    "action": "batch_retranslation",
    "sid": 3,
    "translations": {
      "ja-JP": {
        "sid": 3,
        "text": "今日はプロジェクトの進捗について話し合いましょう",
        "is_final": true,
        "is_retranslation": true
      }
    }
  }
}

欄位說明

欄位類型說明
sidint句子編號
translationsobject翻譯結果(格式同 result 的 translations)

language_switch_done

說明

語言切換完成事件。

{
  "type": "voice-translation",
  "data": {
    "action": "language_switch_done",
    "translation_language": "ja-JP",
    "translation_languages": ["en-US", "ja-JP"],
    "success_count": 15,
    "failed_count": 2,
    "failed_sids": [3, 7]
  }
}

欄位說明

欄位類型說明
translation_languagestring本次操作的單一語言
translation_languagesstring[]當前完整翻譯語言集的權威快照(同 language_switch_start,消費端直接覆寫本地語言集)
success_countint成功翻譯的句子數
failed_countint翻譯失敗的句子數
failed_sidsint[]翻譯失敗的句子編號列表(failed_count > 0 時才包含)

translation_language_removed

說明

翻譯語言移除成功事件(v1.6.7 新增)。多語言場次送出 switch_language(op: "remove")成功時回傳。該語言既有的歷史譯文保留,後續新句子不再翻譯該語言。

{
  "type": "voice-translation",
  "data": {
    "action": "translation_language_removed",
    "translation_language": "ko-KR",
    "translation_languages": ["en-US", "ja-JP"]
  }
}

欄位說明

欄位類型說明
translation_languagestring已移除的翻譯語言
translation_languagesstring[]移除後的完整翻譯語言集權威快照,消費端直接以此覆寫本地語言集

tts_mode_changed

說明

TTS 播放模式變更事件。

{
  "type": "voice-translation",
  "data": {
    "action": "tts_mode_changed",
    "tts_mode": "async"
  }
}

欄位說明

欄位類型說明
tts_modestring新的模式:sync 或 async

language_switched

說明

互譯模式(conversation)語言切換完成事件。當 switch_language 在互譯模式下成功切換 STT 來源語言後觸發。

{
  "type": "voice-translation",
  "data": {
    "action": "language_switched",
    "language": "en-US",
    "translation_language": "zh-TW",
    "message": "語言已切換"
  }
}

欄位說明

欄位類型說明
languagestring新的 active 語言(STT 來源)
translation_languagestring新的翻譯目標語言
messagestring狀態訊息

tts_updated

說明

互譯模式(conversation)TTS 設定更新事件。當 set_tts 成功更新 TTS 開關或語音設定後觸發。

{
  "type": "voice-translation",
  "data": {
    "action": "tts_updated",
    "tts_enabled": true,
    "tts_config": {
      "zh-TW": { "voice": "zh-TW-HsiaoChenNeural", "speaking_rate": 1.0 },
      "en-US": { "voice": "en-US-GuyNeural", "speaking_rate": 1.2 }
    }
  }
}

欄位說明

欄位類型說明
tts_enabledbooleanTTS 是否啟用
tts_configobject各語言的 TTS 設定(voice、speaking_rate)

conversation_mode_changed

說明

互譯模式(conversation)對話模式變更事件。當 switch_conversation_mode 成功切換自動/手動模式後觸發。

{
  "type": "voice-translation",
  "data": {
    "action": "conversation_mode_changed",
    "conversation_mode": "manual"
  }
}

欄位說明

欄位類型說明
conversation_modestring新的對話模式:auto 或 manual

speaker_language_changed

說明

互譯模式(conversation)用戶語言變更事件。當 set_speaker_language 成功變更用戶語言後觸發,包含變更後的完整語言映射。

{
  "type": "voice-translation",
  "data": {
    "action": "speaker_language_changed",
    "speaker_language_map": {
      "1": "ja-JP",
      "2": "en-US"
    }
  }
}

欄位說明

欄位類型說明
speaker_language_mapobject變更後的用戶語言映射(key 為用戶編號字串)

speaking_speed_changed

說明

錄音中語速變更事件。當 set_speaking_speed 成功套用新語速(重建 STT 完成)後觸發,帶回已套用的語速等級。非多人(multi_speaker)辨識模式皆支援(含廣播、多語 LID)。

{
  "type": "voice-translation",
  "data": {
    "action": "speaking_speed_changed",
    "speaking_speed": "slow"
  }
}

欄位說明

欄位類型說明
speaking_speedstring已套用的語速:very_slow / slow / normal / fast / very_fast

summary_updated

說明

錄音中摘要設定更新事件。當 set_summary 成功套用後觸發,帶回當前生效的摘要設定。

基於安全考量,事件不包含 summary_prompt 全文;custom 模式請以 summary_prompt_slug 辨識。

{
  "type": "voice-translation",
  "data": {
    "action": "summary_updated",
    "summary_mode": "custom",
    "summary_prompt_slug": "meeting-actions-v2",
    "summary_language": "zh-TW",
    "auto_summary": true,
    "summary_plain_text": false,
    "message": "摘要設定已更新"
  }
}

欄位說明

欄位類型說明
summary_modestring當前摘要模式:builtin / custom
summary_templatestring當前通用樣板識別碼(builtin 模式才有值)
summary_prompt_slugstring當前自訂 prompt 識別碼(custom 模式才有值)
summary_languagestring當前摘要輸出語言
auto_summaryboolean停止時是否自動生成摘要
summary_plain_textboolean是否以純文字輸出
messagestring狀態訊息

segment_uploaded

說明

音訊分段上傳完成事件。每當一個音訊片段成功上傳至雲端儲存時觸發,可用於前端顯示上傳進度。

{
  "type": "voice-translation",
  "data": {
    "action": "segment_uploaded",
    "segment_index": 0,
    "duration_sec": 30.5
  }
}

欄位說明

欄位類型說明
segment_indexnumber分段索引(從 0 開始)
duration_secnumber該分段的時長(秒)

stt_event

說明

STT 連線狀態事件。當語音辨識服務的連線狀態發生變化時觸發,可用於前端顯示 STT 服務狀態。

{
  "type": "voice-translation",
  "data": {
    "action": "stt_event",
    "event": "reconnected",
    "message": "STT 已重連"
  }
}

欄位說明

欄位類型說明
eventstring事件類型:session_started(辨識會話建立)/session_stopped(辨識會話結束)/canceled(辨識被中止,原因見 message)/reconnecting(連線異常,自動重連中)/reconnected(已重新連線)
messagestring事件描述訊息。內容不保證固定,請一律以 event 判斷狀態

channel_status

多聲道模式(multi_channel)專用

說明

聲道狀態變更事件。多聲道場次中,任何一路聲道的狀態改變時觸發:add_channel / remove_channel 的成功回應、set_channel_language / set_speaking_speed 觸發的設定切換、暫停後恢復(resume)、異常自動重連,以及該路異常且無法自動恢復時。前端可據此逐路顯示即時狀態(例如新路準備中的載入指示、異常路的警示)。

{
  "type": "voice-translation",
  "data": {
    "action": "channel_status",
    "channel": {
      "channel_id": 3,
      "speaker_name": "王經理",
      "transcription_languages": ["ja-JP"],
      "status": "preparing"
    },
    "active_channels": 3,
    "stt_stream_count": 3,
    "reason": "added"
  }
}

欄位說明

欄位類型說明
channelobject狀態變更的聲道快照,欄位同 session_started 的 channels[] 元素(channel_id、speaker_name、transcription_languages、status)
channel.statusstring該路目前狀態:preparing / ready / removed / error(見下方狀態機)
active_channelsint目前仍在收音的聲道數(不含已移除的路)
stt_stream_countint當下採計的辨識路數(每一分鐘開始時依此計費;remove_channel 後立即下降);shared 模式固定為 1
reasonstring可選。狀態變更原因:added / language_change / reconnect / resumed / removed / speaking_speed / stt_error(見下表)。省略時代表該路首次就緒(見狀態機說明)

reason 值域

reason觸發時機
addedadd_channel 新增一路(狀態轉 preparing)
language_changeset_channel_language 切換語言
reconnect該路異常後自動重連;斷線續接(resume_token)後的恢復亦用此原因
resumed暫停後恢復(resume),各路重新準備
removedremove_channel 停用一路(狀態轉 removed)
speaking_speedset_speaking_speed 逐路套用新設定
stt_error該路異常且無法自動恢復(狀態轉 error)

status 狀態機

  • preparing:每一次該路開始或重新準備辨識都會回到此狀態——start 的初始建立、add_channel 的加入、set_channel_language / set_speaking_speed 的設定切換、自動重連與暫停後恢復。此期間該路約需 4 秒完成準備,講的話不會丟失、只是延遲出字;唯獨切換或重連當下正說到一半的那一句無法保留,會另外收到 segment_discarded。
  • ready:該路收到第一個辨識結果(開始出字)時轉入。由設定切換觸發的 ready 事件沿用觸發該次 preparing 的同一 reason,讓前端把「這一次就緒」對回「哪一次操作」;start 與 add_channel 後的首次就緒不帶 reason。
  • removed:該路被 remove_channel 停用。已產生的逐字稿與音檔保留;該編號不可再重用(含 add_channel)。
  • error:該路異常且無法自動恢復(reason: "stt_error")。該路後續若自動恢復,會再依 preparing(reason: "reconnect")→ ready 回報,或於恢復出字時直接轉 ready。

shared 模式:只有第一路(channels[] 的第一個元素)實際進行辨識,其他聲道的 preparing/ready/error 跟著第一路——第一路轉 ready 時全部一起轉 ready,第一路重新準備辨識時全部一起回到 preparing;每一路各收到一則事件,reason 與第一路相同。add_channel 新增的聲道直接套用第一路當下的狀態;removed 依各路自己。第一路變成 error 時,其他聲道也一起變成 error(reason 相同);第一路恢復時一起恢復。

這四個狀態值與 session_started 的 channels[].status、resume_ok 的 settings.channels[].status 快照一致——斷線續接後請以快照還原各路的狀態顯示(error 也會出現在快照中,不會被漂白)。

時序範例(add_channel)

→ 送出 add_channel(channel_id: 3、語言 ja-JP)
← channel_status  channel.status: "preparing"、reason: "added"、
                  active_channels: 3、stt_stream_count: 3
   (約 4 秒準備期;期間第 3 路的音訊照常送、不會丟失,僅延遲出字)
← channel_status  channel.status: "ready"(不帶 reason)
   (該路首次出字;此後該路的 result 事件 origin 帶
     channel_id: 3、speaker_id: "channel_3")

時序範例(set_channel_language)

→ 送出 set_channel_language(channel_id: 2、換為 en-US)
← channel_status  channel.status: "preparing"、reason: "language_change"
   (切換約 4 秒後生效;channel_id 與 speaker_id 不變、逐字稿連續)
← channel_status  channel.status: "ready"、reason: "language_change"

segment_discarded

說明

句子作廢通知。告知某個 sid 已作廢,不會再有任何後續事件 —— 不會有該句 is_final: true 的原文,也不會有該句的翻譯。

有些操作會讓辨識中斷,若當下正好有一句話說到一半,那一句無法保留。前端可能已經收到過該句 is_final: false 的中間結果,收到本事件後請把該 sid 從「翻譯中」狀態移除。

互譯模式(自動與手動)不會收到本事件 —— 自動模式下,說到一半的句子會直接以 is_final: true 收尾送出;手動模式下,說話期間辨識若中途重建(例如改語速、連線恢復),那一段會併入該句的定稿。內容都保留在逐字稿中。

{
  "type": "voice-translation",
  "data": {
    "action": "segment_discarded",
    "sid": 7,
    "reason": "speaking_speed",
    "channel_id": 1
  }
}

欄位說明

欄位類型說明
sidint被作廢的句子編號
reasonstring作廢原因:speaking_speed / language_change / reconnect / resumed / broadcast_go_live(見下表)
channel_idint可選。來源聲道編號;僅多聲道模式帶,其餘模式不帶

reason 值域

reason觸發時機
speaking_speedset_speaking_speed 套用新語速
language_changeset_channel_language 切換該路語言
reconnect辨識連線異常後自動重連
resumed斷線續接(resume_token),或暫停後恢復(resume)
broadcast_go_livebroadcast_go_live 由預備進入直播;預備階段的句子不進正式逐字稿

前四個值與 channel_status 的 reason 是同一組值,可據以把兩個事件對應到同一次操作。例外是斷線續接(resume_token):channel_status 用 reconnect,本事件用 resumed。

set_speaking_speed 失敗(set_speaking_speed_failed)時仍可能已經收到本事件 —— 辨識在重建之前就已中斷,該句無論重建成敗都保不住。收到失敗回應不代表「什麼都沒發生」。


viewer_joined

說明

觀眾加入事件(僅廣播模式)。當觀眾加入廣播時,主講者會收到此事件。

{
  "type": "voice-translation",
  "data": {
    "action": "viewer_joined",
    "viewer": {
      "id": "viewer_abc123",
      "ip": "192.168.1.100",
      "language": "zh-TW"
    },
    "viewer_count": 5,
    "queue_count": 2
  }
}

欄位說明

欄位類型說明
viewerobject加入的觀眾資訊
viewer.idstring觀眾 ID
viewer.ipstring觀眾 IP 地址
viewer.languagestring觀眾選擇的語言
viewer_countnumber目前觀眾人數
queue_countnumber排隊中的人數

viewer_left

說明

觀眾離開事件(僅廣播模式)。當觀眾離開廣播時,主講者會收到此事件。

{
  "type": "voice-translation",
  "data": {
    "action": "viewer_left",
    "viewer_id": "viewer_abc123",
    "viewer_count": 4,
    "queue_count": 1
  }
}

欄位說明

欄位類型說明
viewer_idstring離開的觀眾 ID
viewer_countnumber目前觀眾人數
queue_countnumber排隊中的人數

error

說明

錯誤事件。當操作失敗或系統異常時觸發。

{
  "type": "error",
  "data": {
    "error_code": "session_not_started",
    "severity": "error",
    "message": "語音辨識尚未開始",
    "context": "voice-translation",
    "request_id": "req_abc123xyz789",
    "timestamp": "2026-01-15T10:30:45.123Z"
  }
}

句子級錯誤(如某句的某個語言翻譯失敗)會額外帶上 sid 與 details:

{
  "type": "error",
  "data": {
    "error_code": "llm_content_filtered",
    "severity": "warning",
    "message": "LLM 內容被過濾",
    "context": "translation",
    "sid": 5,
    "request_id": "req_abc123xyz789",
    "timestamp": "2026-04-26T10:30:45.123Z",
    "details": {
      "provider": "llm_service",
      "source_lang": "zh-TW",
      "translation_language": "ja-JP"
    }
  }
}

欄位說明

欄位類型說明
error_codestring錯誤碼(程式化處理用)
severitystring嚴重程度:fatal / error / warning
messagestring人類可讀的錯誤訊息
contextstring錯誤來源分類
sidint可選。句子級錯誤的句子編號(如該句翻譯失敗);非句子級錯誤不帶
request_idstring請求追蹤 ID
timestampstring錯誤發生時間(ISO 8601)
detailsobject可選。錯誤上下文,常見 key:provider、translation_language、source_lang;internal_error(單則訊息處理失敗)會額外帶 message_type(必有)與 action(best-effort,解析失敗時不出現),詳見 websocket-api.md 單一訊息錯誤

嚴重程度說明

severity說明處理建議
fatal致命錯誤停止服務,要求重新連線
error操作失敗顯示錯誤提示,允許重試
warning警告顯示警告,不阻斷操作

warning 等級的預警不代表錄音結束,例如 stt_silence_warning(即將因為沒有語音而自動結束)、broadcast_standby_warning(預備階段即將達到時間上限)。錄音照常進行,真正結束時會另外收到對應的 fatal 錯誤與 status: "ended"。

完整錯誤碼列表請參考 錯誤碼參考。


upload_error

v1.5.6 文件修正:早期文件描述 type: "voice-translation" + action: "upload_error" 的獨立事件格式,但實際 wire 上從未送出此格式。儲存上傳失敗一律走統一 error envelope,錯誤碼為下表三者之一。

若你的 client 監聽 action === "upload_error",應改為監聽 type === "error" 並比對 error_code。

儲存層錯誤碼(透過 error 事件送出)

錯誤碼說明
storage_connection_failed儲存服務連線失敗
storage_upload_failed檔案上傳失敗
storage_queue_full上傳佇列已滿

speakers_auto_merged

多人模式下,系統判定兩個說話者其實是同一人並自動合併時送出。

{
  "type": "voice-translation",
  "data": {
    "action": "speakers_auto_merged",
    "source_speaker_id": "Guest-2",
    "target_speaker_id": "Guest-1"
  }
}
欄位類型說明
source_speaker_idstring被合併掉的說話者
target_speaker_idstring合併後保留的說話者

自動合併通常發生在尚未產生任何逐字稿條目時,因此不帶受影響的句子清單。客戶端收到後把本地的說話者清單中 source_speaker_id 併入 target_speaker_id 即可。


summary_done

說明

錄音停止後、Server 端非串流摘要生成完成時推送的事件。客戶端收到此事件後可呼叫 GET /api/v1/sse/history/transcribe/{taskId} 取得摘要內容(payload 不含 final_content,避免 WebSocket 訊息肥大)。

v1.5.5 新增 summary_fallback_level / summary_dropped_segments 兩個 fallback 審計欄位:當 custom prompt 或逐字稿內容觸發 LLM 服務內容過濾時,系統會自動降級重新產生摘要(標準模式 → 中性模式 → 段落省略模式),並透過這兩欄通知客戶端實際走的路徑。

範例

標準模式直接成功(無 fallback、未觸發過濾):

{
  "type": "voice-translation",
  "data": {
    "action": "summary_done",
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "summary_id": "sum_a1b2c3d4e5f6g7h8",
    "summary_mode": "custom",
    "summary_template": "skin-clinic-acme-v2",
    "summary_plain_text": true,
    "tokens_used": { "input": 1234, "output": 567 }
  }
}

段落省略模式觸發(省略部分逐字稿段落後產出摘要):

{
  "type": "voice-translation",
  "data": {
    "action": "summary_done",
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "summary_id": "sum_a1b2c3d4e5f6g7h8",
    "summary_mode": "custom",
    "summary_template": "skin-clinic-acme-v2",
    "summary_plain_text": true,
    "tokens_used": { "input": 3456, "output": 789 },
    "summary_fallback_level": 3,
    "summary_dropped_segments": [3, 7]
  }
}

欄位說明

欄位類型說明
actionstring固定為 summary_done
task_idstringRecording UUID
summary_idstring此次摘要的內部 ID
summary_modestring"builtin" 或 "custom"
summary_templatestringeffective slug — builtin → 內建模板 slug(如 meeting);custom → 客戶 slug
summary_plain_textboolean是否為純文字輸出
tokens_used.input / .outputintToken 用量(觸發 fallback 時為本次摘要所有生成請求的累計值)
summary_fallback_levelint (omit)僅 fallback 觸發時出現(2 或 3),標準模式直接成功則 omit。2=中性模式(改用中性指令重新生成);3=段落省略模式(省略觸發段落後重新生成)
summary_dropped_segmentsint[] (omit)僅 fallback_level=3 時出現,被剝除的逐字稿段 indices(原序)

Fallback level 解讀(供前端 UI 對應提示)

summary_fallback_level意義建議 UI 提示
(欄位 omit)標準模式直接成功,無 fallback不顯示提示
2Customer prompt 觸發過濾,改用中性 fallback prompt「您的自訂指令含內容過濾機制無法處理的詞彙,已使用中性模式產生摘要」
3逐字稿內容觸發過濾,自動定位並省略觸發段落後產出「逐字稿含 N 段無法處理,已省略相關內容後產生摘要」(N = summary_dropped_segments.length)

段落省略模式仍失敗時不會發送 summary_done,而是 summary_error with error_code=llm_content_filtered(見下方 §summary_error)。

注意:payload 刻意不含 final_content。客戶端需自行呼叫 GET /api/v1/sse/history/transcribe/{taskId} 取得摘要全文。summary_fallback_level 與 summary_dropped_segments 也會在歷史回放時透過 init_summary event 的 top-level 欄位提供。


summary_error

說明

摘要生成失敗,或因可用點數不足而未產生摘要時推送的事件,客戶端不需要再輪詢判斷。

範例

{
  "type": "voice-translation",
  "data": {
    "action": "summary_error",
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "error_code": "summary_failed",
    "message": "摘要生成失敗"
  }
}

欄位說明

欄位類型說明
actionstring固定為 summary_error
task_idstringRecording UUID
error_codestring摘要錯誤碼(如 summary_failed / summary_timeout / summary_mode_field_mismatch / summary_insufficient_credit 等)
messagestring人類可讀錯誤訊息(已 sanitize,不含 LLM raw error)

error_code 為 summary_insufficient_credit 時,表示可用點數不足(錄音因點數不足而結束,或結束時點數不足以支付摘要費用);逐字稿與錄音照常保存,儲值後可透過重新生成摘要取得。


版本:V1.24.1 最後更新:2026-10-07

Copyright © 2026