程式自己算出來只有15.9秒,觀眾實際卻等了28秒
這次實測的對象是010-AI-VTuber專案的原型版本,程式檔案叫main.py,文中所有數字都是從它跑出來的。main.py內建了計時,結果是「LLM 6.4秒|語音 9.4秒|合計 15.9秒」。但打開直播畫面實測,從打字到聽到第一個字大約要28秒,中間多出來的12秒,程式自己完全不知道。
語音9.4秒裡有一大半是主播已經在講話
第一個容易誤判的地方是「語音9.4秒」這個數字。main.py裡負責播放的_play_buffer函式用s.write(data)播放,這是阻塞式呼叫,也就是整段語音播完才會返回。這9.4秒是「合成時間+ffmpeg轉檔+語音本身的播放長度」三者加總,觀眾在乾等的時間只有其中一部分。真正讓觀眾在畫面前空等的,只有LLM生成的6.4秒,加上合成與轉檔的2到3秒,合計大約9秒——剩下的6秒左右,是主播已經在開口講話了。
多出的12秒幾乎全部藏在YouTube的串流緩衝設定裡
28秒減掉15.9秒,落差將近12秒,這塊main.py的計時完全量不到,因為它發生在OBS把畫面推上YouTube之後、YouTube伺服器再推給觀眾之前。這一段延遲用一張圖拆解會比較清楚:
打字 ──[LLM 生成 ~6.4s] ──[合成+轉檔 ~2-3s] ──[開口、講完 ~6s] ──[YouTube 串流緩衝 ~12s] ──觀眾聽到
└────────── main.py 計時的 15.9s ──────────┘ └──── 設定就能砍 ────┘
最後這12秒完全不需要動程式碼,只要改設定就能砍掉,是投報率最高的一塊。
先調兩個直播設定,28秒就能砍到16秒左右
第一步不用改任何程式碼:把YouTube後台的串流延遲從一般模式改成「超低延遲(Ultra-low latency)」。一般模式緩衝大約15到20秒,超低延遲模式只要2到4秒,光這一項就能把28秒壓到16秒左右。
技術細節:OBS編碼設定
除了YouTube後台,OBS這邊也要配合調整才會完整生效:
- 編碼器用NVENC。
- Tune選項選「low latency」。
- 關鍵影格間隔(keyframe interval)設1到2秒。
讓LLM邊生成邊念,開口前的等待能壓到3到4秒
調完設定砍掉的是傳輸端的緩衝,接下來要動的是程式邏輯本身。現況main.py是完全序列的做法:等LLM把整段回覆都生完,才開始合成語音,合成完才開口,像是等廚房把整桌菜都出完才上第一道菜。
改法是讓LLM用串流模式(stream: true)邊生成邊收token,收到第一個句號、驚嘆號或問號就立刻把這一句拿去合成並播放,後面的句子一邊播一邊排隊備好。這樣一來,「開口前的等待」從「整段LLM生成+整段語音合成」縮短成「第一句LLM生成+第一句語音合成」,大約只要3到4秒。配合前面調好的直播設定,觀眾端大約6到7秒就能聽到第一個字,達到堪用門檻。
讓角色講短一點,兩邊的工作量都變少
在人設的system prompt裡加一句「回覆控制在1到2句、口語化」,並把max_tokens設在100左右,LLM要生成的內容變少,語音要合成的內容也變少,兩邊都受益,尤其在用免費、容易話多的模型時效果更明顯。另外,把_to_wav48裡的ffmpeg轉檔挪出關鍵路徑——逐句串流做出來之後,轉檔本來就會跟播放重疊執行,這一步的影響會自然變小。
換成付費LLM解決免費層排隊的問題,這一步已經做完了
免費層的LLM常有冷啟動或排隊,6.4秒裡有一部分就是耗在這裡。付費模型通常回應更穩定,且延遲落在1到3秒。在串流模式下更該在意的是「首token延遲」(Time To First Token,縮寫TTFT)——也就是LLM開始吐出第一個字的速度,而不是整段生完的時間。
這一項已經在2026年6月11日完成,把LLM_PROVIDER切到gemini(gemini-3.5-flash,備援用flash-lite),原本的OpenRouter免費鏈保留下來當實驗備援。Gemini的OpenAI相容端點同樣支援stream: true,前面說的逐句串流改造可以直接沿用,不用重寫。
建議的動手順序:先調設定,再重構程式碼,最後才考慮付費
- 現在就能做:YouTube後台改超低延遲,OBS編碼調成low latency,零風險、立即見效。
- 接著改程式碼:把
speak()跟LLM呼叫重構成逐句串流,同時加上max_tokens與精簡回覆的prompt。 - 跑一輪看新數字,再決定要不要換付費LLM。
各階段預期的觀眾端延遲:
| 階段 | 觀眾端聽到第一個字 |
|---|---|
| 現況 | 約28秒 |
| +調整直播設定 | 約16秒 |
| +逐句串流 | 約6至7秒 |
| +精簡回覆+付費LLM | 約4至5秒 |
flowchart LR A[現況:約28秒] --> B[調整直播設定:約16秒] B --> C[逐句串流:約6至7秒] C --> D[精簡回覆加付費LLM:約4至5秒]
這篇只解決了傳輸延遲,角色之間的空白是另一個問題
以上做法解決的是「打字到開口」這條線的延遲,屬於傳輸與生成端的問題。真正把「一個角色講完、另一個角色接著開口」之間的空白壓到0秒,是後來的語音預生成第二版做的事:趁一個角色還在講話時,就把下一段的文字跟聲音先做好備用。那是另一種藏延遲的手段,跟這篇談的傳輸延遲不是同一件事,做法寫在雙AI上臉實戰:雙音訊線、語音預生成與情緒通道。
聲線、臉部與推流的接線方式,見GPT-SoVITS 與 Live2D 接線安裝指南;記憶與主動發話的設計,見AI VTuber 的記憶與自主性設計;想先了解整個專案的全貌,可以看AI-VTuber 是什麼-白話入門。