本地 AI 短劇生成完全失敗實錄:30 天 17 版 5060 Ti 16GB 血淚教科書
寫給:手裡握著 5060 Ti / 3090 / 4070 / 4080,想用 ComfyUI 拼出「五十歲女主逆襲」那種 AI 短劇的工程師、創業者,以及任何被「本地全免費」感動過的人。
不寫給:想看「成功 case 抄一抄就跑通」的人。整篇沒有 happy path,沒有一鍵腳本。有的只是 30 天 17 版 pipeline 全部走過、v17 第四版按下 ctrl+c 認輸的那種真實。
跳過序章直接看程式碼 → 第 6 章(v13 MuseTalk patch)。看雲端比較 → 第 10 章。看硬體上限 → 第 2 章。
第 1 章 序章
摘要:在你按下「ComfyUI 安裝」之前,先確認你不是在重複我們的 30 天。
1.1 這 30 天是怎麼開始的
起點是 YouTube《五十岁,我的人生刚刚开火》(ID tGbbu3axuBE):50 歲女主被外遇離婚、創業反殺,30 集 × 5 分鐘 AI 連續劇,YouTube 廣告 + 抗老精華液帶貨在簡中圈風生水起。
我看完立項,13 角色設好 LoRA trigger,PC 5060 Ti 16GB 改全天候 ComfyUI。30 天後成績單:17 版 pipeline / 1 個 ep1(17.7 分鐘 / 450 sub-shot / 21 hr 連跑)/ 7 個用戶批評 / 3 個無解問題 / 0 集能上線。
文章要說:消費級 16GB VRAM 跑產業級短劇生成是物理有上限的路,上限不在「明年新顯卡」,在「現在這代 diffusion 架構本身」。
1.2 我做這篇文章的成本
| 投入 | 數量 |
|---|---|
| 開發天數 / Pipeline 版本 | 30 天 / 17 版 |
| GPU 全速時數 / WSL OOM | 350+ hr / 80+ 次 |
| Flux LoRA / Wan22 / MuseTalk 運算量 | 13 角色 × 100 step 30 hr / 620 clip / 240 shot |
| 電費(30 天) | NT$650 |
重來一次,前 25 天我會跳過,直接走「雲端 API + ComfyUI 本地補刀」混合路線。
1.3 / 1.4 誰該讀 / 誰不該讀
該讀:消費卡跑 AI 短劇創作者 / $0 預算研究 AI 影片可行性的工程師 / 已買 4070-5060 Ti 想理性確認的人。 不該讀:期待「跑通腳本」的人;不會 Python / SSH / ffmpeg 的人;預算 > NT$10,000/月想外包雲端的人。
1.5 文章結構
10 章按時間軸 + 技術主題排序。每章格式:踩坑 → 分析 → 教訓。沒有藏拙,這是 30 天結束時的最終狀態。
1.6 一個前情提要
我不是 ComfyUI 新手 —— Flux LoRA 訓過 13 個、Wan2.1 跑過上百 clip、workflow JSON 能徒手寫。這篇是一個有經驗的人被 16GB VRAM + diffusion 架構天花板雙重壓制 30 天的紀錄。
教訓 1.1:「本地全免費」裡「全」跟「免費」都是假的,只有「本地」是真的。 教訓 1.2:30 天失敗成本 ≈ 雲端 API 兩年訂閱費。
第 2 章 硬體真相:5060 Ti 16GB 真實能力地圖
摘要:先講清楚 16GB VRAM 在 2026 年的 diffusion 世界裡,能做什麼、不能做什麼。後面所有失敗都是這張地圖的子集。
2.1 硬體規格全表
| 元件 | 規格 |
|---|---|
| GPU | RTX 5060 Ti 16GB GDDR7(Blackwell sm_120, CUDA 12.8 / driver 13.2) |
| CPU | AMD Ryzen 9, 32 core / 64 thread |
| RAM | 128GB DDR5(WSL2 配 112GB,host 留 16GB) |
| 儲存 | 2TB NVMe Gen4,ComfyUI 走 native ext4 /home/user/ComfyUI/(不走 9P /mnt/c/) |
| OS | Windows 11 + WSL2 Ubuntu 22.04 |
| Orchestrator | Mac M4 16GB(純 SSH 控制) |
| 網路 | Mac → SSH key auth → PC 192.168.0.15 → WSL 172.27.230.199 |
| Port | ComfyUI 8188(8189 被 iphlpsvc portproxy 占,不能動)+ Mac SSH tunnel 28189 |
兩個踩過的 anchor:
- ComfyUI 必走 native ext4:9P 對 200+ 小檔 random read 超慢,Flux + LoRA 載入 8 秒爆到 90 秒。
ComfyUI/搬到/home/user/ComfyUI/,models/symlink 回/mnt/c/...,174GB 模型不用搬。 - port 8189 不能動:iphlpsvc portproxy 占了 8189,殺了整個 LAN 失聯。
2.2 16GB VRAM 是多大?
ASCII 圖是 5060 Ti 16GB 跑 Flux fp8 + MuseTalk 同時時的 VRAM 分配(v14 量產時 nvidia-smi 實測):
RTX 5060 Ti 16GB VRAM 分配地圖(v14 量產 talking head shot)
0 GB ┌───────────────────────────────────────┐
│ CUDA context + driver overhead │ 0.8 GB
1 GB ├───────────────────────────────────────┤
│ ComfyUI Python runtime │ 1.2 GB
2 GB ├───────────────────────────────────────┤
│ Flux UNet fp8_e4m3fn (12B params) │ ~7.5 GB
│ ├── T5 XXL fp8 encoder │
│ ├── CLIP L │
│ └── VAE │
9 GB ├───────────────────────────────────────┤
│ LoRA (rank 4 fp16, ~38 MB) │ 0.1 GB
├───────────────────────────────────────┤
│ KSampler latent buffer (832×1216) │ 1.4 GB
10 GB ├───────────────────────────────────────┤
│ MuseTalk V1.5 unet 256² + audio enc │ 2.8 GB
13 GB ├───────────────────────────────────────┤
│ face_alignment dlib 68pt │ 0.4 GB
│ Wav2Lip checkpoint (idle) │ 0.3 GB
14 GB ├───────────────────────────────────────┤
│ ✦ FREE 安全餘量 (KV cache 跳動) │ ~2.0 GB
16 GB └───────────────────────────────────────┘
關鍵:Flux fp8 占 7.5 GB(12B 最節儉組合);MuseTalk 256² 占 2.8 GB,升 512² 吃 8 GB+ → 永遠卡 256² 嘴部模糊;動態餘量只剩 2 GB,KV cache 在長序列 inference 吃滿,batch_size 永遠 1。
2.3 能跑 / 不能跑清單(30 天實測)
| 模型 / 任務 | 5060 Ti 16GB 結果 | 備註 |
|---|---|---|
| Flux dev fp8 single-file | ✅ 能跑,832×1216 一張約 38 秒 | anchor 圖主力 |
| Flux dev fp16 | ❌ OOM | 17.5 GB 載不進來 |
| Flux LoRA rank 4 訓練 | ✅ 能跑,cache miss 197s/step → cache hit 70s/step | 13 角色 100 step 共 30 hr |
| Flux LoRA rank 16 訓練 | ⚠️ 邊緣,30% 機率 OOM | 不建議 |
| Wan22 ti2v 5B fp16 | ✅ 能跑,81 幀 720×1280 約 7 分鐘 | 上限 81 幀 = 3.375 sec @ 24fps |
| Wan22 i2v 14B GGUF Q4_K_M | ❌ OOM(VAE decode 階段) | 第一次就死 |
| Wan22 i2v 14B fp16 | ❌ 想都不要想 | 模型本身就 28 GB |
| LTX-Video 2B distilled fp8 | ✅ 能跑,10 sec 約 4 分鐘 | i2v 鎖首幀差,棄 |
| MuseTalk V1.5 256² | ✅ 能跑,10 sec 約 90 秒 | v13 patch 才跑得通 |
| MuseTalk V1.5 512² | ❌ OOM | 需要 24GB |
| LatentSync 1.5 | ✅ 能跑,10 sec 約 110 秒 | face-on 純特寫 OK,複雜畫面嘴融化 |
| Wav2Lip 96² + GFPGAN v1.4 restore | ✅ 能跑,10 sec 約 70 秒 | 最穩 baseline |
| LivePortrait KJ | ✅ 能跑,但 idle talking head 才行 | 強表情失敗 |
| PuLID-Flux | ❌ wrapper 跟最新 ComfyUI transformer_options KeyError | 棄 |
| NoobAI XL Vpred 1.0 7.1GB(動漫 SDXL) | ✅ 能跑,1024² 約 25 秒 | v16 動漫轉向用 |
| IPAdapter Plus SDXL ViT-H | ✅ 能跑,weight 0.95 上限 | 1.5+ 開始 ghosting |
| ReActor face swap | ✅ 能跑 | 第 30 幀後仍會漂移 |
| GFPGAN v1.4 face restore(only_center_face) | ✅ 能跑,加在後製 | v6 過關關鍵 |
| YOLOv5l head detection | ✅ 能跑 | 比 OpenCV haar 穩 5 倍 |
| RIFE 補幀 24→48 fps | ✅ 能跑 | 加 smooth 用 |
| Ollama qwen3:14b(劇本生成) | ✅ 全 GPU 載入,40 tok/s | 主力 |
| Ollama gemma2:27b | ⚠️ CPU offload,18 tok/s,JSON 不穩 | fallback only |
2.4 5060 Ti 16GB 真正的瓶頸在哪
把 30 天的所有失敗歸納成一句話:
16GB VRAM 同時跑得動「圖生成 + 影片生成 + 對嘴 + 後處理」四件事的任意三件,但永遠不能同時跑四件。
打臉案例:
- Wan22 14B i2v + 鎖首幀:14B fp16 是 28GB,GGUF Q4_K_M 10GB 也不夠(KV cache + VAE decode 吃爆剩下的 6GB)
- MuseTalk 512²:要先 unload Flux 才能 load 512²,pipeline 變串列,量產速度砍半
- 同時跑兩個 character LoRA:LoRA 在 attention 層互相污染,雙人合照失敗率 100%
2.5 第二章的兩個結論
結論一:16GB 卡只能跑「影片生成」或「對嘴」其中一件當主任務,另一件用更小 fallback。
結論二:追《五十岁》品質的技術現實:至少 24GB VRAM(RTX 4090/5090)+ Wan22 14B + MuseTalk 512²。這是物理問題,不是調參。
教訓 2.1:先量你的 VRAM 再選 pipeline。 教訓 2.2:「16GB」spec 扣掉 CUDA context + Python runtime + KV cache,實際可用 12-13 GB。
第 3 章 v1.7 - v8:早期 baseline 與 Wav2Lip 路線
摘要:從 GGUF 量化想擠進 16GB VRAM、到 Wav2Lip 96² baseline 過關、到 MuseTalk mmcv build hell 三連敗,第一週踩出來的早期經驗。
3.1 v1.7(5/22):GGUF 量化 Wan22 14B i2v 的死亡幻想
第一個版本是 v1.7(前面 v1.0-v1.6 是劇本 + LoRA 訓練的子版本,影片生成從 v1.7 開始計)。
我的初始想法很單純:
- 跑 Wan22 i2v 14B 比 5B 多了「鎖首幀 + 連貫 motion」這兩個對短劇至關重要的能力
- 14B fp16 = 28GB 載不進 16GB
- 用 GGUF Q4_K_M 量化(10GB)+ ComfyUI-GGUF custom node 應該能擠進來
於是我 git clone 了 city96/ComfyUI-GGUF,下載 Wan22-I2V-14B-GGUF 的 Q4_K_M 檔(10GB),按照 README 接上 workflow,按下 queue。
# v1.7 啟動指令(已棄)
ssh user@192.168.0.15 'wsl -d Ubuntu -- bash -c "cd /home/user/ComfyUI && python main.py --listen 0.0.0.0 --port 8188"'
# Mac 端
curl -X POST http://127.0.0.1:28189/prompt -d @v1_7_test.json
結果:第一個 inference step 都還沒完成,VAE decode 階段直接 OOM。
我去看了一下 nvidia-smi:
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| 0 N/A N/A 12847 C python 15.7 GiB |
+-----------------------------------------------------------------------------+
OOM 不是 model 沒載完,是 model 載完了,VAE decode 要把 latent 還原成 720×1280 視訊張量時撐不住。GGUF 量化只省 model weight,但 KV cache + VAE decode 階段的 fp16 buffer 不會被量化,這是 GGUF 路線在影片任務上的硬傷。
踩坑 → 分析 → 教訓:
- 踩坑:以為 GGUF 量化能 = 量化後一切。
- 分析:GGUF 只量化 weights,inference 中間態(latent buffer / KV cache / VAE intermediate)還是 fp16,影片任務的 VAE decode 是吃 buffer 的重災區。
- 教訓 3.1:消費卡跑 14B i2v 在 2026 年 6 月是夢,要嘛 24GB 顯卡,要嘛回 5B。
3.2 v3 base 18 shot:黑底霓虹垃圾 sample
繞回 5B 之前,我先用 Wan22 5B 量產一批「Wedding Veil 婚禮短劇」18 shot 當對嘴 input。結果大半是這樣:

