iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
AI 自動化

我以為我保留了五道閘門系列 第 17

Day 17|95 個字元的提示詞,和 13% 的 commit

  • 分享至 

  • xImage
  •  

模組四|剪輯管線(Day 17–22)

模組三講怎麼驗一份稿子。從今天開始講錄完之後的事,而這一段是整條產線裡 AI 參與最深、也最沒有出過大事的一段。

除了一件事。

參數全攤開

逐字稿是這樣產的:

model = WhisperModel("large-v3", device="cpu", compute_type="int8")

segments, info = model.transcribe(
    audio_path,
    language="zh",
    vad_filter=True,
    vad_parameters=dict(min_silence_duration_ms=500),
    beam_size=5,
    condition_on_previous_text=False,   # 避免長音檔重複/漂移
    initial_prompt=DOMAIN_PROMPT,
)

跑在 CPU 上、int8 量化,Mac 上大約是 0.5 到 2 倍實時:一小時的音檔跑半小時到兩小時。沒有 GPU 路徑。

沒寫 GPU 版本不是因為不會,是因為這一步不趕。錄完之後我不會坐在旁邊等,跑一晚上跟跑十分鐘對我來說沒差。而寫一條 GPU 路徑要處理環境、驅動、量化格式,那些成本是實時的。

不急的東西不要優化。 這條在只有一個人的產線上特別重要,因為每一條你優化過的路徑,之後都要由你自己維護。

condition_on_previous_text=False 是一個伏筆

這個參數的意思是:辨識每一段的時候,不要把前面已經辨識出來的文字當成上下文餵進去。

預設是 True,因為有上下文通常辨識得更準。而關掉它的理由寫在註解裡:避免長音檔重複/漂移。

這是 Whisper 家族的一個已知行為:當它把自己的輸出當上下文,遇到一段沒有語音的區間,它可能會繼續生成,因為上下文告訴它「剛剛在講話,所以現在應該也在講話」。

於是它會憑空生出一段話,通常是把前面某句重複好幾次。

我關掉了這個參數,所以這個問題被壓下來了。但沒有被消滅,明天講一個誤砍六分多鐘的事故,成因正是這個。

那 95 個字元

我在整條水管最上游用兩指塞進一片極小的楔子,下游幾十個出口就不用一個個手扳。

initial_prompt 是一段文字,作用是告訴模型「這段音訊大概是什麼領域」,讓它在同音字之間選對。

我的是 95 個字元。

裡面塞的是:節目類型、本集會出現的專有名詞、來賓的職涯領域相關詞彙,結尾一句「繁體中文。」

95 個字元很短。而它的效果不是「讓辨識變好」,是讓特定幾個詞不要錯,那些會反覆出現、錯一次就要改幾十處的詞。

這件事的投資報酬率極高:寫 95 個字元,換掉幾十次尋找取代。

而它的限制也很明顯:它是逐集手寫的。 每一集的專有名詞不同,所以每一集要重寫一次。這意味著它永遠不會累積,上一集學到的詞,下一集不會自動帶過去。

一個共用詞庫加上每集的增量,會好很多。我沒做。

它是對成品重跑,不是對毛片跑

這一點我一開始沒想通,走了一段冤枉路。

毛片的逐字稿跟成品的逐字稿,是兩份不同的東西。

毛片逐字稿是用來決定剪哪裡的,它的時間碼對應原始錄音。
成品逐字稿是用來上字幕、產文案的,它的時間碼要對應剪完之後的檔案。

剪輯把中間切掉了,所以毛片的時間碼在成品上全部位移。不能直接沿用。

所以這支腳本實際上跑兩次:一次在剪之前(給剪點用),一次在剪之後(給字幕用)。

多跑一次的成本是幾十分鐘的 CPU 時間,而它省掉的是「手動重算所有時間碼」。那件事我試過一次,錯誤率高到不如重跑。

當一個計算比手動修正更便宜的時候,就重算,不要修補。 這條在 Day 22 會再出現一次,那次是整份成品重建。

模型在集數之間漂移

現在講不好的部分。

我把所有提到 ASR 模型的地方列出來,發現三個不同的值,散落在三種載體:

出處 寫的是什麼
那支轉錄腳本的預設值 large-v3
兩支剪輯腳本的註解 large-v3-turbo
某份剪輯記錄 smallint8

