跳到主要內容
節省工具箱Jason Tools
專案分享

jt-vc-portal(二):會議逐字稿與摘要

Jason Cheng 發布 瀏覽 2 次
jt-vc-portal(二):會議逐字稿與摘要
本文目錄
  1. 整合緣由
  2. 運作流程
  3. 建立會議室時決定是否產生逐字稿
  4. 錄影記錄與處理狀態
  5. 會議摘要
  6. 逐字稿與發言者對應
  7. 會議記錄匯出
  8. 權限控管
  9. 設定步驟
  10. 資料安全
  11. 結論
  12. 參考資料

之前寫過一篇〈jt-vc-portal:替 Jitsi Meet 補上會議管理入口〉,介紹我替 Jitsi Meet 做的會議管理入口:建立會議室、邀請來賓、帳號權限、稽核記錄,以及搭配自建 Jibri 的錄影調閱。

這幾個月 jt-vc-portal 最大的進展,是和我另一個專案 jt-live-whisper(以下簡稱 JTLW)整合:會議錄影完成後,自動產生含發言者的逐字稿與會議摘要,決議、待辦、風險每一條都附錄影時間點,點一下就跳到錄影的那個位置播放。整個流程都在自己的主機上完成,錄影與逐字稿不會送到任何雲端服務。

整合緣由

視訊會議開完,最花時間的往往是會後整理:誰說了什麼、決議了哪些事、誰負責哪個待辦、期限是什麼時候。有錄影當然可以回頭看,但一場一小時的會議,要從錄影裡找出某個決議是在哪裡講的,並不容易。

市面上的雲端會議服務大多已經有 AI 會議記錄,但對很多企業與公部門來說,會議錄影與內容不能離開自己的環境,這也是當初選擇自建 Jitsi Meet 的原因之一。

JTLW 本來就是全地端的 AI 語音工具箱,語音辨識、發言者分離、逐字稿校正與摘要都在自有設備上推論。把兩者接起來,就能在不送出任何資料的前提下,讓自建的視訊會議也有會後自動整理的能力。

運作流程

整個流程分成三段:

  • 錄影:Jitsi Meet 會議由 Jibri 錄影,錄影檔存在 Jibri 主機上,由 jibri-recordings-api 提供調閱
  • 送件:jt-vc-portal 以 token 向 Jibri 主機取得錄影檔,以串流方式上傳給 JTLW
  • 處理與取回:JTLW 依序完成語音辨識、發言者分離、逐字稿校正與摘要,完成後以 webhook 通知 portal;portal 取回結果寫入磁碟後,再通知 JTLW 刪除它那邊的副本

幾個設計重點:

  • portal 本身不連任何語言模型:辨識與摘要都在 JTLW 完成,用哪個模型由 JTLW 端設定
  • 背景排程每分鐘執行一次:負責送件、追蹤進度、取回結果;一次上傳一筆錄影,大檔上傳中下一輪會自動跳過
  • webhook 是選用的:JTLW 連不到 portal 時也能運作,排程每分鐘會主動查詢一次進度
  • 結果跟著錄影走:刪除錄影,或 Jibri 的保留政策清掉錄影時,逐字稿與摘要也一併刪除

注意:只支援自建 Jitsi Meet + Jibri。8x8 JaaS 模式的錄影存在 8x8 雲端,portal 拿不到檔案,無法產生逐字稿。

建立會議室時決定是否產生逐字稿

有逐字稿權限的主持人,建立會議室時會多一個「錄影完成後產生逐字稿與摘要」選項,預設勾選;不需要的場次取消勾選即可。

勾選時必須選擇會議主要語言,語音服務會依這個選擇挑選辨識模型:

  • 中文、英文、日文、韓文為主:一般辨識模式,並做發言者分離。會議摘要支援中文與英文,日文、韓文只產生逐字稿
  • 台語(閩南語)為主:改用台語專用的 MediaTek Breeze-ASR-26 模型,直接輸出華語漢字;這個模式不做發言者分離,摘要僅供參考

夾雜多種語言時,選講最多的那一種。會議中有台語就選台語,只偶爾一兩句台語的會議選「中文為主」,才能分出發言者。語音服務不會自動判斷台語,所以一定要在這裡指定。

建立會議室:勾選「錄影完成後產生逐字稿與摘要」,並選擇會議主要語言
建立會議室:勾選「錄影完成後產生逐字稿與摘要」,並選擇會議主要語言

錄影記錄與處理狀態