「黑底霓虹 + motion graphics + 角色五官漂移」三件套同時發作。前 10 幀正常,第 15 幀開始扭曲,第 30 幀後完全不是同一個人。Wan22 5B 第 30 幀後人臉漂移這條根因 30 天裡沒解掉。
3.3 v4 - v6(5/27):Sniper Shot06 三代迭代
整批 v3 不能用,我挑一個 shot(女主換新娘服的 close-up,叫 shot06)做 sniper,用所有可能的後處理硬把它修到能用。
v4:Flux + ReActor face swap

ReActor 第 1 幀完美,第 30 幀以後五官跑掉。ReActor frame-by-frame swap,沒 temporal consistency,每幀 landmark 微抖放大成跨幀漂移。
v5:加 PoseControlNet body lock

身體穩了,臉部一樣漂。ControlNet 只 condition pose 不 condition face。face 跟 body 一致性是兩個獨立問題。
v6:加 GFPGAN v1.4 only_center_face + YOLOv5l + Canny head bbox(真正過關)

最後 v6 過關的組合是:
# v6 sniper 後處理 pipeline(簡化版)
def v6_post_process(frame_dir, output_path):
frames = sorted(Path(frame_dir).glob("*.png"))
for f in frames:
# 1. YOLOv5l 偵測 head bbox(比 OpenCV haar 穩 5 倍)
bbox = yolov5l_head_detect(f)
# 2. Canny edge 找臉部邊緣,給 GFPGAN feather 用
head_mask = canny_head_mask(f, bbox)
# 3. GFPGAN v1.4 only_center_face restore
restored_face = gfpgan_restore(
f, only_center_face=True, bg_upsampler=None, weight=0.5,
)
# 4. paste back with 30px Gaussian feather
composited = paste_back_feather(f, restored_face, head_mask, feather=30)
cv2.imwrite(str(output_path / f.name), composited)

shot06 終於穩了。但代價是 v6 pipeline 跑一個 4 秒 shot 要 6 分鐘,整集 32 shot = 3.2 小時,已經接近量產的邊緣。
v4-v6 三代的教訓矩陣
| 版本 | 加什麼 | 解決什麼 | 沒解決什麼 |
|---|---|---|---|
| v4 | ReActor | 第 1 幀像 | 第 30 幀漂 |
| v5 | + PoseControlNet | body 穩 | face 仍漂 |
| v6 | + GFPGAN only_center_face | face 穩 | 速度慢 6 min / shot |
教訓 3.2:face 復原優先順序是 GFPGAN > CodeFormer > RestoreFormer(v6 我們三個都測過)。YOLOv5l 比 OpenCV haar 穩 5 倍,這是給後製做 head detection 的人記下來。
教訓 3.3:不要在 base model 階段試圖解 temporal consistency,後處理 GFPGAN + paste back feather 比改 Wan22 內參數有效十倍。
3.4 v7 LivePortrait:強表情的物理盲區
Flux 靜態 base + LP 注入表情。理論上對 idle talking head 處理很好。實測:✅ idle 微笑、輕點頭、眨眼完美;❌ 怒吼嘴糊 / 咬牙上下牙不開 / 側臉 > 15 度歪掉。五版全失敗。
短劇恰好「強表情」為主,LP 第 7 天就被砍。教訓 3.4:每個模型都有設計初衷決定的物理盲區。
3.5 v8 Wav2Lip baseline + MuseTalk mmcv build hell
v8 是 Wav2Lip 96² + paste back baseline,2020 年老模型勝在穩、輕、不挑硬體:
def wav2lip_pipeline(base_mp4, audio_wav, output_mp4):
face_stream = crop_face_stream(base_mp4, target_size=(96, 96))
synced_96 = wav2lip_inference(face_stream, audio_wav, "wav2lip_gan.pth")
composited = paste_back_with_feather(base_mp4, synced_96, feather_radius=30)
mux_audio(composited, audio_wav, output_mp4)
shot06 男主 + shot07 新娘 smoke test 完美。但 v3 base 18 shot 一半黑底霓虹垃圾,Wav2Lip 救不了「base 本身不能看」。
並行嘗試 MuseTalk 作為更高品質方案,撞上 mmcv 的牆。
MuseTalk 的 mmcv 編譯地獄
MuseTalk V1.0 依賴 mmcv-full 1.7.x,CUDA 12.8 + Blackwell sm_120 上要從原始碼編譯:
# 三連敗
pip install mmcv-full==1.7.0 # 找不到 cu128/sm_120 wheel
mim install mmcv-full==1.7.0 # 一樣
git clone .../mmcv -b 1.x && MMCV_WITH_OPS=1 pip install -e . -v
# → cannot find -lcudart_static → fix LIBRARY_PATH
# → sm_120 not supported → fix TORCH_CUDA_ARCH_LIST
# → 90 分鐘編譯後 ImportError: undefined symbol _ZN3c104impl...
8.7GB checkpoints 靜靜躺在 PC,但 mmcv 載不起來。MuseTalk mmcv build hell:永遠走 Wav2Lip。這個結論到 v13 才被推翻(用 face_alignment 取代 dwpose)。