三個值,三個地方,沒有一個是權威來源。

哪一個是現在實際在用的?要回答這個問題,我得去看最近一集實際跑的是哪支腳本。而這件事應該是一行設定就能回答的。

這是 Day 16 那個「同一份東西有多個副本」在參數層級的版本:參數被寫在註解裡、寫在記錄裡、寫在預設值裡,然後各自演化。

修法很簡單:一個共用的設定檔,所有地方引用它。我沒做,因為每一集寫腳本的當下,複製上一集然後改幾個數字是最快的(Day 27 會講這個複製機制造成的更大災難)。

那 13%

同一個字我擦到紙都快破了,腳邊已經堆滿一模一樣的紙團。

現在講這一整篇最難看的數字。

字幕、逐字稿、錯別字相關的 commit,佔製作端全部 commit 的 13.1%(155 筆)。

把所有 fix / 修正 類算進來是 187 筆、15.8%。

每七個 commit 就有一個在修字。

而它的形狀比數字更難看。最密集的一段是 85 分鐘內連續 10 筆,全部在修同一批字幕的錯字,其中一句 commit message 一模一樣重複了三次。

那不是工程,那是鬼打牆。

更糟的是它沒有收斂。那一串的最後一筆只是「修正文本中的錯別字」,沒有任何機制性的改變。然後幾個月後同樣的事情又爆一次,那個月的字幕相關 commit 是全期最高。

為什麼沒有任何檢查擋得住

Day 12 到 16 講了四種檢查,沒有一種對這件事有用。

  • 確定性驗證器:它可以驗「字幕檔存不存在」,驗不了「這個字對不對」
  • 換一個模型審:它讀的是文字,而它不知道音訊裡實際說的是什麼
  • 狀態檔:記錄用的,不檢查內容
  • 人:要逐句聽

這是整條產線裡唯一一個「只能靠人聽」的環節,而它佔了 13% 的 commit。

Day 5 說過「AI 省的是產出時間,不是決定時間」。這裡是更精確的版本:ASR 省的是打字時間,不是校對時間。 而校對佔的比重,遠超過我當初的預期。

代價

我到現在沒有做任何機制化的改善。

至少有三件事可以做,全部不難:

  1. 共用詞庫(把反覆出錯的專有名詞累積成一份清單,每集的 initial_prompt 從它生成)
  2. 批次尋找取代腳本(已知的錯字對應表,跑一次改完,而不是手動找 10 次)
  3. 把模型設定收進一個地方(消掉那三個漂移的值)

三件事加起來大概兩小時。而 155 筆 commit 的時間遠遠超過兩小時。

我知道這件事,而且我在寫這篇的時候又確認了一次數字,然後還是沒做。 這已經是這個系列第五次出現同一句話了。

第二個代價:condition_on_previous_text=False 壓下了幻聽,但也讓辨識失去上下文,長句、跨段的專有名詞會辨識得比較差。這是一個我選了的取捨,而我沒有量過它的代價有多大。

帶走什麼

用最小的輸入,換掉最大的重複工作。

95 個字元的提示詞,換掉幾十次尋找取代。這種投報比在 AI 工具上很常見,而它的形狀通常是:找出那個「錯一次要改很多次」的東西,然後在最前面把它固定住。

第二條:當重算比修補便宜的時候,重算。

剪完之後的時間碼,我試過手動換算,錯誤率高到不如重跑一次 ASR。而重跑的成本是幾十分鐘的 CPU,不是我的時間。

你的時間跟機器的時間不是同一種資源,而人很容易為了省機器的時間而花自己的時間。

第三條,也是最該記住的:

在導入一個 AI 工具之前,先想清楚它省的是哪一段,以及那一段原本佔多少。

ASR 省的是打字。而在我的流程裡,打字從來不是瓶頸,校對才是。所以導入之後,總時間沒有變少多少,只是從「打字 + 校對」變成「等機器 + 校對」。

如果我當初問過這個問題,我會在第一天就開始建那個詞庫。

明天講那個誤砍六分多鐘的事故,它的成因,就是今天那個被壓下來但沒消滅的參數。


上一篇
Day 16|七組落差,一組都沒有被抓到
系列文
我以為我保留了五道閘門17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言