前陣子在臉書分享過用 AI 整理課程影片的成果,收到超乎想像的迴響,也一直有人問工具什麼時候放出來。整理了一陣子,今天正式開源:lecture-to-notes。
這篇的重點
- 為什麼課程錄影大家都在錄,卻沒有人回去看完
- 筆記不必是「文字+圖」的形狀:影片、逐字稿、總整理同步在一頁
- 手上有什麼就帶什麼來:錄影、錄音、投影片、照片,全部接上同一條時間軸
- 技術上堅持的幾件事:逐字稿永不自動改字、對時用證據不用猜
- 為什麼只有 OCR 不夠:沒有字的流程圖與超音波,怎麼判斷它重不重要
- 沒有 NVIDIA 顯卡也能跑的退階方案
教室後面的腳架森林
從以前就覺得復健科的課程很難做筆記。徒手治療、超音波掃描這種課,知識藏在「動作」裡,文字怎麼抄都抄不起來。所以現場永遠是滿滿的腳架,大家都在錄影,打算回去配飯複習。
但幾小時的影片,實際上根本不會回去看完。
想通的一個轉折:筆記不必是「文字+圖」的形狀
有了 AI 之後,我原本的思路是教它精準截圖,把影片塞回傳統「文字+圖片」的筆記形式。後來想通了:筆記不必拘泥於那個形狀。
直接做一個網頁,把影片跟逐字稿對上,想看哪段就跳到哪段。畢竟真正想知道的,是那個動作到底怎麼做——那只存在於影片裡。
所以最後的成品是三個層次疊在同一頁:
- 總整理拿來讀:結構化的重點筆記,配上當時的投影片
- 逐字稿拿來驗證:每句話都有時間戳
- 影片永遠在一鍵之外:影片播到哪,筆記自動高亮;點筆記的時間戳,影片直接跳過去

同一份內容還會輸出 markdown 進 Obsidian 筆記庫(之後語意搜尋找得到),以及 PDF 給不用這些工具的人。一堂課,三種耐久形態。


(截圖是一場頸椎超音波工作坊的實際輸出,日期與講者已馬賽克。)
手上有什麼就帶什麼來
真實的課程從來不會只有一支乾淨的錄影:有的講題錄了影、有的只錄到音、有的只用手機拍了投影片,會後主辦單位又補發一份 PDF 講義。
這個工具把資料夾原樣吃進去,自動判斷每個檔案扮演什麼角色,再把所有來源接上同一條時間軸——就算某張投影片從頭到尾沒出現在影片畫面裡,筆記引用到它的那一刻仍然指得回正確的時間點。
技術上堅持的幾件事
這個工具的設計目標不是「摘要一支影片」,而是可回溯(traceability):筆記裡每句話都要能指回逐字稿的某個時間點、以及當下螢幕上那張投影片。幾個為此堅持的設計:
貴的事情全部在本機跑
Whisper 轉錄、抽幀、OCR、投影片語意判讀,全部在自己的 GPU 上跑完,零 API 費用。大型語言模型只在最後一步負責「寫」,而且只能根據前面各階段已經組好的證據寫。就算不跑最後一步,你也已經拿到逐字稿、去重後的投影片集、和兩者的對應關係。
逐字稿永遠不自動改字
自動改錯字聽起來很誘人,我們實際做了兩版、量測、然後全部退役。現在可疑的詞只會被「標記」出來,逐字稿本身一個 byte 都不動。每個標記是一個問題,不是一個替換——因為改錯了你永遠不會發現。
對時:檔案時間是假說,交叉比對才是證據
一場演講常常不只一個裝置在錄:主錄影、手機片段、照片。要拼回同一條時間軸,最直覺的做法是相信每個檔案自己的拍攝時間——而手機時鐘會漂移、有些檔案只剩修改時間、按過暫停的錄影會謊報自己的開始時間。
所以管線把兩件事分開:拍攝時間當「主張」,重疊音訊的交叉比對當「證據」。兩者差超過 5 秒,就標記衝突並停下來問人,絕不自動修正。這擋掉的是「44 分鐘對錯位、但每一頁輸出看起來都很正常」的災難。
缺工具就大聲說,不悄悄降級
選用的模型都經過自己資料的評測(repo 裡附了 OCR 引擎的 A/B 測試架)。可選的套件沒裝,功能會關掉並明講你少了什麼——絕不悄悄換一個比較差的方法。悄悄降級產生的是「錯的輸出」而不是「少的輸出」,那是最貴的一類 bug。
那張投影片上沒有半個字,怎麼辦?
貼文發出來之後,有位朋友留言問:「請問您是把螢幕上的 PPT 以 OCR 方式彙整進入資料庫嗎?」這個問題剛好戳中我卡最久的一段,值得展開講。
答案是:OCR 有,但如果只有 OCR,這個工具會漏掉演講裡最值錢的東西。
演講轉筆記,直覺的做法是抽投影片畫面、跑 OCR、把文字接到逐字稿旁邊。這在條列式投影片上完全可行。問題是復健科的演講,最重要的那幾張常常是:一張診斷流程圖、一張分期表格、一張超音波影像加兩個箭頭。
這幾張的 OCR 結果會是什麼?幾個散落的標籤,或者根本一片空白。在純文字的世界裡,它們看起來就像空白投影片。
我第一版就是這樣做的。今年 5 月那次,一場演講裡有 11 張流程圖,全部被判成不重要,一張都沒進筆記。逐字稿裡講者在講「這時候我們看這條路徑」,而筆記裡沒有那條路徑。