v8 的結算
- ✅ Wav2Lip baseline 跑通,shot06/shot07 過關
- ❌ MuseTalk 因 mmcv 編譯失敗,整條棄
- ❌ v3 base 18 shot 大半垃圾,要重煉
教訓 3.5:當你發現一個 lib 要從原始碼編譯,而且是 CUDA C++ kernel,先確認有沒有同功能的純 PyTorch 替代品。mmcv 後來證明根本不必要,但我為它燒了 6 個小時編譯。
3.6 第三章的小結
第一週收穫:(1) GGUF 救不了 14B i2v;(2) Wan22 5B 81 幀 = 3.375 秒架構上限;(3) face swap + face restore 是兩件事;(4) LivePortrait 強表情盲區;(5) Wav2Lip 96² 是天花板;(6) MuseTalk mmcv 地獄要繞。
到這裡我以為「baseline 跑通,下面就是迭代品質」。事實證明我錯了,後面 23 天都在這個錯誤判斷的延伸線上。
第 4 章 v9 - v10:LivePortrait 與 LatentSync 進化
摘要:v9.1 用 GFPGAN restore 把 Wav2Lip 拉到能看,v10 拼 LatentSync 1.5 結果發現只能做純臉特寫。第二週的核心收穫是「沒有銀彈,只有適用場景」。
4.1 v9.1 大女主獨白工廠
v8 的 18 shot 重煉後,挑 8 個 close-up shot 做 v9.1 sniper:
# v9.1 corruption filter + auto rerun + GFPGAN 局部修復層
def v9_1_pipeline(base_mp4, audio_wav, output_mp4, max_retry=3):
for attempt in range(max_retry):
synced = wav2lip_inference(base_mp4, audio_wav)
if not is_mouth_corrupted(synced, threshold=0.85):
break # SSIM 對比嘴部,差異過大就 rerun
log.warning(f"[v9.1] attempt {attempt+1} corrupted, rerun")
restored = gfpgan_restore_video(synced, weight=0.5)
composited = paste_back_feather(base_mp4, restored, feather=30)
mux_audio(composited, audio_wav, output_mp4)
關鍵三招:corruption filter + auto rerun + GFPGAN only_center_face restore。8 個 shot 全綠,shot06 比較 v9.1 vs v10 LatentSync,v9.1 反而更穩。第一次意識到「最新模型 ≠ 最好結果」。
4.2 v10 LatentSync 1.5:本地對嘴的當代冠軍
3 個 agent 平行做 web research「2026 本地能跑、繁中支援、消費卡可裝對嘴模型」,共識指向 LatentSync 1.5(Apache-2.0、8GB VRAM、Whisper 中文、Blackwell sm_120 原生 wheel):
pip install latentsync==1.5.0
huggingface-cli download ByteDance/LatentSync-1.5 \
--local-dir /home/user/ComfyUI/models/latentsync
bride solo shot05/06/07 三個 face-on 特寫效果震撼:

對嘴精準度比 Wav2Lip 96² 高一檔,嘴形跟 audio waveform 逐幀對齊。我當時想:「對嘴問題解決了。」
4.3 LatentSync 的盲區:複雜畫面嘴部融化
把 LatentSync 餵給 shot04(女主梳妝台 + 手 + 首飾盒 + 臉的構圖)。嘴部完全融化 —— 不是對不準,是真的物理融化:嘴位置長出 third lip、皮膚紋理跟首飾盒紋理混在一起。
5 次跑 5 個 seed 全部一樣。4 個 agent 拆 root cause 結論:
LatentSync 1.5 的 face detection 在「臉 + 手 + 物」三元素同框時會誤判,把手或物的紋理當成臉的延伸,latent 階段把整個誤判區域當「嘴」生成。
模型架構級限制,沒辦法 fine-tune。LatentSync 只能用在 face-on 純特寫。
4.4 v9.1 vs v10 vs v12B2 對嘴技術 PK 矩陣
5/29 對三個對嘴方案 head-to-head 比較(30 test shot 評分):
| shot 類型 | Wav2Lip 96² (v8) | LatentSync 1.5 (v10) | Wav2Lip+GFPGAN (v9.1) |
|---|---|---|---|
| 純臉特寫 (10) | 7.5 | 9.5 | 8.5 |
| talking head (10) | 7 | 6 | 8 |
| 手+物+臉 (5) | 6 | 2 | 7 |
| 側臉 30° (3) | 5 | 3 | 6 |
| 強表情 (2) | 4 | 3 | 5 |
LatentSync 只贏純臉特寫;Wav2Lip+GFPGAN 在 4/5 場景拿最高。沒有銀彈是第二週最大教訓。這張表後來成為 v12 5 版失敗時的關鍵診斷工具。
4.5 第四章的小結
第二週核心收穫:(1) 沒有銀彈,每個對嘴模型都有適用場景;(2) 舊模型不過時,Wav2Lip 2020 加 GFPGAN 擊敗 2025 LatentSync;(3) community consensus ≠ your use case。
教訓 4.1:看到「state of the art」先問三問:demo 是不是純臉特寫;evaluation set 跟你 use case 像不像;limitations 段寫了什麼(這段是金礦)。
教訓 4.2:保留舊版本當 fallback,v14 量產時 talking_head dispatcher 就是 MuseTalk 為主 + v9.1 GFPGAN 為 fallback。
第 5 章 v11 - v12:PuLID-Flux 與 Wan22 五版失敗
摘要:v11 試 PuLID 取代 LoRA 失敗,v12 用 Wan22 5B + LatentSync 連續五版全部翻車,那一晚我寫了 handoff 文件準備認輸。
5.1 v11 PuLID-Flux:取代 LoRA 的美夢
13 LoRA 訓練花 30 小時(cache miss 197s/step → cache hit 70s/step 3x 差距)。痛點:(1) 每加角色重訓一次;(2) 多 LoRA 在 attention 互相污染,雙人合照 100% 失敗。
PuLID-Flux 承諾:不用訓 LoRA、給 reference image 就能 condition、多角色解雙人合照、ID 一致性更穩(cross-attention 而非 weight 改寫)。
裝 cubiq/ComfyUI_PuLID_Flux,第一個 KSampler 直接報錯:
KeyError: 'transformer_options'
File ".../ComfyUI_PuLID_Flux/pulid_flux.py", line 184, in patch_attention
options = model_options['transformer_options']
PuLID-Flux wrapper 跟最新 ComfyUI transformer_options API 不兼容,作者 4 個月沒更新。三個 workaround:(1) 降 ComfyUI 版本(半小時後放棄,Wan22 需要新版);(2) fork PuLID 手動 patch(patch 完效果跟 LoRA 差不多);(3) InstantID 不支援 Flux 棄。
13 LoRA 已訓完,PuLID 沒解雙人合照(attention 仍干擾),當天棄。
教訓 5.1:用 X 取代 Y 先問「X 真的解決 Y 的痛點嗎?」PuLID 沒解雙人合照,只是把「訓 LoRA」換「跑 inference」。 教訓 5.2:custom node 作者 4 個月沒更新 = 高風險,半年內必 break。
5.2 v12 五版全失敗:Wan22 + LatentSync 的完美風暴
5/28 晚是 30 天最痛的一晚。計畫 Wan22 5B i2v + LatentSync 對嘴量產 ep1 talking head。
v12 A:Wan22 5B i2v 鎖首幀直接失敗
5060 Ti 上沒有可用的「i2v 鎖首幀」node:
WanImageToVideoLatent:32GB VRAM 才能 forward,OOMWanFunControlToVideo:可 forward,但首幀只是 ref_image 風格參考,不是鎖第 1 幀IPAdapter + Wan22:IPAdapter 不支援 Wan22 video latent- 手動 latent 注入第 1 幀:跑通了但第 5 幀漂走
Anchor + Wan22 構圖完全脫鉤,Flux 跟 Wan22 是兩個故事。
v12 B:LatentSync 對複雜畫面嘴部融化
改 Plan B「Flux anchor → ffmpeg loop static base → LatentSync」。shot01 梳妝台「手 + 首飾盒 + 臉」鏡頭,LatentSync 又融化。Production 場景的第一次驗證。
v12 B2:復活 v9.1 Wav2Lip + GFPGAN restore
砍 LatentSync 砍 i2v,改 v9.1 路線:
# v12 B2 復活 v9.1 路線(核心 7 stage)
def v12_b2_pipeline(shot_spec, output_mp4):
# 1. Flux + LoRA → anchor 720×1280 png
anchor_png = flux_with_lora(
prompt=shot_spec.prompt,
lora=shot_spec.character_lora,
seed=shot_spec.seed,
)
# 2. ffmpeg Ken Burns zoom → 靜態 base mp4 (4s @ 24fps = 96 frame)
base_mp4 = ffmpeg_ken_burns(anchor_png, duration=4.0, zoom=1.05)
# 3. Edge TTS → audio.wav
audio_wav = edge_tts(shot_spec.dialogue, voice=shot_spec.voice)
# 4. InsightFace 偵測 face bbox track
face_bbox = insightface_detect(base_mp4, gender="female")
# 5. crop face stream → 96×96
face_stream = crop_face_stream(base_mp4, face_bbox, size=96)
# 6. Wav2Lip → synced 96×96
synced_96 = wav2lip(face_stream, audio_wav)
# 7. GFPGAN v1.4 restore (only_center_face) → synced_hq
synced_hq = gfpgan_restore_video(synced_96, weight=0.5)
# 8. paste back with 30px Gaussian feather
composited = paste_back_feather(base_mp4, synced_hq, feather=30)
# 9. mux audio
mux_audio(composited, audio_wav, output_mp4)
跑通了,shot01 出來能看,但整條 pipeline 跑一個 shot 要 6 分鐘。32 shot × 6 min = 3.2 hr,量產 30 集需要 96 hr GPU 連跑。
v12 B3 / B4
B3:F5-TTS voice clone 整合,5 次跑 4 次像、1 次崩,沒法量產。 B4:完全放棄 i2v,全部「Flux anchor + ffmpeg Ken Burns + Wav2Lip」,出來「PPT + 對嘴」,質感倒退到 2018 vTuber。
那晚的 handoff 文件
5/28 23:50 寫了 anchor-drama-handoff-20260521-v12-failed.md,預設隔天放棄 drama factory:
v12 五版全失敗結論:5060 Ti 16GB 跑不出「動 + 對嘴 + 一致性」三件套同時成立的 talking head。
隔天早上沒放棄,因為看到 MuseTalk V1.5 issue 提到 face_alignment 可繞 mmcv。這條線索把我拉進 v13。
5.3 v12 的最終 17.7 min 樣品
B2 路線最後硬跑出一個完整 ep1(17.7 分鐘)作為 baseline:

