同一帧的效果对比
#对比
720P → 4K:同一帧的细节差多少
把鼠标移到任意一张图上,两张图会以光标所在位置为中心同步放大——左右对照的永远是画面里的同一处细节。 移开鼠标即复位。
#流水线
Easy4K 不把参数丢给用户自己拼命令,而是把转场检测(启用补帧与转场保护时)→ 拆帧 → 帧去重判决与平滑 → 超分 → 补帧 → 音频超分 → 合并(含 SDR→HDR、音频嵌入、元数据/封面)→ 帧数审查串成处理链路: 各阶段产物落在临时目录,可按已完成的产物续跑;去重回填与转场保护在合并前完成。
#主界面
选择视频后自动探测分辨率、帧率、时长与总帧数,勾选要执行的流程,选好超分与补帧模型, 输出分辨率与目标帧率实时算给你看。
#实时反馈
处理过程不是黑盒:阶段进度、最新产出帧、子进程的近期日志、CPU/GPU 占用都在同一个页面里滚动更新。
#对比
把鼠标移到任意一张图上,两张图会以光标所在位置为中心同步放大——左右对照的永远是画面里的同一处细节。 移开鼠标即复位。
#帧去重
动画与录屏里有大量画面是「定格」的:相邻帧几乎一模一样。Easy4K 默认用 SFDP 孪生网络(SiameseNET) 把它们挑出来,模型缺失或加载、预热失败时回退到四阶级联判决。勾选补帧时超分仍处理全部源帧, 只把保留帧交给补帧;未勾选补帧时才把重复帧移出输入目录,让超分只算保留帧。 合并前按索引表把结果展开回目标帧数,保持目标时间轴与音频对齐。
四阶级联判决(AI 模型缺失或预热失败时的回退路径;性能档在 dHash 后即判,完美档补上后两阶)
当前帧 vs 对比帧
├─ 第 1 阶 分块像素差 细块 / 粗块两级局部判定,检测到超阈值差异则保留
├─ 第 2 阶 dHash 汉明距离 整体结构是否一致
├─ 第 3 阶 QR 分解距离 归一化阈值 1.0 灰阶
└─ 第 4 阶 Farnebäck 稠密光流 平均残差与方差双阈值终判
判为重复 → 勾选补帧:帧留在原地(超分要算全部源帧),只把保留帧挑出来喂补帧
→ 未勾选补帧:把可安全移走的重复帧移出输入目录(超分只算保留帧)
→ 合并前按 dedup_map.json 展开回目标帧数#SFDP
SFDP 是 Easy4K 里负责「判重」的那一层:判决、时序平滑、回填与 GPU 阶段并行, 四件事都围绕同一套索引表;回填不完整时会停止任务,而不是继续产出一支错片。
判决 → 时序平滑 → 回填
│ │ │
│ │ └─ 按 dedup_map.json 展开回目标帧数(expandPos / keptIndices)
│ └─ 连续判为重复的标记不足 3 个则全部撤销,避免吃掉动画刻意的短暂顿帧
└─ 判决:SFDP 孪生网络(SiameseNET / ONNX)
(模型缺失或预热失败时回退四阶:像素差 → dHash → QR → Farnebäck 光流)
普通模式:整段判决与平滑完成后再进入超分 / 补帧
块流水:携带上一块末帧,一块前瞻后定稿,与 GPU 超分 / 补帧阶段重叠
分段涡轮:各段独立判重,跨段边界不比较;去重判决由全局锁串行执行
校验:判决表与磁盘实际帧数、产物数量核对,不匹配时回退串行重跑#可观测
去重不是黑盒。进行中页会把三张帧并排显示:左侧是最近被判为重复的「判决帧」, 中间是「对比帧」,右侧是当前正在判决的「筛选帧」——一眼看出这一帧是和谁比、比出了什么。
#性能 / 完美
两档用的是同一套孪生网络结构,差别在权重精度与判定阈值:性能档跑 FP16 模型、阈值 0.60; 完美档跑 FP32 模型、阈值 0.50。哪一档更适合,需要对代表性片段实际比对。
#AudioSR
基于 AudioSR 扩散模型重建高频,把音轨升采样到 48 kHz 直出;勾选「将原音频合并进新视频」时直接嵌入视频, 不勾选则单独输出一个 48 kHz 的 wav 文件。未开启音频超分时,音频由 FFmpeg 重采样到 96 kHz 后封装。
#界面
标准 / 高级一键切换:需要斟酌的进阶功能(帧去重、音频超分、转场优化、涡轮模式)集中在高级页,日常使用保持简洁。 界面当前固定简体中文(多语言词表与切换逻辑保留,入口暂时隐藏)。
#加速
官方 AudioSR 是 PyTorch + CUDA 的实现。这里把整条扩散链路导出成 ONNX,交给 ONNX Runtime 在显卡上跑: NVIDIA 优先尝试 CUDA,其它显卡尝试 DirectML,逐级不可用时回退 CPU。CUDA 运行库(cuBLAS / cuDNN / ORT CUDA EP) 与便携 Python 随包分发,用户无需自行配置 Python 环境;显卡驱动仍需满足所选后端要求。
读音频 → 重采样 48 kHz → 归一化 → 官方低通(滤掉伪高频,同时作为模型的低频条件)
→ log-mel → VAE 条件编码 → DDIM 50 步(eta = 1,CFG 3.5)→ VAE 解码 → vocoder 重建
→ mel / 波形低频段回填(回填源音频低频,减少低频内容偏移)→ 写 48 kHz WAV
加速要点
├─ 后端 NVIDIA:CUDA → DirectML → CPU;其它显卡:DirectML → CPU,逐级尝试
├─ 图优化 ORT_ENABLE_ALL 全图优化;DirectML 下关闭内存复用(enable_mem_pattern = false)
├─ 自检 启动先各跑一次最小推理,权重与图精度不匹配(fp16 图配 fp32 数据)立刻报错
├─ 分窗 5.12 秒窗、50% 重叠,长音频按窗推进;按单窗推理,不做并批
└─ 约束 fp16 权重包禁止在 CPU 上跑(CPU 的 fp16 算子又少又慢),宁可报错也不悄悄退化#音质
扩散模型补出来的 8 kHz 以上高频是「凭空生成」的,容易过量成一片嘶声,安静段还会被填满宽带底噪。 现在的做法是:先按官方实现做低通滤波(0.985 分位求截止、8 阶零相位、硬降采样再升回 48 kHz), 再把生成的高频整形成「由源频谱自然外推」的包络——限制过量生成的高频,同时参考源频谱设置包络下限;实际听感仍需试听。
#SceneGuard
补帧会在相邻两帧之间「插」出一帧。碰上镜头硬切,插出来的就是两个镜头各混一半的鬼影帧。 开启转场优化后先用 PySceneDetect 扫出剪切点,合并前把切点处的插值帧换回上一镜头的末帧—— 帧数、帧率、时长都不变,只是不再有跨镜头混合。
#封装
成片是从帧序列重建的,原文件的标题、注释、封面不会自己跟过来。Easy4K 只在检测到源文件确实有元数据/封面时 才允许勾选;写回时用 -map_metadata + -c copy 只重封装不重编码, 封面按容器写成 mkv 附件或 mp4 attached_pic。
#AI 判决
帧去重的默认判决器是一个孪生网络(Siamese Net,导出为 ONNX):左右两支共享权重, 把相邻两帧在同一坐标上的两张 128×128 灰度块一起送进去,输出 0~1 的分数,分数越高越倾向判为相似/重复。 整帧按 128×128 铺满分块、逐块推理后取「最低分」作为这一对帧的结论:只要有一块明显不同,两帧就不算重复。 该取法偏向保守,但仍需注意:模型输出只是相似度估计,不保证两帧像素完全相同。
相邻两帧 A / B(同一坐标分块,覆盖整帧)
↓ 每对 128×128 灰度块 → (N, 1, 128, 128),取值 [0,1]
SiameseNET(左右分支权重共享)
↓ score ∈ [0,1]:越高越倾向相似 / 重复
取所有块的最低分 → 与阈值比较(性能档 0.60 / 完美档 0.50)
↓
判为重复 → 按去重策略处理;合并前按索引表展开回目标帧数
为什么必须分块:1080p 里占画面 0.05% 的元素在动,全局平均差几乎察觉不到,
缩成小图更是彻底抹平;只有按块逐一看,才抓得住这种局部运动。#Real-ESRGAN
模型列表来自 realesrgan-ncnn-vulkan 的 models 目录,按当前倍率过滤: x2 / x3 对应 realesr-animevideov3-x2|-x3,x4 还提供 realesrgan-x4plus 与其动漫版。
realesr-animevideov3-x{倍率}, 避免出现"选了模型却不可用"。 -u UHD 模式),与安全帧率可同时启用; 自动降级重试时也会一并打开省显存模式,避免只降线程仍然爆显存。 #补帧后端
NCNN 路径使用 rife-ncnn-vulkan,依赖可用的 Vulkan 驱动,本身不依赖 CUDA; PyTorch 补帧使用随包的便携环境。不同模型的硬件要求不同,不能仅凭显卡品牌判断是否可用。
rife-v4 及以后支持 -n 目标帧数,命中 v2 / v3 老模型时会自动锁定倍率为 x2。 VK_ERROR_DEVICE_LOST 或显存溢出:开启安全帧率则立即停止保护显卡, 未开启则自动降级为单线程 -j 1:1:1 并同时打开 -u 省显存模式重试一次。 #性能
超分与补帧各有一组「解码 / 编码」线程滑块(1~32);调整编码线程时,解码线程按约一半自动跟随(至少 1)。 NCNN 工具最终收到的是 -j 解码:编码:编码 三段参数,超过 1:8:8 会提示设备丢失风险。 CPU 处理模式下相关 GPU 开关会一并关闭。
#Real-ESRGAN
各超分引擎使用各自的模型目录,Real-ESRGAN 的模型位于 Tools/realesrgan-ncnn/models。 启动与切换倍率时按已部署的模型文件过滤,下拉框只显示当前引擎与倍率可用的组合。
#选型
720p 到 2160p 正好是 ×3。模型与倍率是绑定的,倍率选错下拉框里就没有对应模型,所以这里直接给结论:
#rife-ncnn-vulkan
rife-ncnn-vulkan 走纯 Vulkan 推理,本身不需要 CUDA。模型目录下带 flownet.param 的子目录都会被识别。
#补帧
补帧只需要一个输入帧目录和一个输出目录。NCNN 路径把倍率写成 -n 输出总帧数; 开了帧去重时按「保留帧 × 倍率」传,合并前再展开到目标帧数,保持目标时间轴与音频对齐。
#性能
外部工具会把 CPU 与显卡吃满,所以"不卡"靠的不是少用资源,而是把资源分配和界面更新彻底分开: 重量级工作全在子进程与后台线程里,UI 线程只负责渲染和绑定。
#自动化
能自动判断的都让它自己判断:该先验证的先验证,该跳过的跳过,该退让的退让,跑完自己把产物交出来。 你只需要决定"要做什么",不用盯着"现在到哪一步、要不要重来"。
#流程
选择视频
├─ 自动探测分辨率 / 帧率 / 时长 / 总帧数
├─ 临时目录指纹校验 ── 不符 → 引导更换或清理
├─ 处理前测试:1 秒测试视频 × 当前勾选流程
│ └─ 没跑通 → 直接取消正式处理,不浪费几个小时
└─ 正式处理:转场检测(启用时)→ 拆帧 → 去重判决与平滑
→ 超分 → 补帧 → 音频超分
→ 合并(含 HDR / 音频 / 元数据封面)→ 帧数审查
├─ 帧去重:勾选补帧时超分算全部源帧、只省补帧的计算量
├─ 每阶段:帧数够就跳过,残留就清理后重跑
├─ 出错时:按实际条件降级 / 回退 / 重试,无退路则停止
└─ 完成后:审查帧数 → 自动命名输出 + 生成 HTML 报告#单文件
不走完整流水线(不拆帧 / 不补帧 / 不合并):选一个文件,按类型直接处理并给出结果,适合封面、BGM 与单支视频的快速处理。
#分层
没有引入依赖注入容器,启动时在 App.OnLaunched 里手工装配服务链并交给 MainViewModel,界面通过静态入口 App.Services 取用状态中枢。
#Views
XAML 窗口与页面负责交互:主界面收集参数,进行中页展示进度、预览与日志,欢迎向导负责首次运行配置。
#ViewModels
MainViewModel 维护勾选联动、模型过滤、输出预览与启动前校验,并驱动 ProcessingOrchestrator 执行流水线。
#Services
进程执行、命令拼装、显卡与环境探测、工具路径解析、配置持久化、报告生成都被拆成可单独测试的小服务。
#分层
Easy4K.LuminolCore 是独立的类库(Easy4K.LuminolCore.dll),包含帧去重判决与稠密光流, 不依赖 WinUI 界面类型;它面向 Windows,帧去重实现会用到 Windows 图像接口。LuminolEngine 则是应用内的执行引擎层, 负责把 UI 收集来的参数变成命令、把命令变成进程、再把进程输出变成进度与报告。
#引擎
引擎层承担「执行一次任务」所需的主要能力;各模块按职责拆分,可单独替换或单独测试, 但本地化服务等服务仍会操作 UI 可视树。
#进度采集
FFmpeg 与 NVEncC 会往标准错误输出覆盖式进度,所以进程读取按 \r 与 \n 都切分,逐行实时回调;AI 工具没有进度输出,就轮询输出目录的帧数再叠加当前帧内的 tile 百分比。
// 按 \r 与 \n 都切分,否则 FFmpeg 的覆盖式进度会被缓冲到进程结束
if (c == '\r' || c == '\n') { onLine(sb.ToString()); sb.Clear(); }
// 拆帧 / 合并:解析行内帧号
frame=\s*(\d+) → 已处理 1234 / 4823
// HDR:优先解析百分比,帧号比例仅在分母合理时采用
(\d+(?:\.\d+)?)\s*% → 已处理 45%
// 超分 / 补帧:轮询输出目录帧数 + stderr 的 tile 百分比
进度 = min(已完成帧数 + 当前帧内百分比 / 100, 总帧数)#容错回退
能回退的环节按实际条件逐级尝试:能用 CPU 的转 CPU,能换编码器的换编码器, 模型不被支持就换模型;没有可用退路时停止任务并把错误交给日志与失败报告。
拆帧 / 合并 启用旧版重试且旧版已部署 → 新版 FFmpeg 失败后尝试旧版
拆帧 / 合并 旧版不可用或仍失败 → CPU 处理档(关闭相关硬件处理)
音轨/封面/元数据/AudioSR 转 48k → 按同样条件尝试旧版,再转 CPU 档
HDR NVEncC 转换失败 → 条件允许时重试旧版,仍失败则终止,不自动改走 AI
合并 硬件编码器失败 → 回退 libx265 -crf 18
超分 捆绑版无 CPU 后端 → 自动升级为 GPU 处理
补帧 "MemoryData not exists" → 回退 rife-v4.6
补帧 v2 / v3 老模型 → 强制 x2 并锁定倍率下拉框
GPU 致命 设备丢失 / 显存溢出 → 安全帧率:停止;否则:-j 1:1:1 重试
失败 任何阶段 → 停止任务并生成失败报告(不静默跳过)#断点续传
每个阶段开始时先数输出目录里的 PNG:够数就整段跳过;有残留但不够数,说明上次是被中断的, 先清理再从该阶段重跑,避免半截帧序列被当成有效输入。
existing = 输出目录 PNG 数量
existing >= 目标帧数 → 当前阶段已完成,直接跳过
0 < existing < 目标帧数 → 清理残留,从本阶段重新开始
existing == 0 → 正常执行#缓存校验
临时目录里会写一份 cache.json,记录来源视频路径、文件大小与最后修改时间。 换了视频却没清理临时目录时,启动前会提示重新选择目录或清理缓存,避免旧帧被误当成新素材。
{
"inputVideo": "D:/video/彩条测试视频.mp4",
"videoSize": 1089894,
"videoModifiedTicks": 638600000000000000,
"createdAt": "2026-09-13 13:20:41"
}
指纹不一致 → 弹窗:重新选择临时目录 / 清理缓存 / 取消#--selftest
带参数启动即可跳过界面操作跑一遍链路,结束后把自测日志写入报告文件并退出, 适合放进批处理或 CI 做回归。
Easy4K.exe --selftest <输入视频> <报告文件> [阶段掩码]
阶段掩码(位运算):
1 拆帧 2 超分 4 补帧
8 合并 16 音频 15 拆帧 + 超分 + 补帧 + 合并(默认,不含音频;此入口关闭 HDR)
其它入口:
Easy4K.exe --selftest-clean <临时目录> <报告文件> # 清理链路自测
Easy4K.exe --dedup-test # 只跑帧去重判决#--autotest-all
遍历模型目录里的超分与补帧模型逐个真跑,界面全程可见可停;失败的用例会把临时目录单独保留, 方便对着中间产物复查。
Easy4K.exe --autotest-all # 代表性模型 × 各倍率
Easy4K.exe --autotest-all full # 全模型 × 2~5 倍率全矩阵
Easy4K.exe --autotest-api full # API 模式逐例子进程跑全矩阵
结果写入:Res\autotest\AutoTestSummary.txt
API 模式:Res\autotest_api\ + 桌面 Easy4K流水线全组合自动测试_*.txt
失败残留:Res\autotest\fail\#技术栈
应用、运行时依赖、外部工具与模型组成安装包,并非所有内容都塞在单个 exe 中。随包环境无需手动配置,显卡驱动仍需满足所选后端要求。
#上手
没有快捷键要记,也没有命令行参数要背:选好输入与目录,勾选要跑的阶段,点「开始处理」。
1 选择输入 视频文件;或「导入」已有 PNG 帧文件夹直接跳过拆帧
2 勾选流程与模型 拆帧 / 超分 / 补帧 / 合并 / SDR→HDR
保留内嵌字幕 / 嵌入元数据 / 嵌入封面
补帧可直接填「目标帧率」(0 = 按倍率)
3 开始处理 主页实时显示最终文件名;进度、预览与日志在「进行中」页
处理中可以停止;「清理临时文件」回收中间产物#目录
程序把只读资源(exe、Assets、Tools)和可写数据分开放:商店版的安装目录在 WindowsApps 下且只读,配置、报告、临时与输出统一落到 %LOCALAPPDATA%\Easy4K;便携版在 exe 目录可写时直接使用 exe 同级目录。
#环境
Windows 10 1809 及以上 / Windows 11;超分与 NCNN 补帧需要可用的 Vulkan 驱动, 其它功能按所选后端要求 DirectML / CUDA 或 CPU。 SDR→HDR 在支持 TrueHDR 且 NVEncC 可用时交给 NGX TrueHDR;否则尝试 AI 模型 HDRTVNet++ 按画面重建高光(DirectML,输出 HDR10 的 MKV)。两条路都不可用时该选项才不可用。
建议 8GB 以上内存;4K 超分建议 6GB 以上显存。出现显存不足或设备丢失时, 开启安全帧率会停止任务,否则降为单线程并打开省显存模式重试。
超分走 NCNN / Vulkan;补帧可选 NCNN / Vulkan 或 PyTorch 路径,硬件要求随模型而异; 帧去重优先 DirectML(不可用时回退 CPU),音频超分按 CUDA → DirectML → CPU 逐级尝试(FP16 仅 GPU)。 转场检测依赖随包 Python 与 PySceneDetect,属于可选功能;临时目录建议放在固态盘,同卷 NTFS 有利于使用硬链接。