多的那一顆模型,不准讀字
現在流程裡多了一階本機的視覺語言模型(minicpm-v:8b)。這裡有一條寫死在規則裡的限制:
這顆模型不准做 OCR
它回傳的不是文字,是一份結構化的判斷。文字一律交給 OCR 引擎,一句話都不從視覺模型拿。
它要回答的是:這張是流程圖、表格、X 光、超音波還是純文字;有沒有箭頭構成決策流;有沒有測量數值;文字重複度(這張圖有多少只是把旁邊的字再講一次);非文字資訊密度(扣掉文字以外還剩多少資訊)。
為什麼不讓它順便讀字?因為視覺模型讀字會編。它會給你一段看起來很合理、但投影片上根本沒有的文字。在臨床內容裡,這種錯誤比「少一段」貴得多。程式裡那個放 VLM 文字的欄位是永遠空的,留著只是為了相容。
便宜的先篩,貴的才送
視覺模型很慢,一張張送太浪費。所以前面有一道四條件的閘門,四個全部成立才判定「這張是裝飾性的」跳過:
| 條件 | 門檻 |
|---|---|
| 文字密度 | < 0.05 |
| OCR 抓到的字數 | < 20 |
| 檔案大小 | < 80 KB |
| 畫面 Laplacian 變異數 | < 100 |
關鍵是最後兩條。一張只有超音波圖、沒有半個字的投影片,前兩條成立,但它的檔案大、畫面結構複雜,後兩條不成立,閘門就關不起來,它照樣被送進去分析。真正會被跳過的是段落標題卡、純色分隔頁、還沒 build 完的空白頁。
最後決定嵌不嵌圖的,不是 OCR 抓到幾個字
這些訊號會匯進一個分數,再決定每張投影片的層級。有幾條規則是被實際的失敗逼出來的:
- 流程圖強制升級:有箭頭決策流、或看起來是治療流程與分期架構的,強制拉到最高層級。
- 影像類有地板:超音波、X 光、MRI、解剖圖、表格、統計圖,就算分數低於門檻也不准掉下去。這條是因為有次講者只提了一句的超音波圖,分數低到掉出去,整批消失。
- 純條列頁強制不嵌:文字重複度高於 0.7 的條列頁跟口訣頁不嵌,因為 markdown 已經寫成條列了,再貼一張圖只是同一件事講兩次。
失敗時往保守的一邊倒
視覺模型如果分析失敗或回傳空值,那張一律降到不嵌的層級。寧可少一張,不要嵌一張我不知道裡面是什麼的圖。
一句話總結:OCR 負責「抓得到的字」,視覺模型負責「抓不到的資訊在不在」。兩件事互補,誰都取代不了誰。
有 AI agent 訂閱的話,可以請它代勞
這個 repo 同時是一份 Claude Code skill:把整個資料夾丟進 ~/.claude/skills/,AI agent 就能自己驅動整條管線。你出判斷(這是什麼語言的課、哪段是重點),它出機械勞動。還不熟悉 AI agent 的話,可以從我的入門系列開始:從零開始、怎麼跟 AI agent 講話。
工具本身也可以純 CLI 使用,每一階段都是普通的 Python 腳本。
結語
GitHub:github.com/drpwchen/lecture-to-notes(MIT,中英文 README 都有)
有 NVIDIA GPU 最快(8 GB 就夠,我自己是 RTX 3070 Ti),但不是硬需求:內建 CPU fallback(會誠實印出預估時間),轉錄也可以外包給 Groq 的雲端 Whisper(免費層可用,機密錄音別走這條)。Mac 理論上以 CPU 模式可行但未實測——有踩到坑歡迎開 issue,也歡迎分享你們自己整理課程的方法~