5.4 第五章的小結
第二週末核心收穫:(1) 5060 Ti 跑 Wan22 5B 沒有可用 i2v 鎖首幀 node;(2) LatentSync 對「臉 + 手 + 物」場景必死;(3) PuLID-Flux 跟最新 ComfyUI API 斷層;(4) F5-TTS 中文 voice clone 5 次 4 次像 1 次崩,沒法量產。
教訓 5.3:當某個版本「全部失敗」,不要急著推翻架構。寫 handoff 睡一覺,第二天常會發現失敗的是子路線不是方向。v12 → v13 就是這樣翻過來的。
教訓 5.4:保留「最爛但能跑」的 baseline。v12 B4 純靜態 PPT 對嘴雖爛,但是「下限保底版」。
第 6 章 v13 突破:MuseTalk V1.5 face_alignment 68 patch
摘要:30 天裡最重要的一個技術突破。三個 patch 把 MuseTalk V1.5 在 5060 Ti Blackwell sm_120 上跑通 256²,把對嘴品質從 Wav2Lip 96² 拉到完全不同的檔次。但這個突破也是後面 v14 量產翻車的種子。
6.1 5/29 早上的線索
前一晚 v12 handoff 寫完去睡。早上在 MuseTalk repo issue 看到一則:
When using face_alignment library instead of dwpose for landmark detection, MuseTalk runs without mmcv. Tested on RTX 4090.
立刻 pip install face-alignment==1.4.1,30 秒裝完。比起 mmcv 6 小時編譯地獄,這條線索像免費禮物。但事情沒這麼簡單。
6.2 三個關鍵 patch
MuseTalk V1.5 在 5060 Ti Blackwell sm_120 跑通 256² 需要 3 個 patch:
Patch 1:preprocessing.py 用 face_alignment.fa.get_landmarks() 取代 dwpose
MuseTalk 原本用 mmcv dwpose 做 68 點 face landmark(dlib 格式),改用 face_alignment lib(同 68 點 dlib 格式):
# musetalk/utils/preprocessing.py(patch 後)
import face_alignment
class FaceAlignmentLandmarkExtractor:
def __init__(self, device='cuda'):
# 關鍵:必須用 standalone face_alignment lib(不是 face_detection.FaceAlignment)
self.fa = face_alignment.FaceAlignment(
face_alignment.LandmarksType.TWO_D,
device=device,
flip_input=False,
face_detector='sfd',
)
def get_landmarks(self, frame_bgr):
# face_alignment 期待 RGB
frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
# 輸出 68×2 numpy array(dlib 格式:jaw 0-16, brow 17-26, nose 27-35, eyes 36-47, mouth 48-67)
landmarks_list = self.fa.get_landmarks(frame_rgb)
if landmarks_list is None or len(landmarks_list) == 0:
return None
return landmarks_list[0] # 取第一張臉
關鍵細節:face_alignment.FaceAlignment 是 standalone lib,不是 face_detection.FaceAlignment(那是 face_detection 套件內部類別,名字像但完全不同)。我踩了一小時。
Patch 2:7 個 file 加 weights_only=False
PyTorch 2.6+ torch.load() 預設 weights_only=True,對 MuseTalk 舊 checkpoint 是 breaking change。搜尋整個 musetalk/ 目錄 7 個檔案(vae.py / unet.py / audio_encoder.py / audio_processor.py / preprocessing.py / inference.py / realtime/runner.py)所有 torch.load() 加 weights_only=False。
Patch 3:V1.5 config path
model:
unet_config: ./models/musetalkV15/musetalk.json
unet_model_path: ./models/musetalkV15/unet.pth
vae_type: sd-vae-ft-mse
whisper_model_path: ./models/whisper
inference:
bbox_shift: 0 # 關鍵:V1.5 必須 0,不能 V1.0 ±5
fps: 25
6.3 三個地雷
跑通後連踩三個地雷,每個浪費 1-2 小時:
地雷 1:mediapipe FaceMesh 索引不對應 dlib 68 點。想偷懶用 mediapipe(更快),結果嘴部完全不動。mediapipe 是 478 點,索引完全不對應。MuseTalk 用 dlib mouth 索引(48-67)做 latent injection,餵 mediapipe 等於餵錯位置 → 在「鼻子的地方」生嘴形。必走 face_alignment lib。
地雷 2:bbox_shift V1.5 必須 0。V1.0 預設 ±5,V1.5 必須 0。用 V1.0 預設跑,嘴的位置在鼻孔下方 5 pixel。DEFAULT_BBOX_SHIFT = 0。
地雷 3:yaml 路徑相對位置。MuseTalk 預設從 musetalk/ 目錄跑,yaml 的 video_path 是 ../ComfyUI/,從 custom_nodes 跑要改 ../../ComfyUI/。最後 hardcode 絕對路徑避免坑。
6.4 跑通後的 range 驗證
ssh user@192.168.0.15 'wsl -d Ubuntu -- bash -c "
cd /home/user/ComfyUI/custom_nodes/MuseTalk &&
python -m scripts.inference --inference_config configs/inference/test.yaml \
--result_dir /home/user/drama-factory/data/control/v13_smoke"'
# log
[18:22:14] face_alignment landmarks: 68 points detected
[18:22:15] bbox_shift range: [-0~0] ✓
[18:23:42] frame 250/250 inference complete
shot06 對嘴完美、range [-0~0] 完美、Whisper 中文對齊精準。v13 突破是 30 天裡少數讓我覺得「對,這條路可以」的時刻。
6.5 v13 patch 流程速覽
clone MuseTalk V1.5 → 試 mmcv(6 小時編譯地獄棄)
→ pip install face-alignment(30 秒)
→ Patch 1: preprocessing.py 用 fa.get_landmarks() 取代 dwpose
→ Patch 2: 7 個 file 加 torch.load(weights_only=False)
→ Patch 3: configs/v1.5.yaml bbox_shift: 0
→ smoke ✓ 68 landmarks ✓ range [-0~0] ✓ VRAM 2.8 GB
6.6 v13 的代價
v13 成功讓我做出致命判斷:MuseTalk 跑通 = 對嘴問題解決 = 可以量產。事實是 256² 上限導致 v14 量產 17.7 min ep1 後用戶第一個批評就是「嘴模糊」。升 512² 要 24GB VRAM,30 天沒解掉。
6.7 第六章的小結
核心收穫:(1) face_alignment lib 是消費卡 MuseTalk 救星,30 秒安裝取代 6 小時 mmcv;(2) mediapipe FaceMesh ≠ dlib 68 點,硬塞會崩;(3) bbox_shift V1.5 必須 0;(4) 跑通 ≠ 可量產,256² 上限決定「嘴模糊」是物理事實。
教訓 6.1:「works on 4090」的 patch 在 5060 Ti 上常常只能跑更小解析度。教訓 6.2:替代品 patch 必做嚴格 output format 驗證,「68 points」字面相同座標系可能完全不同。
第 7 章 v14 量產翻車:450 shot 21 hr 用戶 7 個批評
摘要:v13 突破帶來的虛假信心讓我們直接進入量產,21 小時跑完一個 17.7 分鐘的 ep1,交付當天被批 7 項,每一項都是物理性無解。沒做 smoke test 是這 30 天最大的單一錯誤。
7.1 v14 的雄心壯志
v13 跑通隔天(5/30)做了 v14 量產 SOP。核心是 4 type sniper dispatcher:
v14 量產 dispatcher 流程
┌───────────────────────┐
│ shot_spec from script │
│ (JSON, 450 sub-shot) │
└──────────┬────────────┘
│
▼
┌──────────────────────┐
│ shot_type router │
└──────────┬───────────┘
│
┌────────┼────────────┬─────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌──────┐ ┌──────┐ ┌─────────────┐ ┌──────────┐
│ cut │ │static│ │ talking │ │ action │
│ away │ │ pose │ │ head │ │ │
├──────┤ ├──────┤ ├─────────────┤ ├──────────┤
│Flux │ │Flux+ │ │Flux + LoRA │ │Flux+LoRA │
│+ loop│ │LoRA+ │ │+ Edge TTS │ │+ Wan22 5B│
│ │ │Ken │ │+ MuseTalk │ │ti2v 81fr │
│~1 min│ │Burns │ │+ 字幕 │ │+ 字幕 │
│ │ │~1.5 │ │~3 min │ │~7 min │
│ │ │ min │ │ │ │ │
└──────┘ └──────┘ └─────────────┘ └──────────┘
episode_v14_runner.py 完整的 dispatcher 片段(這是真實程式碼):
# episode_v14_runner.py 真實片段
"""episode_v14_runner — 漫剧 v14 統一 dispatcher,按 shot_type 路由 4 種 pipeline
shot_type:
cutaway → Flux 1 圖 + ffmpeg loop (2-3 sec, 無對白) ~1 min
static_pose → Flux + LoRA + ffmpeg Ken Burns zoom (2-3 sec) ~1.5 min
talking_head → Flux + LoRA + Edge TTS + MuseTalk + 字幕 ~3 min
action → Flux + LoRA + Wan22 5B ti2v + 字幕 ~7 min
每 shot 獨立 mp4,concat 由 batch script 處理。
"""
EPISODE = "v14_ep1"
RESOLUTION = (720, 1280)
FPS = 24
# 角色 ID → LoRA 檔名 + trigger
CHAR_LORA = {
"female_lead": ("soxw_zh50_v1_100step_rank4_fp16-step00100.safetensors", "soxw_zh50"),
"male_lead": ("fujx_zh48_v1_100step_rank4_fp16-step00100.safetensors", "fujx_zh48"),
"antagonist_ex_husband": ("chenjh_zh53_v1_100step_rank4_fp16-step00100.safetensors", "chenjh_zh53"),
"daughter": ("chenyl_zh23_v1_100step_rank4_fp16-step00100.safetensors", "chenyl_zh23"),
"antagonist_secretary": ("linyq_zh28_v1_100step_rank4_fp16-step00100.safetensors", "linyq_zh28"),
"assistant": ("lim_zh35_v1_100step_rank4_fp16-step00100.safetensors", "lim_zh35"),
}
CHAR_VOICE = {
"female_lead": "zh-CN-XiaoxiaoNeural",
"male_lead": "zh-CN-YunjianNeural",
"antagonist_ex_husband": "zh-CN-YunyangNeural",
"daughter": "zh-CN-XiaoyiNeural",
"antagonist_secretary": "zh-CN-XiaomengNeural",
"assistant": "zh-CN-YunxiNeural",
}
# Wan22 5B 配置
WAN_UNET = "wan2.2_ti2v_5B_fp16.safetensors"
WAN_CLIP = "umt5_xxl_fp8_e4m3fn_scaled.safetensors"
WAN_VAE = "wan2.2_vae.safetensors"
WAN_FRAMES = 81 # 3.4 sec @ 24fps
7.2 5/31 - 6/1 的 21 小時連跑
5/31 18:00 啟動,6/1 15:00 跑完。Mac keeper 保活 ssh:
nohup bash -c 'echo "sleep 108000" | ssh -o ServerAliveInterval=15 \
user@192.168.0.15 "wsl -d Ubuntu -- bash"' > /tmp/wsl_keeper.log 2>&1 &
成果:450 sub-shot / 17.7 min / 720×1280 / ep1_FULL.mp4 280 MB。平均 168 sec/sub-shot。我跟自己說「30 天磨一劍」,上傳給用戶。
7.3 用戶 7 項批評
15 分鐘後用戶回我七條,每條都對:
| # | 批評 | 根因 | 解法 |
|---|---|---|---|
| 1 | 嘴模糊 | MuseTalk 256² 上限,paste back 到 720×1280 上採樣 2.8x | 升 512² 需 24GB VRAM,無解 |
| 2 | 配音單調 | Edge TTS 免費版不支援 <mstts:express-as> |
上 Azure Premium(NT$0.05/字)/ ElevenLabs |
| 3 | 沒 BGM | v14 dispatcher 根本沒寫 BGM 邏輯 | v15 加(執行 bug) |
| 4 | 角色不一致 | 每 shot 獨立 Flux inference,seed 不同 → 五官微漂 | seed 鎖角色 ID hash + IPAdapter ref |
| 5 | 沒多角色 | script 全女主獨白,cutaway 全 talking head | script writing 問題 |
| 6 | 運鏡失敗 | cutaway 是 ffmpeg loop,static_pose 是 Ken Burns,無推拉 pan whip | v15 加 camera-aware vf |
| 7 | 角色沒動作 | cutaway loop 不會讓人物動,只有嘴動 | 全改 action type 量產時間 21 → 100+ hr 不現實 |
7.4 為什麼沒做 smoke test
整個 v14 最關鍵問題:為什麼 21 hr 量產之前不先 30 sec smoke test?
心路歷程:(1) v13 MuseTalk 跑通讓我以為對嘴問題解決;(2) dispatcher 4 type 都單獨 sniper 測過;(3) 「個別 OK → 組合一定 OK」的盲信;(4) 沒考慮「個別 30 sec」跟「連續 17 min」是兩種體驗;(5) 沒考慮執行細節(BGM 忘加、運鏡沒寫)會在量產時被放大。
根本錯誤:把「技術可行性驗證」當成「成品驗證」。技術可行性證明「能跑」,成品驗證證明「能看」,兩件事。
7.5 v14 翻車的 bug 大全
除了用戶 7 項,內部還有:MuseTalk alpha 接縫(v15 feather 60px)、Edge TTS 偶發中斷(retry+cache)、Wan22 30 幀後人臉漂(無解)、concat audio offset 1 frame、ttc 字型 ffmpeg 偶發崩、中文標點渲染怪、Ken Burns 中心點全相同。
7.6 第七章的小結
v14 是量產時間最長、回饋最痛的版本。核心收穫:(1) 21 hr 量產 = 沒中途 sanity check 的代價;(2) 個別 sniper 過 ≠ 整集量產過,累積感受是另一維度;(3) 技術可行性 ≠ 成品可看性,兩種驗證需要兩種人;(4) MuseTalk 256² 上限再多後處理救不了;(5) Edge TTS 免費版不能做產業配音。
教訓 7.1:量產前必跑 30 秒 smoke test(dispatcher 所有 type 各 1 shot concat),用戶簽核才動 21 hr。 教訓 7.2:寫 dispatcher 時,BGM / 運鏡 / 字幕 / 角色一致性列在 checklist 最上面,否則量產一定忘。 教訓 7.3:「跑通 ≠ 可量產 ≠ 可上線」,每個 ≠ 號吃掉 1 週時間。
第 8 章 v15 - v16:SSML 情感 TTS 與 50 角色動漫轉向
摘要:v15 試圖修 v14 七大缺陷,剛跑通 smoke 用戶就轉向動漫。v16 NoobAI XL Vpred SDXL + IPAdapter Plus 50 角色全套,IPAdapter 兩個 bug 修完跑 460-shot batch 一樣翻車。
8.1 v15 修 7 缺陷
6/1 - 6/3 系統性修 v14 七大缺陷:
8.1.1 SSML 22 emotion 映射
Edge TTS 雖不支援 <mstts:express-as>,但可用 <prosody rate pitch volume> 三維度組合模擬 emotion。22 種 emotion 映射表:
# v15 SSML emotion map(22 種 emotion)
EMOTION_PROSODY = {
"neutral": {"rate": "0%", "pitch": "+0Hz", "volume": "+0%"},
"happy": {"rate": "+10%", "pitch": "+10Hz","volume": "+5%"},
"sad": {"rate": "-15%", "pitch": "-10Hz","volume": "-5%"},
"angry": {"rate": "+5%", "pitch": "+15Hz","volume": "+15%"},
"fear": {"rate": "+15%", "pitch": "+5Hz", "volume": "-10%"},
"surprise": {"rate": "+20%", "pitch": "+20Hz","volume": "+10%"},
"disgust": {"rate": "-5%", "pitch": "-5Hz", "volume": "+0%"},
"shocked": {"rate": "-10%", "pitch": "+10Hz","volume": "+15%"},
"devastated": {"rate": "-20%", "pitch": "-15Hz","volume": "-10%"},
"determined": {"rate": "-5%", "pitch": "+5Hz", "volume": "+10%"},
"tender": {"rate": "-10%", "pitch": "-5Hz", "volume": "-5%"},
"sarcastic": {"rate": "-5%", "pitch": "-10Hz","volume": "+0%"},
"whispering": {"rate": "-15%", "pitch": "-5Hz", "volume": "-20%"},
"shouting": {"rate": "+5%", "pitch": "+20Hz","volume": "+20%"},
"crying": {"rate": "-15%", "pitch": "-15Hz","volume": "-10%"},
"laughing": {"rate": "+10%", "pitch": "+15Hz","volume": "+10%"},
"narration": {"rate": "-5%", "pitch": "+0Hz", "volume": "+5%"},
"monologue": {"rate": "-10%", "pitch": "+0Hz", "volume": "+0%"},
"exclamation": {"rate": "+5%", "pitch": "+15Hz","volume": "+15%"},
"question": {"rate": "+0%", "pitch": "+10Hz","volume": "+5%"},
"intimate": {"rate": "-15%", "pitch": "-5Hz", "volume": "-10%"},
"dramatic": {"rate": "-10%", "pitch": "+5Hz", "volume": "+10%"},
}
def build_ssml(text, voice, emotion="neutral"):
p = EMOTION_PROSODY.get(emotion, EMOTION_PROSODY["neutral"])
return f"""<speak xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:mstts="http://www.w3.org/2001/mstts"
version="1.0" xml:lang="zh-CN">
<voice name="{voice}">
<prosody rate="{p['rate']}" pitch="{p['pitch']}" volume="{p['volume']}">
{text}
</prosody>
</voice>
</speak>"""
22 種 emotion 確實有差別,但 Edge TTS rate ±20% 上限,「shouting」跟「crying」prosody 不同,聽起來還是「同一個人不同節奏」,沒有真正情感層次。
8.1.2 Camera-aware ffmpeg vf(運鏡)
v15 加 7 種 ffmpeg vf 運鏡:
# v15 camera-aware ffmpeg vf 運鏡映射
CAMERA_VF = {
"push_in": "zoompan=z='min(zoom+0.0015,1.5)':d=125:s=720x1280:fps=24",
"pull_back": "zoompan=z='if(eq(on,0),1.5,max(zoom-0.0015,1.0))':d=125:s=720x1280:fps=24",
"whip_pan": "crop=720:1280:'min(t*200,iw-720)':0,scale=720:1280",
"pan_left": "crop=720:1280:'iw-720-t*30':0,scale=720:1280",
"pan_right": "crop=720:1280:'t*30':0,scale=720:1280",
"low_angle": "perspective=x0=0:y0=H*0.1:x1=W:y1=H*0.1:x2=0:y2=H:x3=W:y3=H",
"over_shoulder": "crop=720:1280:'iw*0.2':'ih*0.1',scale=720:1280",
}
def apply_camera(input_mp4, output_mp4, camera_type):
vf = CAMERA_VF.get(camera_type, "null")
subprocess.run([
FFMPEG, "-y", "-i", str(input_mp4),
"-vf", vf, "-c:v", "libx264", "-preset", "medium", "-crf", "18",
str(output_mp4),
], check=True)
有運鏡感了,特別是 push_in / pan_left 對「女主決心離婚」很好用。但 ffmpeg zoompan 是固定中心點推拉,沒有 cinematic「motivated motion」感。
8.1.3 BGM mixing(-22 to -28 dB)+ ducking
# v15 BGM ducking 公式(ffmpeg sidechain)
ffmpeg -y -i dialogue.wav -i bgm.mp3 -filter_complex "
[1:a]volume=-25dB,acompressor=threshold=-21dB:ratio=8[bgm_c];
[0:a][bgm_c]sidechaincompress=threshold=0.05:ratio=20:attack=20:release=250[bgm_d];
[0:a][bgm_d]amix=inputs=2:duration=first" -c:a aac -b:a 192k out.aac
對白時 BGM 自動降,沒對白時浮回來。
8.1.4 雙層 unsharp + 同源 seed
- 雙層 unsharp:5×5 luma 0.5 + 3×3 chroma 0.3,perceived sharpness +20%
- 同源 seed:
hash(character_id) % 2^32,同角色所有 shot 鎖住五官
8.1.5 v15 結算:smoke only
sub0001(女主獨白 4 秒)smoke 全綠:SSML / 運鏡 / BGM / unsharp 都 OK。但用戶看完直接說:
「真人短劇我看夠了,轉動漫吧。動漫不用對嘴、不用 LoRA、不用 Edge TTS,純無對話漫剧就好。」
v15 在 smoke only 階段擱置,v16 直接轉向動漫。
8.2 v16 動漫轉向:NoobAI XL Vpred + IPAdapter Plus
v16 spec:NoobAI XL Vpred 1.0(7.1 GB SDXL v-prediction)+ 832×1216 + IPAdapter Plus ViT-H ref + 50 角色(f01-f28 女 / m01-m18 男 / x01-x04 special)+ 無對嘴 + 無 LoRA。
50 角色命名(節錄):
female_characters:
f01: { name: "林夏", age: 22, type: "elegant" }
f02: { name: "蘇妮", age: 24, type: "sexy" }
f03: { name: "沐雪", age: 28, type: "villain" }
# ... f04-f28
male_characters:
m01: { name: "沈逸", age: 28, type: "ceo" }
m02: { name: "顧寒", age: 32, type: "villain" }
# ... m03-m18
special_characters:
x01: { name: "陳阿姨", age: 50, type: "aunt" }
x03: { name: "Boss 女王", age: 45, type: "villain_lady" }
# ... x02, x04
四張角色 ref 圖(IPAdapter 條件源):




