背景痛点:文生视频的三座大山
过去一年,我帮三家初创团队做过“一句话生成15秒短视频”的 PoC,几乎每次都卡在同一个地方:模型体积大、推理延迟高、多卡并行困难。
- Hunyuan-Video 全精度权重 23 GB,一张 A100 40 GB 刚塞下,留给 batch 的余地几乎为零。
- 512×512、48 帧的默认配置,RTX 4090 单卡跑完一条 prompt 要 210 s,FPS≈0.23,线上业务根本扛不住。
- 想用 torchrun 做多卡流水线?Diffusers 的
accelerate接口对 Hunyuan-Video 的 Causal 3D 分支支持不完整,常常卡死在前向传播。
一句话:传统“pip install diffusers,然后写个 for 循环”的玩法,在文生视频场景下直接破产。
技术选型:为什么最后选了 ComfyUI
我花了两天时间把主流方案跑了一遍,结论如下表:
| 框架 | 原生支持 Hunyuan-Video | 显存优化 | 节点可视化 | 多卡并行 | 备注 |
|---|---|---|---|---|---|
| Diffusers | (需魔改) | 常规 offload | 官方例程不完整 | 社区 PR 还在 review | |
| SD.Next | --medvram | 单卡 | 代码仓库 20 GB,CI 经常红 | ||
| ComfyUI | (官方插件) | 分段 offload | 多进程通信 | 节点可导出 JSON,一键复现 |
ComfyUI 的节点化工作流把“模型加载→CLIP 编码→Latent 扩散→解码→帧插值”拆成 5 个独立单元,每个单元都能单独开进程、占一张卡,天然符合“流水线并行”的直觉。再加上社区已经有ComfyUI-HunyuanVideoWrapper,省掉自己写 CUDA kernel 的麻烦,于是直接 All in。
核心实现:15 分钟搭出第一条工作流
1. 环境配置
# 建议用 22.04,CUDA 12. 1 与驱动 535 组合最稳 conda create -n hunyuan python=3.10 -y conda activate hunyuan pip install torch==2.3.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 git clone https://github.com/comfyanonymous/ComfyUI.git cd ComfyUI git clone https://github.com/ExponentialML/ComfyUI-HunyuanVideoWrapper custom_nodes/ pip install -r requirements.txt2. 模型下载与放置
# 脚本自动做分片校验,断点续传 huggingface-cli download tencent/HunyuanVideo --local-dir models/diffusers/hunyuan-video # 把大文件软链到 ComfyUI/models ln -s $(pwd)/models/diffusers/hunyuan-video ComfyUI/models/hunyuan_video3. 工作流 JSON(可直接导入)
{ "1": { "inputs": { "text": "一只柴犬在樱花树下打滚,高清,4K", "clip": ["2", 0] }, "class_type": "CLIPTextEncode" }, "2": { "inputs": { "ckpt_name": "hunyuan_video.safetensors" }, "class_type": "HunyuanVideoLoader" }, "3": { "inputs": { "width": 512, "height": 512, "frames": 48, "batch_size": 1 }, "class_type": "EmptyLatentVideo" }, "4": { "inputs": { "seed": 12345, "steps": 25, "cfg": 7.5, "sampler_name": "euler_ancestral", "scheduler": "normal", "denoise": 1.0, "model": ["2", 0], "positive": ["1", 0], "negative": ["1", 1], "latent_video": ["3", 0] }, "class_type": "HunyuanVideoSampler" }, "5": { "inputs": { "latent_video": ["4", 0], "vae": ["2", 1] }, "class_type": "HunyuanVideoDecode" }, "6": { "inputs": { "frame_rate": 16, "loop_count": 0, "filename_prefix": "demo", "format": "mp4", "pix_fmt": "yuv420p", "crf": 17, "save_metadata": true, "video": ["5", 0] }, "class_type": "SaveVideo" } }导入后大概长这样:
4. 关键 Python 代码(脱离 UI 也能跑)
# api_runner.py import json import requests import torch from pathlib import Path PROMPT = "一只柴犬在樱花树下打滚,高清,4K" WORKFLOW_JSON = Path("workflow_api.json").read_text() def queue_prompt(prompt): p = {"prompt": json.loads(WORKFLOW_JSON)} # 动态替换 prompt p["prompt"]["1"]["inputs"]["text"] = prompt resp = requests.post("http://127.0.0.1:8188/prompt", json=p) return resp.json() if __name__ == "__main__": torch.multiprocessing.set_start_method("spawn", force=True) print("提交任务:", queue_prompt(PROMPT))5. 批量生成脚本
# batch_gen.py import api_runner from concurrent.futures import ThreadPoolExecutor prompts = [f"场景{i}:一只猫在{i}色背景下跳舞" for i in ["红", "蓝", "绿"]] with ThreadPoolExecutor(max_workers=3) as pool: pool.map(api_runner.queue_prompt, prompts)跑完 3 条 48 帧视频,总耗时 312 s,平均每条 104 s,比串行提升 2.8 倍。
性能优化:让 4090 也能跑 64 帧
1. 显存三板斧
- 启动参数加
--medvram:把 VAE 和 Text Encoder 常驻显存,UNet 按需交换,显存占用从 23 GB 降到 15 GB。 - 节点里把
frames拆成两段,先做 0–31,再做 16–47,两段重叠 8 帧做滑窗,后期 FFmpeg 拼接,显存峰值再降 20%。 - 开半精度:
torch_dtype=torch.float16,画质损失 0.02 dB,省 7 GB。
2. 多实例并行(单机 4 卡)
ComfyUI 原生不支持 torchrun,但可以用comfy_api.py起 4 个端口:
for i in {0..3}; do CUDA_VISIBLE_DEVICES=$i python main.py --port 8188$i --listen & done用 ZeroMQ 把任务队列做成 PUSH-PULL,主进程按显存空闲度分发 prompt,实测 4×4090 可同时跑 4 条 48 帧视频,整机 FPS 从 0.23 提到 0.89,接近线性加速。
3. 性能测试数据
| 配置 | 帧数 | 总时间(s) | FPS | 显存峰值(GB) |
|---|---|---|---|---|
| 单卡 4090 全精度 | 48 | 210 | 0.23 | 23.1 |
| 单卡 4090 + --medvram + fp16 | 48 | 165 | 0.29 | 15.4 |
| 4 卡 4090 并行 | 192 | 215 | 0.89 | 15.2×4 |
避坑指南:踩过的坑都写在这里
- CUDA 12.2 与 535 驱动组合会报
cublasLt找不到,解决:降级到 12.1 或升级驱动到 537+。 - 提示词太长 (>77 token) 会在 32 帧后崩坏,把长句拆成 3 行,再用
cross_attention_control节点做分段注入,画面连贯性提升肉眼可见。 - Windows 下路径含中文导致
ffmpeg写入失败,统一用英文下划+短路径,或者把temp目录改到D:/tmp。 - 生成 64 帧以上视频时,VAE 解码会 OOM,把
frame_batch_size调成 8,解码分段写磁盘,最后ffmpeg concat拼回。
长视频内存占用开放讨论
目前滑窗+分段拼可以勉强做 5 min 720p,但 Latent 中间状态仍然要占 30 GB+ 内存。如果把 KV-cache 卸载到 DDR5,再通过 PCIe 5.0 按需回拷,延迟能扛住吗?或者干脆把 UNet 拆成 tensor parallelism,把单层放到多卡?欢迎有试过的小伙伴留言交流。