錄影記錄頁多了「主要語言」與「逐字稿」兩欄,每一場會議的處理狀態一目了然:

  • 查看逐字稿與摘要(綠色):已完成,點進去檢視
  • 處理中:排隊或處理中,可以取消
  • 產生失敗 / 等待重試:滑過或展開可以看到原因
  • 產生逐字稿(虛線框):尚未產生,按下即排入處理

辨識暫時失敗時(例如語音服務的 GPU 伺服器暫時不能用),會在 10、30、60 分鐘後自動重試,不需要重新上傳錄影;摘要因語言模型暫時故障而失敗時,也會自動重做摘要、保留已完成的逐字稿。

錄影記錄:每場會議的主要語言與逐字稿處理狀態,展開可看參與者進出時間
錄影記錄:每場會議的主要語言與逐字稿處理狀態,展開可看參與者進出時間

會議摘要

逐字稿檢視頁最上方是會議摘要,內容包含:

  • 重點摘要:整場會議的重點整理
  • 決議與待辦:待辦會列出負責人與期限
  • 事件與影響、風險、未決問題
  • 議題時間軸:會議依序討論了哪些議題
  • 發言統計:每個人講了多久

每一條都附錄影時間點與發言者,點一下就跳到錄影該處播放,並標亮對應的逐字稿段落。要確認某個決議當時是怎麼說的,不必再拖著進度條找。

會議摘要:決議與待辦附負責人、期限,每條都有錄影時間點與發言者
會議摘要:決議與待辦附負責人、期限,每條都有錄影時間點與發言者

逐字稿與發言者對應

逐字稿依發言者分色顯示,上方是整段錄影的波形播放器,播放時逐字稿會跟著自動捲動,點任一段的時間也能跳到該處播放。

發言者改名

語音服務分出來的發言者代號(S1、S2…)是依聲音分群,不是人名。點名字就能改名,預設同一個代號全部一起改,也可以只改單一段落。改好的名字會套用到摘要內文、負責人與所有匯出檔。

發言者對應建議

這是我覺得最實用的一個功能。主持人開著會議頁時,portal 會記錄 Jitsi 本身偵測到的「目前發言者」時間軸,逐字稿頁會拿這條時間軸跟 S1、S2 的發言時間比對,列出建議的參與者與重疊比例,例如「S1 → 王經理 91%」,按一下「全部套用最可能的人」就完成改名。

注意:主持人的會議頁要全程開著,發言者時間軸才完整;中途關閉的場次仍可手動改名。

逐字稿:依 Jitsi 發言者時間軸建議 S1、S2 各是哪位參與者,可一鍵套用
逐字稿:依 Jitsi 發言者時間軸建議 S1、S2 各是哪位參與者,可一鍵套用

發言者辨識方式

v1.17.0 起,portal 送件時會要求 JTLW 使用較新的發言者辨識(NVIDIA Nemotron 3 Diarization)。依 JTLW 的實測,7 人座談從原本「分成 3 位」改善為「分成 7 位」,段落發言者錯誤率由 28% 降到 3%,摘要裡的發言統計與引用也跟著變準。發言者超過 8 位時,JTLW 會自動改用舊方法,逐字稿頁也會提醒分組可能較不準。

會議記錄匯出

整份會議記錄(會議資訊、摘要、議題、發言統計、逐字稿)可以匯出成:

格式說明
PDF內嵌 Noto Sans TC 字型,中日文正常顯示,可選取與搜尋
DOCX / ODT可以用 Microsoft Word 或 LibreOffice 繼續編輯
HTML單一檔案、樣式內嵌、不含 script,手機閱讀與列印都正常
其他純文字、SRT 字幕、JSON、摘要 Markdown

所有格式都會套用改好的發言者名稱。這些檔案全部由 portal 自己產生,主機上不需要安裝 LibreOffice 或瀏覽器引擎。

匯出的 PDF 會議記錄:會議資訊、重點摘要、決議與待辦、事件與影響
匯出的 PDF 會議記錄:會議資訊、重點摘要、決議與待辦、事件與影響

權限控管

逐字稿牽涉會議內容,權限分成三層:

層級設定位置說明
帳號帳號管理的「逐字稿權限」不可使用(預設)、手動、自動
單場建立會議室時的選項有權限的主持人才看得到,不能超過帳號權限
管理員不需另外設定可以對任何場次產生、取消、重新產生或刪除逐字稿

主持人只看得到自己主持場次的錄影與逐字稿。稽核記錄會記下誰產生、檢視、下載、改名或刪除逐字稿,但不會記錄逐字稿內容。

