消費級顯卡的退而求其次:本地開源模型的 YouTube 長片產線
在一張消費級顯卡(RTX 5060 8GB)上,捨棄雲端閉源 API、改用本地開源模型,把 YouTube 長片成本壓到近乎零——以失智症衛教長片為例,記錄這條 LLM Agent 主導的 faceless 影片自動化產線:架構、用到的模型、無人值守的韌性設計,與一路踩到流血的八個坑。
TL;DR
一支 17 分鐘的失智症衛教長片,從寫腳本、生圖、配音、合成、做封面、到上傳 YouTube 並排程發布,全程沒有人剪輯、沒有人錄音、沒有人進剪輯軟體。整條線跑在一台 RTX 5060(8GB VRAM)的家用電腦上,邊際成本幾乎是 0 元(本地生圖 + 本地語音克隆,不燒任何 API 配額)。
核心不是某個單一模型,而是一個 「LLM Agent 當總指揮 + 一堆專用本地模型/工具當工人」 的架構:Agent 負責決策、寫稿、下指令、看結果、出錯就修;真正幹活的是 SDXL 生圖、GPT-SoVITS 配音、ffmpeg 合成、YouTube API 上傳。
這篇記錄它的技術原理、用到的模型,以及把它變成「能無人值守跑完」的工程韌性設計——還有一路踩到流血的八個坑。
整體架構:指揮 vs 工人
傳統「AI 生成影片」想的是「一個模型吃文字、吐影片」。但要做長達 17 分鐘、113 個鏡頭、有結構有鉤子的衛教片,單一模型既不可控也不可負擔(image-to-video 這類一秒約 $0.05,17 分鐘要 ~$50,而且單次最長才 ~15 秒)。
所以這條線的設計哲學是分層:
┌─────────────────────────────────────────────────────────┐
│ 指揮層 (Orchestrator) = LLM Agent │
│ Claude Opus 4.8 (1M context) │
│ · 寫腳本 / 切 113 個 beat / 寫每個 beat 的英文生圖 prompt │
│ · 下指令給各工具、讀回結果、判斷成敗、出錯自動修 │
│ · 最後呼叫 YouTube API 上傳 + 排程 │
└───────────────┬─────────────────────────────────────────┘
│ 編排 / 錯誤處理 / 重試
┌────────────┼───────────────┬──────────────┬───────────┐
▼ ▼ ▼ ▼ ▼
生圖 配音 合成 封面 上傳
ComfyUI GPT-SoVITS ffmpeg Pillow YouTube API
SDXL (聲音克隆) (Ken Burns) (Data v3)
每個 beat(鏡頭)是流水線的最小單位 = 一張 16:9 靜圖 + 一句旁白語音 + 一行字幕。整支片就是 113 個 beat 用 Ken-Burns 運鏡 + 交叉淡接串起來。
關鍵體悟:「影片生成」其實是「資產生成 + 確定性組裝」兩件事。創意、易變、需要判斷的部分(腳本、選圖、修錯)交給 Agent + 神經網路模型;組裝(時間軸、運鏡、字幕、響度、轉場)交給 ffmpeg 這種確定性、可重現、零成本的工具。把這兩者分開,才能又便宜又可控。
各階段的技術原理與模型
1. 腳本與分鏡 ── LLM Agent
由 Agent(Claude Opus 4.8)直接產出:
- 口播稿:開頭 15 秒抓眼球、中段不斷下鉤子、收尾溫暖。主題鎖定時事,但把「新藥的三個但是」「一半風險你能自己擋」這種反差/可行動的點埋進去拉留存。
- 逐 beat 切分:把口播稿切成 113 句,每句一個 beat,各自存成一個本機逐句文字檔。
- 每 beat 的英文生圖 prompt:同樣逐句存成檔。為什麼是英文?因為 SDXL 對英文語意理解遠優於中文;Agent 等於同時兼任中翻英 + 視覺導演,把「憂心的長輩望著整牆泛黃老照片」翻成 SDXL 吃得動的 prompt。
衛教片的硬規則也在這層落實:不用真實人物/逝者肖像、不放血腥醫療畫面,只用象徵性畫面(例如「病情惡化」用一張傾倒的椅子,而不是病床特寫);旁白裡的新聞出處標記一律拿掉。
2. 生圖 ── ComfyUI + RealVisXL V5.0 Lightning (SDXL)
- 模型:RealVisXL V5.0 Lightning —— 一個 SDXL 架構、針對極少步數蒸餾過的寫實向 checkpoint。
- 跑法:本地 ComfyUI(API 模式),1344×768、約 6 steps、cfg ~1.8、
dpmpp_sde+karras排程。Lightning 版的價值就在這:一般 SDXL 要 25–40 步,它 6 步就出可用的寫實圖。 - 效能:RTX 5060 8GB 上穩態約 14 秒/張(冷啟動第一張 ~79 秒,含 ComfyUI 開機 + 載模型;之後常駐)。
- 為什麼選本地:免費、無雲端配額、無跨 session 併發衝突。對寫實東亞場景,品質已接近付費的 gpt-image 等級。
- 備援路徑:雲端生圖(gpt-image-2,走訂閱)仍保留給「偶爾要一張頂級英雄圖」的場合。
3. 配音 ── GPT-SoVITS 聲音克隆
- 模型:GPT-SoVITS,zero-shot 聲音克隆——用一小段使用者本人的錄音當參考,就能用「他自己的聲音」唸任意文字。本地 GPU。
- 情緒控制:GPT-SoVITS 的語氣完全取決於參考音。所以預先從使用者錄音裁出一組情緒參考音(calm / engage / story / uplift),整支片依段落換語氣——主軸用 story、提問段用 engage、溫暖收尾用 calm——避免長口播從頭平到尾。
- 輸出:每 beat 一個 mp3 + wav + srt(含時間軸),srt 之後直接餵給字幕與 YouTube CC。
4. 合成 ── ffmpeg(這步是整條線的「確定性骨架」)
全部靠 ffmpeg,沒有任何剪輯軟體:
- Ken-Burns 運鏡:用
zoompan做緩慢推/拉/平移。關鍵技巧:先把靜圖放大到 3 倍畫布(5760×3240)再做 zoompan,這樣每一幀的整數 x/y 取整誤差在 1080p 上是次像素級的 → 完全無抖動(直接在 1080p 上 zoompan 會肉眼可見地一格一格跳)。 - 節奏:每個 beat 時長 = 旁白長度 + 一段**靜音尾巴(pause)**當作「換氣」;交叉淡接(xfade)刻意落在這段靜音裡,所以兩句旁白不會疊在一起。
- 字幕:逐 beat 產生 ASS 字幕、用 libass 燒進畫面。字型 微軟正黑體粗體、白字 + 4px 黑外框、78px。
- 響度:最後一道
volume=2.0,alimiter=limit=0.95—— 整體 +6dB 但用峰值限制器壓住,不爆音(直接線性 2× 會破音,因為人聲混音峰值本來就接近 0dBFS)。 - 交付響度 −14 LUFS(最反直覺、也最實用的一招):讓影片「夠大聲」的祕訣不是把音量開大,而是把整體響度正規化到 −14 LUFS(YouTube 的響度基準)。因為 YouTube 只會把過大聲的影片轉小、不會把太小聲的轉大——所以唯有交付在 −14 LUFS,平台才會以最大允許音量播放;低於這個值,你的片就被永遠播得比別人小聲。用 ffmpeg 的
loudnorm一道濾鏡量到並打平到這個目標即可。
字幕與響度的設計全部服務於一個明確的受眾:頻道觀眾以重聽、老花的長輩為主。所以預設就是「字大 1.5 倍、聲音大 2 倍、粗黑體而非宋體、不放背景音樂」。這些是寫死進工具的預設值,不是每次手動調。
5. 封面 ── Pillow
1280×720,Python Pillow 直接畫:相關的長輩臉孔在一側、左側拉一條深色漸層遮罩讓文字壓得住背景;白(鉤子)/ 紅(衝擊關鍵字,焦點最大)/ 黃(行動呼籲)三色文字全部粗體 + 粗黑外框——一樣是為了長輩在手機上一眼可讀。
6. 上傳 ── YouTube Data API v3
透過官方 API + OAuth 桌面流程,一行指令搞定:上傳、設 AI 合成揭露、排程隔天中午 12:00(台北)發布、加入播放清單、設封面、再把 srt 當 CC 字幕傳上去。
API 的邊界也摸清楚了:未過審的 API 專案會強制上傳成私人;營利開關與 AI 揭露的「顯示為是」這兩件API 設不了,得在後台手動確認。這類「機器能做到哪、哪裡一定要人」的邊界,本身就是工程的一部分。
把它變成「能無人值守跑完」的工程韌性
能 demo 一次不難,難的是無人盯著也能從頭跑到尾、出錯自己爬起來。這條線的韌性靠四個機制:
-
可續跑 (Resumable):每個 beat 的圖/音若已存在且通過驗證就跳過。中途掛掉重跑,只補缺的,不重做已完成的(也不重燒 API 配額)。
-
驗證 + 重試:
- 配音驗證:一道檢查確認「平均音量 > −40dB 且 時長 ≥ 字數/5.5」。因為 GPT-SoVITS 偶爾對短句吐出近乎靜音/被截斷的片段,而「只看檔案大小 > 20KB」根本擋不住。不過就重試 3 次。
- 生圖驗證:寬度為 0 的壞圖直接丟棄重生。
- 防抓到舊圖:生圖前先記下「輸出夾裡最新圖的時間戳」,生完只接受比這個基準更新的圖。否則一旦生圖失敗(沒吐新檔),程式會誤抓上一張舊圖塞進這個 beat——這正是某次「最後 9 個鏡頭變同一張圖」的元兇。
-
逾時 + 自動重啟:生圖子程序包在計時 Job 裡,卡住超過時限(本地 200s)就殺掉、並重啟 ComfyUI,下次重試開乾淨的伺服器——根治某次在 8GB VRAM 上卡了 6 小時的慘案。
-
隔離 + 外部看門狗:
- 隔離:渲染用獨立工作夾(以工作標籤區隔),避免兩支渲染共用暫存夾互相清空。
- 看門狗:一支獨立的監督程序每 20 秒檢查進度,卡住或整支死掉就殺乾淨並自動重啟渲染(收尾合併階段放寬時限以免誤殺)。這補上了「程序內重試補不到的洞」——當渲染整支被外力殺掉時,得有個站在外面的東西把它拉起來。
實驗心得:八個流血的坑
| # | 坑 | 根因 | 修法 |
|---|---|---|---|
| 1 | 最後 9 個鏡頭變同一張圖 | 雲端生圖配額耗盡→沒吐新圖,程式誤抓最新的舊圖 | 生圖前記基準時間戳,只收更新的檔 |
| 2 | 某些 beat 有畫面沒聲音 | GPT-SoVITS 短句吐靜音,舊檢查只看檔案大小 | 配音驗證(音量 + 時長雙條件)+ 重試 |
| 3 | 卡死 6 小時 | ComfyUI/GPU 在 8GB VRAM 偶發 hang,HTTP 等待無逾時 | 計時 Job + 逾時殺掉並重啟 ComfyUI |
| 4 | 上傳後「無法營利」 | 「免版稅」配樂 ≠ 沒有 YouTube Content ID 認領,BGM 被認領 | 改用平台音樂庫;最終決定不放 BGM(零認領風險) |
| 5 | 腳本路徑爆掉、空轉 | PowerShell 5.1 讀無 BOM、含中文的腳本會用 cp950 誤解碼(「文件」變亂碼) | 路徑改用腳本所在目錄組合 / 純 ASCII,避免中文字面 |
| 6 | 渲染做不完、片段數對不上 | 兩支組裝程序同時跑、共用暫存夾互相清空 | 加「工作標籤」參數、用獨立工作夾隔離 |
| 7 | 渲染靜默躺死 39 分鐘 | 組裝這步當時沒有外部監督,整支被殺後沒人重啟 | 獨立看門狗:偵測卡住/死亡→自動重啟 |
| 8 | 音量開到最大、整支還是偏小聲 | YouTube 只把過大聲的轉小、不會把太小聲的轉大;交付響度低於 −14 LUFS 就被播得比別人小聲 | 用 loudnorm 把整體響度正規化到 −14 LUFS(YouTube 基準),才會以最大音量播放 |
共通心得:這些坑沒有一個是「模型不夠強」造成的,全部是工程膠水(glue)的問題——配額耗盡、靜音邊界、逾時、版權認領、編碼、併發、程序監督。AI 生成的時代,瓶頸往往不在模型,而在把模型可靠地串起來、並優雅地處理它們的失敗模式。
成本與效益
| 項目 | 這條線 | 對照 |
|---|---|---|
| 生圖 | 本地 SDXL,$0 | 付費圖 API:每張數美分 |
| 配音 | 本地 GPT-SoVITS,$0 | 商用 TTS:每千字計費 |
| 合成 | ffmpeg,$0 | 剪輯軟體 + 人力 |
| 一支 17 分鐘片 | 約 15–17 分鐘算完,邊際成本 ~$0 | image-to-video:17 分鐘 ≈ $50,且要拼接 |
| 人力 | 0(無人值守) | 寫稿 + 配音 + 剪輯 + 做圖 + 上傳:數小時 |
效益不只省錢,而是可規模化:同一條線換個主題就能再產一支,且品質一致(字級、響度、封面風格、發布排程全部標準化)。
成品展示
本案例對應的成品,是健康Hello 頻道的一支 17 分鐘失智症衛教長片——整支從腳本、生圖、配音、合成、封面到上傳排程,全部由上述產線自動完成,無真人入鏡、無人剪輯。
這支片是〈失智症新藥在台見效,腦中異常蛋白全清除!但醫示警:真正能救大腦的,是這件事〉。點下圖,就能看到同一條產線從開場鉤子到溫暖收尾的完整長相:
結語
這個實驗真正驗證的,不是「AI 能不能生影片」,而是 「一個 LLM Agent 能不能當稱職的工程總指揮」:它要會寫內容、會把意圖翻成各模型吃得動的指令、會讀懂失敗、會在半夜沒人時自己把卡住的渲染重啟。
模型(SDXL、GPT-SoVITS)是肌肉,ffmpeg 是骨架,而韌性設計(驗證、重試、逾時、隔離、看門狗)才是讓它能無人值守跑完的神經系統。把這三者組好,一個人 + 一張 8GB 顯卡,就能把一條近乎零成本、全自動的長影片產線跑起來。
下一步:把看門狗的事件、各 beat 的耗時與重試次數寫成結構化日誌,讓整條線自我觀測;以及讓 Agent 依據後台數據(留存曲線、點閱率)回饋調整下一支的腳本鉤子與封面文案——讓流水線從「自動」進化到「自我優化」。
本文記錄的是一條實際在運行的家用級自動化影片產線的工程設計與踩坑過程,所有數字與失敗案例均來自真實 run。為對外公開,文中已移除本機路徑、腳本檔名等實作細節,保留工程原理與數據。
常見問題
一支 17 分鐘的 AI 生成長片成本是多少?
在這條產線上邊際成本幾乎是 0 元:生圖用本地 SDXL、配音用本地 GPT-SoVITS、組裝用 ffmpeg,全部本地運算不燒 API 配額,一支 17 分鐘的片約 15–17 分鐘就算完。對照之下,用雲端 image-to-video,17 分鐘的素材成本約 50 美金,而且單次最長只能生約 15 秒、還要自己拼接。
為什麼用本地 SDXL,而不是付費的生圖 API?
本地 ComfyUI + RealVisXL V5.0 Lightning(SDXL)免費、無雲端配額、無跨 session 併發衝突,在 RTX 5060 8GB 上穩態約 14 秒生一張 1344×768 寫實圖。對寫實的東亞場景,品質已接近付費的 gpt-image-2;雲端生圖只保留給偶爾要一張頂級英雄圖的場合。
怎麼讓全自動影片產線無人值守也能跑完?
靠四個韌性機制:可續跑(已完成且通過驗證的 beat 跳過,中途掛掉只補缺的)、驗證加重試(配音檢查音量與時長、生圖丟棄壞圖、用時間戳防止抓到舊圖)、逾時自動重啟(生圖卡住就殺掉並重啟 ComfyUI)、以及一支獨立的外部看門狗(每 20 秒檢查進度,整支渲染被殺掉也能自動拉起來)。
為什麼把影片生成拆成「資產生成」和「確定性組裝」兩件事?
創意、易變、需要判斷的部分(腳本、選圖、修錯)交給 LLM Agent 與神經網路模型;組裝(時間軸、運鏡、字幕、響度、轉場)交給 ffmpeg 這種確定性、可重現、零成本的工具。把這兩者分開,才能同時做到便宜與可控——而不是寄望單一模型一次吐出完美長片。
AI 生成的影片上傳 YouTube 要注意什麼?
兩件事:一是版權——「免版稅」配樂不等於沒有 YouTube Content ID 認領,被認領就會「無法營利」,最穩的做法是改用平台音樂庫或乾脆不放背景音樂;二是 AI 揭露——要設定合成揭露,而「營利開關」與「AI 揭露顯示為是」這兩件 API 設不了,得在 YouTube Studio 手動確認。
為什麼 YouTube 影片音量開到最大,聽起來還是比別人小聲?
因為 YouTube 會做響度正規化,但它只把過大聲的影片轉小、不會把太小聲的轉大。所以讓影片夠大聲的祕訣不是把音量開大,而是把整體響度正規化到 −14 LUFS(YouTube 的響度基準)——交付在這個值,平台才會以最大允許音量播放;低於它,你的片就被永遠播得比別人小聲。用 ffmpeg 的 loudnorm 濾鏡量到並打平到 −14 LUFS 即可。