RTX 5060 Ti 跑 FlashVSR:我把 480P 视频“拉”到 1728×960,顺便踩完了这些坑
写在前面
“把一段 480P 视频变清楚”听起来像把图片放大两倍,但真正运行一次才知道:视频超分更像是请一位修图师,连续修理上百张照片,还要保证相邻照片里的人脸、文字和光线不会突然跳变。本文记录一次完整的 FlashVSR_plus 实战:从 RTX 50 系兼容性判断、便携 Miniconda 安装,到模型下载、源码 bug、FFmpeg 音频合并,再到可复用的 Windows、Ubuntu 和 macOS 脚本。
本文使用的社区版 FlashVSR_plus 并非官方仓库,命令和参数会随版本变化。文中的路径均已改为公开示例路径,不包含原始机器信息;原视频、模型和终端日志没有上传到博客。
1. 最终结果先看:成功,但不是“魔法变成 1080P”
源视频是 864×480、24 FPS、约 5.17 秒。使用 2× 放大后,最终得到 1728×960、H.264、24 FPS 的视频,再把源文件中的 AAC 音频安全合并进去。文件可以正常播放,声音和画面时长一致。
图 1:从解码、分块推理到音频合并的完整流程
这里有一个很容易被标题党掩盖的事实:2× 不等于严格 1920×1080。864×480 的比例不是 16:9,简单乘以二就是 1728×960。如果硬拉成 1920×1080,就会改变画面比例或引入裁切。因此这次的目标应该说是“接近 1080P 的清晰度档位”,而不是承诺输出尺寸一定为 1920×1080。
图 2:保留源比例时,2× 输出是 1728×960
2. 为什么先研究 RTX 50 系兼容性?
RTX 5060 Ti 属于 Blackwell 世代。很多 AI 项目在新显卡上市时,并不是模型本身坏了,而是“翻译链”中有一层还不认识新硬件:驱动负责看见显卡,CUDA runtime 负责解释 GPU 指令,PyTorch wheel 再把这些能力交给上层应用。任何一层出错,上层都可能只告诉你“没有设备”。
图 3:把驱动、CUDA、PyTorch 和 FlashVSR 想成四层翻译链
我的实际验证结果是:驱动报告 CUDA 13.1,环境里的 PyTorch 为 2.8.0+cu128,内置 CUDA runtime 为 12.8,torch.cuda.is_available() 返回 True,设备名称正确显示为 RTX 5060 Ti。这里最重要的经验是:不要只看驱动面板上的 CUDA 版本,也不要把某一个版本号写成永恒真理,直接在目标环境中验证。
python -c "import torch; print(torch.__version__); print(torch.version.cuda); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0)); print(torch.cuda.get_device_capability(0))"
图 4:脱敏后的显卡检测结果
图 5:脱敏后的 PyTorch 验证结果
官方 FlashVSR 使用的 Block-Sparse-Attention 对 CUDA 编译环境更敏感;社区版 FlashVSR_plus 提供了 SageAttention、DiT 分块和 VAE 分块选项,更适合先在消费级 Windows 机器上验证。分块就像把一张大海报裁成小方块逐片处理,显存峰值会下降,但边界需要 overlap 进行柔和拼接。
3. 安装路线:为什么 PyTorch 要单独装?
我选择便携 Miniconda,并建立 Python 3.11 环境。安装顺序很重要:
- 克隆 FlashVSR_plus 到一个不含隐私信息的目录,例如
D:\AI\FlashVSR。 - 创建
flashvsr环境。 - 从 PyTorch CUDA wheel 源单独安装 torch 和 torchvision。
- 再从普通 PyPI 安装 gradio、einops、safetensors、imageio-ffmpeg 等依赖。
- 将模型下载到项目自己的
models/FlashVSR缓存目录。
曾经踩过的坑是把整个 requirements.txt 都配上 PyTorch 专用 index,结果 gradio 根本找不到。原因很简单:专用仓库像“只卖显卡的商店”,不负责普通 Python 包。
# PyTorch 使用官方 CUDA wheel index;版本请以官方选择器为准
python -m pip install torch==2.8.0 torchvision==0.23.0 `
--index-url https://download.pytorch.org/whl/cu128
# 普通依赖回到 PyPI
python -m pip install gradio einops safetensors tqdm pillow `
imageio imageio-ffmpeg ffmpeg-python huggingface_hub hf-xet triton-windows
模型首次运行会下载 JunhaoZhuang/FlashVSR。如果模型已经缓存,后续可以断网运行;镜像地址应作为可选配置,不要把 token 写进脚本或文章。
4. 问题表现一:明明有显卡,却说没有设备
第一次运行直接失败:
RuntimeError: No devices found to run FlashVSR!
图 6:第一层错误并不等于显卡不兼容
根因在源码:run.py 导入时就缓存了 devices = get_device_list(),而 get_device_list() 为了“友好”地吞掉 CUDA 初始化异常,使用了宽泛的 except。一旦初始化时机不对,后续即使显式传入 -d cuda:0,缓存也可能仍为空。
排查顺序应该是:
- 用同一个 Python 解释器单独验证 torch CUDA。
- 确认 ComfyUI 等程序已经关闭,避免显存被占满。
- 显式传入
-d cuda:0。 - 如果仍失败,再检查驱动、PyTorch wheel 和项目依赖,而不是马上重装整个系统。
5. 问题表现二:temp_name 未初始化
模型下载成功后,第二次失败更具体:
UnboundLocalError: cannot access local variable 'temp_name'
图 7:tiled tiny 模式的变量初始化 bug
代码只在 tiny-long 分支里定义临时视频文件名,但 tiny 分支也把这个变量传给了 pipeline。解决办法不是改参数,而是给每一个 tile 都先分配名字:
temp_name = os.path.join(temp, f"tile_{i+1:05d}.mp4")
if mode == "tiny-long":
temp_name = os.path.join(local_temp, f"{i+1:05d}.mp4")
这是一次典型的“用户配置错误”和“项目源码 bug”边界案例。看到 traceback 后,先定位变量生命周期,不要把所有问题都归结为显卡性能。
6. 问题表现三:FFmpeg 明明安装了,程序还是找不到
conda 版本 FFmpeg 曾出现 Windows DLL 启动异常。后来改用 imageio-ffmpeg 自带的静态程序,并把它所在的 binaries 目录加入 PATH。原因是 FlashVSR 的检查方式是 shutil.which('ffmpeg'),它只认 PATH,不会自动读取 Python 包内部路径。
$env:PATH="$env:CONDA_PREFIX\Lib\site-packages\imageio_ffmpeg\binaries;$env:PATH"
ffmpeg -version
图 8:视频流复制、音频重新编码并合并
FlashVSR 输出默认没有音频,因此最后用 FFmpeg 做 mux:
ffmpeg -y -i superres.mp4 -i input.mp4 `
-map 0:v:0 -map 1:a:0? -c:v copy -c:a aac -shortest final.mp4
-map 1:a:0? 中的问号很有用:如果输入没有音频,命令不会因为“找不到可选音频流”而失败。原始文件只读,输出写入新文件。
7. 真正的内存瓶颈:不是显存,而是 CPU RAM
最容易误判的一次失败是:显卡显存还有余量,但程序在 CPU 上申请约 1.24 GB 的画布时失败。
RuntimeError: DefaultCPUAllocator: not enough memory
tiled_dit 只降低了 GPU 侧的峰值;tiny 模式仍会为所有帧创建完整的 final_output_canvas 和 weight_sum_canvas。这就像把大海报分块送进打印机,却仍然要求桌面先铺开两张完整海报。
解决策略:
- 优先使用
tiny-long,让 tile 结果落盘后再拼接。 - 减小 tile-size,必要时增大分段次数。
- 运行前检查系统可用内存,而不是只看 GPU-Z。
- 不要无限自动重试同一个参数;失败重试会继续消耗磁盘和时间。
图 9:成功完成 8 个 tile 的脱敏日志
8. 最终输出与可复用脚本
最终文件的关键属性如下:
图 10:最终 H.264 + AAC 输出
| 项目 | 结果 |
|---|---|
| 输入 | 864×480,24 FPS |
| 输出 | 1728×960,24 FPS |
| 视频 | H.264 |
| 音频 | AAC |
| 时长 | 约 5.17 秒 |
| 推理 | RTX 5060 Ti,2×,tiled |
8.1 Windows 11
下载 flashvsr-win11.ps1,放在 FlashVSR 项目目录。脚本会检查输入、Python、CUDA、FFmpeg 和可用内存;默认使用 tiny-long,避免本次遇到的 CPU canvas 分配错误。
Set-ExecutionPolicy -Scope Process Bypass
.\flashvsr-win11.ps1 `
-InputPath "D:\video\input.mp4" `
-OutputDir "D:\video\output" `
-Scale 2
如果模型已缓存,脚本不需要外部服务。需要镜像时显式加 -UseHfMirror。
8.2 Ubuntu 26.04
下载 flashvsr-ubuntu26.sh,设置 FLASHVSR_DIR 和 FLASHVSR_PYTHON 后运行:
chmod +x flashvsr-ubuntu26.sh
FLASHVSR_DIR="$HOME/AI/FlashVSR" \
FLASHVSR_PYTHON="$HOME/AI/FlashVSR/.venv/bin/python" \
./flashvsr-ubuntu26.sh ./input.mp4 ./output 2
脚本会要求 nvidia-smi、PyTorch CUDA 和 FFmpeg 都可用。Ubuntu 的驱动和 CUDA 安装方式可能不同,建议使用发行版与 NVIDIA 官方文档的当前版本。
8.3 macOS 26
下载 flashvsr-macos26.sh。它会做硬件检查,然后明确停止。原因不是脚本偷懒,而是本文验证的是 CUDA/SageAttention 路径,不能把 Apple GPU 的 MPS 兼容性伪装成已验证功能。若未来项目提供经过测试的 MPS 后端,应单独测试,不要照搬 CUDA 参数。
8.4 人工执行和 Agent 执行
人工执行适合想掌握每一步的人:先验证硬件,再安装环境,再运行短视频,最后 mux 音频。Agent 自动配置适合重复部署,但必须遵守“只读探测—展示计划—获得批准—执行—验证”的顺序。博客同时提供 flashvsr-agent-template.md,其中明确禁止删除原视频、上传数据和输出隐私信息。
9. Q&A
Q1:为什么不直接输出 1920×1080?
因为源视频比例不是 16:9。可以在后处理阶段选择裁切或加黑边,但那已经是构图决策,不应悄悄由超分脚本替你决定。
Q2:RTX 50 系一定要某个固定 CUDA 版本吗?
不要这样下结论。驱动、runtime 和 PyTorch wheel 是不同层。使用官方安装选择器,并在目标环境运行 CUDA 探针最可靠。
Q3:tiled 能解决所有内存问题吗?
不能。它主要降低 GPU 峰值;如果代码还在 CPU 创建完整输出画布,系统内存仍可能成为瓶颈。
Q4:为什么输出没有声音?
视频超分模型通常只处理视频帧,音频需要用 FFmpeg 从原文件映射到新文件。使用 -c:v copy 可以避免再次压缩视频。
Q5:社区版和官方版如何选择?
先看目标平台和显卡。官方版更接近论文与上游实现;社区版通常提供消费级 GPU 更容易运行的参数。无论选哪一个,都应锁定版本、保存日志,并先用短片测试。
10. 参考资料
- FlashVSR 官方项目
- FlashVSR 项目主页
- PyTorch 本地安装选择器
- NVIDIA CUDA GPU 列表
- CUDA Blackwell 兼容性指南
- ImageIO FFmpeg 文档
- Hugging Face 下载文档
最后的经验:超分项目最难的部分,常常不是按下“运行”,而是知道每一层出了什么问题。把环境探针、资源预检、可回退模式和音频 mux 都写进脚本,下一次就不必从一堆 traceback 里猜答案了。