另外,第一次啟用這個功能的時間會被記下,自動產生只處理啟用之後錄的會議,不會把舊錄影一次全部送出去處理。舊錄影要產生逐字稿,在錄影記錄頁手動按「產生逐字稿」即可。

設定步驟

完整步驟請參考專案的 TRANSCRIPTS-SETUP_zh-TW.md,以下整理重點。

需求

  • 自建 Jitsi Meet + Jibri,Jibri 主機上已安裝 jibri-recordings-api,並已在 portal 的「系統設定 → 錄製設定」接上
  • jt-live-whisper 的 REST API api_revision 2.4 以上,一般部署在有 GPU 的主機,一次處理一件,其餘排隊
  • portal 主機要能連到 JTLW 的 API 連接埠(預設 HTTPS 8790);選用:JTLW 能連回 portal 的 /jtlw-webhook

JTLW 端:建立 API 金鑰

在 JTLW 主機上,替 portal 建立一把專用的 API 金鑰,權限範圍只給需要的四項:

cd <jt-live-whisper 安裝目錄>
venv/bin/python -m jtlw_api.keys add jtvc jobs:write jobs:read jobs:cancel profiles:read

金鑰只會顯示這一次,請妥善保存。請勿給 admin 權限,每個系統各用一把,金鑰只看得到自己送出的作業。

接著把 portal 主機的 IP 加進 JTLW config.json 的 api.allowed_hosts,然後重新啟動 API 服務:

sudo systemctl restart jtlw-api

JTLW 預設使用自簽憑證,取得憑證後先核對 SHA-256 指紋:

openssl x509 -in jtlw-api.crt -noout -fingerprint -sha256

portal 端:系統設定

在「系統設定 → 逐字稿與摘要」填入:

  • 語音服務(JTLW)網址:例如 https://192.168.1.30:8790,不用加 /api/v1
  • API 金鑰:上一步建立的金鑰
  • 語音服務的憑證:自簽憑證請貼上 PEM。portal 一律驗證憑證,不提供關閉檢查的選項,畫面上會顯示 SHA-256 指紋供核對
  • 預設會議語言、辨識模式、發言者辨識方式(建議選「自動」)、是否同時產生會議摘要

填好後依序按「儲存並測試連線」與「註冊 webhook」。webhook 的簽章密鑰由 JTLW 產生並自動存起來,之後每則通知都以 HMAC 驗證簽章。

系統設定:語音服務網址、API 金鑰、憑證、會議語言與發言者辨識方式
系統設定:語音服務網址、API 金鑰、憑證、會議語言與發言者辨識方式

背景排程

送件、查詢進度、取回結果都由每分鐘執行一次的排程完成。Docker 部署時在主機上加入:

# /etc/cron.d/jtvc-transcribe
* * * * * root docker exec -u www-data jt-vc-portal php /var/www/html/transcribe-worker.php >/dev/null 2>&1

直接安裝時:

# /etc/cron.d/jtvc-transcribe
* * * * * www-data php /var/www/jt-vc-portal/transcribe-worker.php >/dev/null 2>&1

要看詳細的處理過程,可以手動加上 -v 執行一次。排程超過 10 分鐘沒有執行時,系統設定頁的「逐字稿與摘要」卡片會顯示警示,不會默默停擺。

資料安全

這個整合從一開始就以「資料不離開自己環境」為前提設計:

  • 錄影以串流上傳到 JTLW,JTLW 處理完即刪除上傳檔;portal 取回結果並寫入磁碟後,才通知 JTLW 刪除作業記錄
  • portal 連 JTLW 一律驗證 TLS 憑證,自簽憑證以貼上的 PEM 信任,不會關閉驗證
  • webhook 以 HMAC 簽章並驗證時間窗,依事件 ID 去除重複
  • 送件帶 Idempotency-Key,網路中斷重送也不會重複處理
  • API 金鑰與 webhook 密鑰不會回填到頁面上

結論

jt-vc-portal 一開始只是想替 Jitsi Meet 補上會議管理的入口,加上 jt-live-whisper 之後,自建的視訊會議也有了會後自動整理的能力:開完會,逐字稿、摘要、決議與待辦就整理好了,每一條都能點回錄影確認。

對不能把會議內容交給雲端服務的單位來說,這應該是很實用的組合。兩個專案都是開源的,有自建 Jitsi Meet 的朋友可以參考看看。

參考資料

Jason Cheng

Jason Cheng

企業開源技術顧問,專注架構規劃與實務導入

關於作者 →

延伸閱讀