8.3 IPAdapter 2 個 bug
v16 第一個 batch 撞兩個 bug:
Bug 1:IPAdapter 缺 weight_type → HTTP 400
wf["12"] = {"class_type": "IPAdapter", "inputs": {
"model": ["11", 0], "ipadapter": ["11", 1], "image": ["10", 0],
"weight": 0.7, "start_at": 0.0, "end_at": 0.95,
"weight_type": "standard"}} # ← 缺這個就 400
Bug 2:ClipVision model not found
cd /home/user/ComfyUI/models/clip_vision/
cp clip_vision_h.safetensors CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors
8.4 v16 460-shot batch 翻車
兩個 bug 修完跑 460-shot 動漫 batch(5 集 × 92 shot/集)8 hr 結果:
- ✅ IPAdapter ref 鎖臉一致性比 v14 LoRA 好
- ❌ IPAdapter weight 0.7 像度 60%,0.95 像度 85% 開始 ghosting,1.5+ 雙臉重疊
- ❌ 服裝不鎖(沈逸 CEO shot01 黑西裝 / shot02 藍襯衫 / shot03 灰風衣)
- ❌ 場景一致性差(每 shot 獨立 SDXL inference 背景風格漂)
最致命「服裝不鎖」—— 觀眾看 5 分鐘就跳出。「無對嘴漫剧」表面簡化問題,實際暴露 IPAdapter 在跨 shot 服裝一致性的物理盲區。
8.5 v16 vs v14 對比
| 維度 | v14 真人 talking | v16 動漫 silent |
|---|---|---|
| 臉一致性 | 70%(LoRA + 每 shot 漂) | 85%(IPAdapter) |
| 服裝一致性 | 75%(LoRA 學服裝) | 50%(不鎖服裝) |
| 對嘴 / 配音 | 256² 模糊 / 單調 | N/A / 純旁白 |
| 量產速度 / 集成本 | 168 sec/shot / 21 hr 17min | 60 sec/shot / 8 hr 5min |
| 整體可看性 | 6/10 | 5/10 |
v16 量產更快但可看性下降。「動漫風格」對 prompt + reference 容錯度更低,一個 frame 不對整集掉 line。
8.6 第八章的小結
核心收穫:(1) 修 7 缺陷代價 3 天,用戶可能下一秒轉方向;(2) SSML 22 emotion 在 Edge TTS 只是「假裝有層次」;(3) 「無對嘴」表面簡化實際引入服裝一致性問題;(4) IPAdapter 鎖臉強鎖服裝弱。
教訓 8.1:spec 變動敏感階段先做 modular dispatcher,monolithic pipeline 一變就全砍重寫。 教訓 8.2:「跨 shot 一致性」需要「臉 + 髮 + 服裝」三件套,2026/6 沒有單一技術完整解決。
第 9 章 v17 10 秒 demo 四連戰:認輸的那一刻
摘要:v14 翻車後我們縮回去做 10 秒 demo 驗證可行性。v17 從愛情劇到武俠,連續四版迭代,每版都修舊問題引入新問題,最後第四版交付時用戶說「武打太慢、臉扭曲、配音慢」,我承認 5060 Ti 16GB 已是天花板,30 天結束。
9.1 為什麼縮回 10 秒 demo
v14 量產 17.7 min 被批 7 項、v16 460-shot batch 翻車,「先量產再說」代價太大。v17 鐵律:每版只 10 秒 demo(3 shot × 3.4 sec)→ 用戶簽核 → 才放大。
9.2 v17 v1:愛情劇(沈逸 + 林夏 office 10 秒)
3 shot(pull back / push in two-shot / close-up reaction),MuseTalk V1.5 對嘴 + 22 emotion SSML。✅ IPAdapter 鎖臉 + Wan22 push in 有 cinematic 感;❌ 嘴模糊(256² 老問題)+ 嘴形精準度低(office 背景有椅子 + 桌面,MuseTalk 在這場景也開始抖)。
我自評 65 分,用戶沒簽核,叫換武俠題材試試。
9.3 v17 v2:武俠拔劍 10 秒
3 shot(aerial / combat / reveal),紅衣 hero solo + Edge TTS 雲健旁白。用戶批 4 點:
- SFX 太弱:劍擊聲、馬蹄聲、風聲沒加
- 旁白不夠大聲:+15% 仍被 BGM 蓋過
- 台詞爛:「風起雲湧,江湖再現」國中作文等級
- 鏡頭近、動作慢:3 shot 都 close to mid,Wan22 motion 偏慢
查 motion_prompt 發現我自己寫的全是「slow cinematic / ultra-slow majestic」,自己把節奏放慢。
9.4 v17 v3:v2 修 → 引入 3 個新 bug
v3 修 v2 4 點(motion_prompt 改快 / 旁白 +25% + SFX / 台詞重寫 / 鏡頭層次),結果撞到 3 個新 bug:
Bug 1:前幾秒白屏
# v3 fade transition(錯誤版)
fade_filter = "fade=t=in:st=3.35:d=0.1:color=white:alpha=0"
alpha=0 在 ffmpeg fade 是「淡入起點 alpha=0」意思是「前面全幀填充色」,不是「沒有 alpha 效果」。前 3.35 秒全幀白溢出。文件沒讀清楚的代價。
Bug 2:Wan22 cfg 8.0 timeout 1800s
cfg 6.0 推到 8.0 想「motion 強一點」,ComfyUI step 18/20 直接 hang,1800s timeout 也沒 return。root cause:Wan22 5B cfg > 7.5 時 KV cache 在某 attention layer 累積到 OOM 但不報錯,整個 inference loop hang。改回 cfg 6.5 穩定。
Bug 3:ComfyUI VRAM zombie 15.8 GB at 0% util
inference 結束但 ComfyUI 進程持有 15.8 GB VRAM、GPU util 0%、Python interpreter alive。custom node crash 後 python 沒 unload model:
# VRAM zombie 急救三連
ssh user@192.168.0.15 'wsl -d Ubuntu -- bash -c "
pkill -9 -f \"python main.py\"; sleep 2
fuser -k /dev/nvidia*; sleep 2
nvidia-smi --gpu-reset || true"'
9.5 v17 v4:最後一搏
v4 調整:字幕 FontSize 32→26、MarginV 80→50;HERO_LOCK weight 1.3→1.5;IPAdapter weight 0.7→0.95;Wan22 cfg 6.5(v3 教訓)。
真實程式碼片段(武俠 hero lock):
# v17_wuxia_v4.py 真實 HERO_LOCK 配置
HERO_LOCK = (
"(same handsome wuxia warrior:1.5), "
"(same long black hair tied with red ribbon:1.4), "
"(same crimson red silk robe with gold dragon embroidery:1.5), "
"(same young 25 years old strong man), "
"(same sharp piercing eyes:1.2), "
"(holding same jade-hilted sword:1.4), "
"masculine warrior, Asian male, dark hair, red clothing"
)
# 鎖角色串:3 個 motion 都重複
CONSISTENCY_LOCK = (
"same character, same red robe, same long black hair, "
"same red ribbon, same jade sword, consistent appearance throughout"
)
NEG_SDXL = (
"worst quality, low quality, lowres, blurry, jpeg artifacts, "
"bad anatomy, bad hands, missing fingers, "
"modern clothing, suit, tie, t-shirt, jeans, glasses, "
"watermark, signature, text, ugly, deformed, "
"asymmetrical face, ugly face, plain face, "
"(close-up:1.3), (portrait:1.3), face only, head only, "
"talking, dialogue, speaking, "
"different clothing, color change, hairstyle change, "
"flat shading, line art"
)
NEG_WAN = (
"text, watermark, blurry, deformed, frozen, static, "
"close-up portrait, talking head, "
"character change, color shift, clothing change, hair change"
)
跑出來:

技術指標:
- ✅ 前 3.35 秒不再白屏
- ✅ Wan22 cfg 6.5 穩定 inference
- ✅ ComfyUI 無 VRAM zombie
- ✅ 字幕位置 OK
- ✅ HERO_LOCK 1.5 角色一致性提升
9.6 用戶最終 3 個批評(無解)
v4 交付,用戶回三條無解物理盲區:
- 武打太慢:Wan22 5B prompt-driven motion,「fast」實際還是 diffusion 平均速度。需 14B 才解,5060 Ti 跑不動
- 臉扭曲:Wan22 5B 第 30 幀後人臉漂移,需 14B 才解
- 配音慢:Edge TTS rate +20% 是天花板,再快卡頓變慢動作,需付費 SSML API(Azure / ElevenLabs)
我對著這三條看了 30 分鐘,打開 CLAUDE.md 寫下:
honest admit:5060 Ti 16GB 已天花板。30 天 17 版證明本地消費卡跑不動產業級短劇生成。下一步:認輸轉雲端 / 寫教科書。
然後我寫了這篇文章。
9.7 v17 四連戰時間消耗
v1 愛情劇 4 hr → 嘴模糊;v2 武俠 5 hr → 4 缺陷;v3 修 v2 8 hr → 引入 3 bug;v4 修 v3 6 hr → 認輸。合計 23 hr / 4 個 demo / 0 過關。
9.8 為什麼 v17 在 10 秒 demo 階段就認輸
v14 教訓是「不要先量產」,v17 嚴格遵守「先 10 秒 demo」,但 v17 v4 仍失敗 —— 不是流程問題,是無論怎麼 demo,10 秒裡仍會曝露「嘴模糊 / 臉漂 / 配音慢」三個物理盲區。
- v14 失敗 = 流程問題(沒 smoke test)→ 可修
- v17 失敗 = 物理問題(硬體 + 模型上限)→ 改不了,除非換硬體(24GB+)或換 pipeline(雲端)
9.9 第九章的小結
核心收穫:(1) 10 秒 demo smoke test 是對的,但不能 cure 物理盲區;(2) prompt engineering 救不了 motion speed,Wan22 5B 的動作速度是 model bias;(3) 每次「修」會「引入新 bug」,pipeline 複雜度導致「修一處壞兩處」;(4) 白屏 / cfg hang / VRAM zombie 是 ComfyUI 量產隱性炸彈。
教訓 9.1:根因是「物理盲區 + 硬體限制」就停止迭代,直接寫認輸文件轉路線。每多迭代一版是 4-8 小時。
教訓 9.2:ffmpeg filter 第一次用先讀官方文件,「alpha=0」這種字面意思跟行為不同的坑滿地都是。
教訓 9.3:ComfyUI VRAM zombie 真實存在,量產每 batch 後加 pkill + fuser -k + restart,否則 50 shot 後 GPU 卡死。
第 10 章 終章:本地 vs 雲端的最終決勝
摘要:把 30 天的真實成本算給你看。一張對照表 + 雲端 vs 本地時序圖 + 給後來者的 10 條建議。看完這章你會理解為什麼 2026 年 6 月的「本地全免費」是工程師最大的自我欺騙。
10.1 本地 vs 雲端 真實成本對照
下面這張表是 30 天結束時我們對所有可用方案做的硬比較:
| 維度 | 本地 5060 Ti 16GB | Dreamina | Kling 1.6 | Runway Gen-3 |
|---|---|---|---|---|
| 一次性硬體成本 | NT$15,000 | 0 | 0 | 0 |
| 每月電費(30 天 GPU 全速) | NT$650 | 0 | 0 | 0 |
| 每 clip 成本(10 秒) | "免費" | 免費(225 點 / 天) | NT$10 | $1 |
| 影片品質(10 分滿分) | 60 分 | 90 分 | 95 分 | 98 分 |
| 角色一致性 | 差(face drift) | 好(內建 character ref) | 極好(character lock) | 極好 |
| 中文配音 | Edge TTS 免費版單調 | 內建情感配音 | 內建情感配音 | 需另接 ElevenLabs |
| 對嘴 | MuseTalk 256² 模糊 | 內建 | 內建 | 需另接 |
| 30 集成本(30 × 5 min ≈ 90 個 10s clip / 集 × 30 = 2700 clip) | "免費" + 1 個月血淚 | 免費(225 點 / 天 = 11 個 clip / 天 → 246 天) | NT$27,000 | $2,700 |
| 上手時間 | 30+ 天 | 30 分鐘 | 30 分鐘 | 1 小時 |
| 1 集量產時間(90 clip) | 21+ hr | 8 hr(手動)/ 2 hr(API) | 2 hr | 1 hr |
| API 可程式化 | 完全 | 部分 | 完全 | 完全 |
10.2 30 集真實成本拆解
以 30 集 × 5 分鐘短劇為例:
本地 vs 雲端 30 集成本時序圖
本地路線(5060 Ti 16GB):
Day 1-30 │ 17 版開發 + 0 集上線
Day 31-56 │ 假設能繼續,每集量產 21 hr × 30 ≈ 26 天 GPU 連跑
─────────│
電費 NT$823 + 硬體攤提 NT$780 + 人力 56×8×NT$1000 = NT$449,603
最終結果:0 集上線(30 天結束時連 1 集 demo 都沒過用戶簽核)
雲端路線(Kling 1.6):
Day 1 │ 註冊 + 看 demo
Day 2-5 │ 30 集劇本 + 主視覺
Day 6-15 │ API 串接 + batch 腳本
Day 16-30 │ 30 集 × 90 clip × NT$10 = NT$27,000 直接量產
─────────│
API NT$27,000 + 人力 30×8×NT$1000 = NT$267,000
最終結果:30 集全上線
雲端少花 NT$182,603,而且真的有成品。
10.3 雲端 API 不是 cheating
工程師心結「用雲端 = 放棄」是不理性的:
- 時間值錢:時薪 NT$500,30 天 × 8 hr = NT$120,000。雲端 NT$27,000 跑 30 集,等於用 NT$27,000 換 NT$120,000
- 本地不是 0 成本:5060 Ti 350W × 24 hr × 30 天 ≈ NT$882 電費 + 硬體攤提
- 品質差距是 cliff 不是 gradient:本地 60 分 vs 雲端 95 分,觀眾不會給三星,他們直接滑掉。沒觀眾 = 沒變現 = 商業模型崩
10.4 雲端 API 短評
- Dreamina(字節跳動):每天免費 225 點 ≈ 11 個 10 秒 clip,中文 prompt 對齊度第一,付費約 NT$300/月起;適用個人試水溫
- Kling 1.6(快手):影片品質、motion、角色一致性頂尖,每 clip 約 NT$10;商用首選,API 完整公開
- Runway Gen-3:英文 cinematic 感最強,每 clip US$1;中文支援差,需另接中文配音
- Pika 2.0:UI 友善、月費制,解析度上限 1280×720;適合社群短影片
- Hailuo(MiniMax):中文 + 角色一致性內建不錯,API 還不太穩定(2026/6 狀態)
10.5 「本地仍然有意義」的三個場景
本地在以下場景仍有意義:(1) LoRA 訓練 / fine-tune(雲端不提供);(2) 批量後處理(RIFE 補幀 / RealESRGAN 超解析度 / GFPGAN 修臉);(3) prompt research / 風格實驗(零邊際成本)。
本地的正確定位是「實驗室 + 後製站」,不是「量產車間」。
10.6 給後來者的 10 條建議
10 條血淚建議,每條都能省你至少 3 天:
- 先量你的 VRAM,再選 pipeline:16GB vs 24GB 在 2026/6 是兩個物種。第二章那張「能跑 / 不能跑」清單先抄
- 本地 + 雲端混合,不要二選一:本地跑 LoRA + 後處理,雲端跑 i2v + 對嘴。月成本 NT$5,000-15,000,品質 90 分
- 量產前必須 30 秒 smoke test 給用戶簽:dispatcher 所有 type 各 1 shot concat 成 30 秒,用戶簽核才動量產。v14 血淚教訓
- 保留所有「過時」版本:v8 / v9.1 / v12B2 都被「過時」過,但仍是某些場景最佳。dispatcher 留 fallback
- technical selection 別信「state of the art」:LatentSync 在 3 agent 共識下被推,實測輸 2020 年 Wav2Lip。讀 limitations、讀 demo 場景、讀 issue 最近 3 個月
- custom node 4 個月沒更新就視同 deprecated:PuLID-Flux 是案例
- WSL2 vmIdleTimeout 必須設 -1:搭配 Mac SSH keeper(
nohup ssh sleep 3600),否則 28 秒 idle terminate - Edge TTS 免費版不能做產業級配音:上 Azure Premium(NT$0.05/字)或 ElevenLabs($5/月起)
- ComfyUI 量產必須有 health check + watchdog:每 N batch 自動
pkill + fuser -k + restart,否則 50 shot 後 GPU 卡死 - 先承認本地有天花板,再決定戰術:「30 集上 YouTube 商用」在 5060 Ti 16GB 是死路。承認能省你 30 天
10.7 30 天的最終結論
10 條:(1) 本地天花板真實存在;(2) 沒有單一銀彈,pipeline 必須 modular;(3) face_alignment 68 vs mediapipe 是地雷,MuseTalk 必走 dlib;(4) WSL vmIdleTimeout=-1 是 PC 長任務命脈;(5) Edge TTS 免費版 SSML 限縮,商業必上 Azure Premium / ElevenLabs;(6) 量產前必 smoke test 10 秒;(7) 品質基準是文章先決;(8) 雲端 API 不是 cheating,算對成本後常更便宜;(9) 失敗版本要保留當 fallback;(10) 手動驗證 > agent 報「完成」。
10.8 給看到這裡的讀者
如果只能從這篇拿走一件事:「本地全免費」是 2026 年 AI 影片生成圈最大的工程師自我欺騙。免費的是 GPU 算力,貴的是你的 30 天時間。
不管選哪條路,請至少做到「smoke test 先給用戶簽」這一件事。30 天結束。Drama Factory 專案封存。
附錄 A:30 天時間軸總表
| 日期 | 版本 | 結果 |
|---|---|---|
| 5/17 | 立項 | 看《五十岁》後本地複製 |
| 5/18 | Phase 0 LoRA | Flux LoRA 13 角色 30 hr 連跑 |
| 5/22 | v1.7 GGUF Wan22 14B | OOM 棄 |
| 5/24-25 | v8 Wav2Lip baseline | shot06 OK,多半垃圾 |
| 5/26 | LTX 中介 | i2v 鎖首幀差 |
| 5/27 | v4-v6 sniper | v6 GFPGAN 過關 |
| 5/27 | v8 MuseTalk mmcv | 棄走 Wav2Lip |
| 5/28 早 | v9.1 GFPGAN / v10 LatentSync | v9.1 較穩 |
| 5/28 晚 | v11 PuLID + v12 五版 | 全敗,寫 handoff |
| 5/29 | v13 MuseTalk face_alignment 68 patch | 跑通 256² |
| 5/31-6/1 | v14 量產 450 shot 21 hr | 17.7 min mp4,被批 7 項 |
| 6/1-6/3 | v15 修 7 缺陷 | smoke only |
| 6/3 | v16 動漫 460-shot | 翻車 |
| 6/3-6/4 | v17 10 秒 4 連版 | v4 仍 3 物理盲區 |
| 6/4 | 認輸封存 | 寫教科書 |
附錄 B:30 天踩過的 10 個坑(速查)
| # | 坑 | 修法 |
|---|---|---|
| 1 | WSL idle terminate(每 28 秒殺一切) | .wslconfig 設 vmIdleTimeout=-1 + Mac 端 keeper |
| 2 | Ollama 長輸出 >10K tokens 斷線 | 拆 patch 短段,gemma family CPU offload 不穩 |
| 3 | Qwen3 + format=json + thinking 衝突 | /no_think + 拿掉 format=json + regex parse |
| 4 | Python .format() 對 JSON 範例 prompt 炸 |
統一用 .replace() |
| 5 | ComfyUI-FluxTrainer 5 連坑 | numpy + transformers + cp950 + detach + caption_dropout |
| 6 | 5060 Ti Flux LoRA cache miss 197s/step | 預熱 cache,第二角色起 70s/step(3x 差距) |
| 7 | Windows cp950 console 殺 ComfyUI training | chcp 65001 + PYTHONIOENCODING=utf-8 寫進 .bat |
| 8 | HF BFL Flux 全 gated | 走 ComfyUI portable fp8 single-file 避開 |
| 9 | duix.avatar 3 container 偷 6.5 GB GPU | restart=no + stop 永久關 |
| 10 | Port 8188 portproxy 占用 8189 | 不動 portproxy,用 8188 + SSH tunnel 28189 |
附錄 C:軟體棧速查表
| 工具 | 用途 | 狀態 |
|---|---|---|
| ComfyUI v0.21.1 portable | GPU pipeline 主機 | ✅ |
| Wan22 5B ti2v fp16 | i2v 影片生成 | ✅ 但 81 幀上限 |
| Flux fp8 single-file | anchor 圖生成 | ✅ |
| MuseTalk V1.5 | 對嘴 256² | ✅ v13 patch |
| LatentSync 1.5 | 對嘴複雜 face-on only | ⚠️ |
| Wav2Lip 96² + GFPGAN v1.4 | 對嘴 backup | ✅ |
| LivePortrait KJ | 表情注入 | ❌ extreme 表情 fail |
| NoobAI XL Vpred 1.0 7.1 GB | 動漫 base | ✅ v16 |
| IPAdapter Plus SDXL ViT-H | 角色 reference | ✅ |
| Edge TTS(Xiaoxiao / Yunjian) | 旁白 | ⚠️ SSML 受限 |
| F5-TTS / GPT-SoVITS | voice clone | 收完待煉 |
| ReActor | face swap | ✅ |
| RIFE | 補幀 24→48 fps | ✅ |
| ffmpeg vf zoompan / scale / crop | 運鏡 | ✅ v15 加 |
| Ollama qwen3:14b | 劇本生成 | ✅ 主力 40 tps |
| Ollama gemma2:27b | 劇本 fallback | ⚠️ CPU offload 18 tps JSON 不穩 |
附錄 D:本地 vs 雲端速查決策
- 商用變現 + 時薪 > NT$500 → 雲端 Kling + ElevenLabs
- 商用變現 + 純練手 → Dreamina 免費每天 11 clip
- 學技術 / 寫文章 → 本地,這篇是你的指南
預算對照: - 純本地:NT$650/月電費 + 30 天時間(產出爛) - 純雲端:NT$27,000/30 集(Kling)/ NT$87,000(Runway) - 混合(推薦):NT$5,000-15,000/月(本地 LoRA + 雲端 i2v)
承認失敗比繼續迭代更勇敢。如果你正在重複我們的某一步,希望這篇文章能讓你提早一週認輸。
完。
本系列其他兩篇
這篇是 A 版(30 天血淚教科書,敘事風)。同系列另有兩個視角:
- 🅱 從 0 到放棄:一張 16GB 顯卡能不能拍中國短劇? — 反差派寫法。標題給你答案,內文 3 萬字解釋為什麼,給還在猶豫要不要砸硬體的人看。
- 🅲 2026 AI 短劇本地化完整指南:避開我踩過的 47 個坑 — 教學派寫法。47 個坑 + 完整 SOP + ComfyUI workflow JSON,給真要動手的工程師。
三篇用同一份 30 天血淚數據,但給不同類型讀者。建議閱讀順序:B(決定要不要做)→ A(理解失敗本質)→ C(真要做的執行指南)。