Jasna 教程:本地 GPU 马赛克视频修复是怎么做到的(附实测数据)
【免费下载链接】jasnaVideo restoration tool项目地址: https://gitcode.com/GitHub_Trending/ja/jasna
一段 3 分 22 秒的 1080p 视频,Jasna 在 RTX 5090 上 39 秒修复完,1080p 端到端约 156 fps,10 GB 显存即可跑满,8 GB 显卡降一档参数也能跑通 720p。Jasna 是一个本地 GPU 视频马赛克修复工具:它只找出画面里的马赛克区域并重建这部分像素,其余画面原样保留。本文基于仓库源码与 官方基准报告 里的实测数据,讲清楚这条流水线内部如何运转、为什么这么设计。
🧭 架构总览:四个线程串起整条 GPU 流水线
修复主路径由四个并发循环组成,用有界队列衔接,代码集中在 jasna/pipeline_threads.py。先看这张地图,后面逐站走:
| 组件 | 职责 | 输入 | 输出 | 所在文件 |
|---|---|---|---|---|
decode_detect_loop | NVDEC/AMF 硬件解码 + 逐帧检测 | 输入视频文件 | 检测到的 bbox + mask 批次 | jasna/pipeline_threads.py、jasna/media/video_decoder.py |
expand_bbox/CropBuffer | 把检测框长到 256×256 并做预处理 | bbox + 原始帧 | 256×256 裁剪序列 + 坐标元数据 | jasna/crop_buffer.py |
ClipTracker+ BasicVSR++ | 跨帧聚合成 clip,对 clip 做时序重建 | 裁剪序列 | 256×256 修复张量 + 回填坐标 | jasna/tracking/clip_tracker.py、jasna/restorer/restoration_pipeline.py |
blend_encode_loop | 按 mask 把修复结果混回原帧并硬件编码 | 原帧 + 修复张量 + mask | 输出视频(音频流拷贝) | jasna/blend_buffer.py、jasna/media/video_encoder.py |
官方 README 对这条链路只有一句话,但它就是全项目最重要的不变量:"Finds mosaics in a video and restores them. The rest of the picture is not touched."(README.md)也就是说,后面所有裁剪、重叠、混合的工程手段,都是在守住"只改马赛克、不碰背景"这条线。
主线走读:一段视频从解码到回填的完整旅程
以下按数据流动方向走五站。每一站都回答三件事:输入输出是什么、内部关键逻辑是什么、为什么这么做。
站点一:硬件解码与逐帧检测——帧和检测结果都留在显存
这一步接收输入视频文件,产出带置信度的 bbox 与逐像素 mask,解码代码在 jasna/media/video_decoder.py,检测调度在 jasna/mosaic/detection_registry.py。VideoReader默认走vali后端(NVDEC 直读),帧直接以 GPU 张量形式产出,不再回拷到内存。检测默认模型是rfdetr-v6(576 分辨率、置信度阈值 0.35):它和只给框的 YOLO 不同,同时输出逐像素 mask,jasna/mosaic/detections.py 里的Detections同时携带boxes_xyxy(裁剪定位用)和masks(回填混合用)。在 NVIDIA 上模型首次会被编译成 TensorRT 引擎(compile_rfdetr_engine,workspace_gb=20),AMD 则回退 torch 推理。
为什么值得为"首次慢"买单?因为引擎编译是一次性的:编译产物缓存在model_weights目录,可跨 Jasna 版本复用;被否掉的替代方案是每次现跑 torch 推理,那意味着每个任务都付一遍推理开销。常见误解"首任务慢是因为模型在跑推理"可以这样纠正——慢在引擎编译,不在推理,README 明确给出 15–60 分钟的预期并建议这段时间别动电脑。
解码批次送进检测后,检测线程继续推进下一批帧,裁剪与重建随即接棒。
站点二:bbox 向 256 生长——裁剪与预处理
这一步接收检测 bbox 和原始帧,产出 256×256 的裁剪序列,代码在 jasna/crop_buffer.py。核心是expand_bbox:
RESTORATION_SIZE = 256 BORDER_RATIO = 0.06 MIN_BORDER = 20 MAX_EXPANSION_FACTOR = 1.0它决定了裁剪的两个阶段:先按BORDER_RATIO(至少MIN_BORDER像素)向外扩一圈上下文边距,再向 256 的目标比例生长——优先吃画面内的可用空间,扩张预算不超过原框的一倍(MAX_EXPANSION_FACTOR)。随后整批等比缩放(只降不升)、反射填充补齐到 256×256,同时记下pad_offsets与resize_shapes两组坐标元数据,它们会一路带到回填阶段。
为什么带边距而不是贴框裁?因为时序模型只靠马赛克内部的像素补细节会糊,边界上下文是重建质量的来源。为什么不用"修复后再按原框中心对齐"之类的事后反推?因为缩放和填充会打乱坐标对应关系,显式携带偏移是零歧义的做法,被省掉的就是一张事后对齐表。裁剪序列按时间顺序攒好后,交给下一站做跨帧关联。
站点三:跟踪分组与 clip 重叠——时序重建的边界问题
这一步接收逐帧的裁剪序列,产出若干 clip 及各自的修复结果,跟踪代码在 jasna/tracking/clip_tracker.py。ClipTracker给每个马赛克发track_id,把连续帧聚成TrackedClip(bbox 序列 + mask 序列),长度受max_clip_size约束,超过就带重叠拆分;SceneCutDetector在镜头切换处强制断开 clip,保证两个镜头的画面永不混进同一个时序窗口。
重建前还有一段容易被忽略的账:相邻 clip 必须重叠,否则拼接处会跳变。jasna/pipeline_overlap.py 负责算重叠策略——discard_margin(对应 GUI 的 temporal overlap)决定片段首尾各丢多少帧(这些帧本身已被相邻 clip 覆盖),compute_crossfade_weights给重叠区生成线性渐变权重:
weights[local_idx] = (j + 0.5) / (2 * bf)它决定了重叠区两路修复结果按多少比例交叉淡化。也就是说,同一个时间窗会被相邻 clip 各修一遍再按权重融合,而不是"一帧只修一次"——这是时序模型在片段边界不产生闪烁的工程答案;被否掉的是"按切点硬拼接",省不了多少算力,换来的却是肉眼可见的跳变。每个 clip 送进 BasicVSR++(prepare_and_run_primary),输出 256×256 的修复张量,坐标随张量一起回到混合缓冲。
站点四:mask 混合与硬件编码——把补丁精确嵌回原帧
这一步接收原帧、修复张量和检测 mask,产出最终视频流,代码在 jasna/blend_buffer.py 的blend_frame。算法是"差分回填":把修复结果按pad_offsets反算回原裁剪坐标,双线性放大回裁剪尺寸,再以检测 mask 上采样得到的blend_mask为权重做 lerp——用大白话说,就是把马赛克那一小块像素换掉,边缘渐变一下:
original_crop.lerp_(resized_back, blend_mask.unsqueeze(0)).round_().clamp_(0, 255)mask 内侧 100% 采用修复像素,向外渐变到原像素,clamp_兜住 uint8 溢出。BlendBuffer还维护一张pending_map:记录每帧还欠哪些 track 的结果,全部到齐该帧才允许混合,从机制上杜绝"修到一半就编码"的竞态。最后帧交给 NVENC/AMF 硬件编码,音频默认流拷贝。
为什么用差分 lerp 而不是直接覆盖矩形区域?因为重建模型对"没修的像素"并非输出逐位相同的原值,直接贴矩形会在马赛克边缘留下一圈可感的色差;mask 加权让马赛克外的像素数学上不动,正好兑现 README 那句"The rest of the picture is not touched"。一帧的旅程到此结束,下一个批次已在解码线程里排队。
关键工程决策:显存与速度的几笔账
决策一:把修复面钉死在 256×256,而非对全帧跑超分。付出的是每个马赛克都要走检测、裁剪、跟踪、回填一套完整编排,代码量明显大于"整帧丢进网络";换来的是修复模型只吃局部补丁,显存占用从 v0.4.1 的 17.98 GB 典型(20.4 GB 峰值,1080p)压到 v0.9.1 的 4.8 GB 典型 / 5.6 GB 峰值(benchmarks/2026-07-26_release_matrix.md),8 GB 显卡从"跑不了"变成"跑得满"。
决策二:编解码全程硬件化。付出的是对硬件编解码器的依赖——NVIDIA 需 GTX 16/RTX 20 起(README.md),AMD 仅实验性支持,AV1 还要在_NVDEC_DECODER_OVERRIDES里单独指定原生解码器绕开 PyAV 默认路径;换来的是 benchmarks/2026-07-21_v0.8.2_e2e_decode_backends.md 里的数字:软件解码比vali硬解多花 5–13% 的端到端时间,帧数据自始至终不离开 GPU。
决策三:首次编译引擎,之后吃缓存。付出的是首任务 15–60 分钟的编译等待,README 建议期间关掉其他程序;换来的是此后每个任务直接加载model_weights里的缓存引擎,且升级 Jasna 版本时拷走该文件夹即可复用(README.md)。
决策四:检测与修复拆成两个可互换的模型族。付出的是两套模型各自的版本与维护成本;换来的是检测侧可换 YOLO 系列兼容旧权重生态(jasna/mosaic/detection_registry.py 维护整张模型清单),修复侧可插 LTX 扩散模型(NVIDIA 为主)走独立多遍流程,显存峰值由修复阶段单独决定而非两者叠加。
数字说话:官方基准里的速度、显存与对比
以下数字全部来自仓库 benchmarks/ 与 README.md,测试机为 RTX 5090。
端到端速度(修复一段 3:22 的视频,BasicVSR++):
| 输入 | 耗时 | 吞吐 | 显存(典型/峰值) |
|---|---|---|---|
| 720p H.264 | 34.4 s | 175.9 fps | 4.2 / 4.6 GB |
| 1080p H.264 | 38.6 s | 156.8 fps | 4.8 / 5.6 GB |
| 2160p AV1 10-bit | 79.7 s | 76.0 fps | — |
数据来源:benchmarks/2026-07-26_release_matrix.md(v0.9.0)与 README.md(v0.9.1 显存)。
与同类工具 Lada 0.11.0 同机对比:
| 输入 | Lada 0.11.0 | Jasna v0.9.0 | 提速 |
|---|---|---|---|
| 720p H.264 | 01:47 | 00:34 | 3.1× |
| 1080p H.264 | 02:02 | 00:39 | 3.2× |
| 2160p H.264 | 04:56 | 01:16 | 3.9× |
README.md 给出的对比口径为 3.4× / 3.6× / 4.7×(Lada 侧配置略有差异),两个口径都指向同一结论:差距在 3 倍以上。
版本演进(同一段 1080p H.264):
| 版本 | 耗时 | 显存(典型/峰值) |
|---|---|---|
| v0.4.1 | 01:46 | 19.4 / 21.9 GB |
| v0.5.0 | 00:47 | 9.8 / 10.4 GB |
| v0.9.0 | 00:39 | 9.5 / 10.4 GB |
| v0.9.1 | — | 4.8 / 5.6 GB |
速度翻了约 2.7 倍,显存降了四分之三——版本间的性能不是玄学,benchmarks/2026-07-26_release_matrix.md 把逐 commit 的消融数据都留了档(如检测预处理 kernel 一项,2160p 从 87.6 s 降到 78.1 s)。
使用建议:什么硬件跑得动,哪些坑最常见
硬件门槛与场景适配
NVIDIA GTX 16 / RTX 20 及以上(计算能力 7.5+)是完整支持线;8 GB 显存可跑默认 BasicVSR++ 路径(1080p 典型 4.8 GB),LTX 则要求 8 GB 显存加 16 GB 内存(README.md)。AMD RX 7000/9000 为实验性支持,且没有二级修复。适合的场景:素材含局部马赛克、批量大、隐私敏感;马赛克占满全帧或追求极致细节时才考虑 LTX——官方标注它比 BasicVSR++ 慢得多,Top 档约 5 倍耗时。
最常见的三个坑 ⚠️
- 首任务 15–60 分钟是引擎编译,不是卡死;升级 Jasna 版本时把
model_weights文件夹拷过去,可跳过这次等待。 - 显存不够时把 Max Clip Size 从
90降到60(README.md 的官方建议),见 docs/en/tuning.md。 - 路径不能含中文、日文等非英文字符,且官方不支持网络盘;机械硬盘上启动和加载模型会明显变慢。
收束
回到开头那组数字:3 分 22 秒的 1080p 素材,39 秒出片,显存典型 4.8 GB。Jasna 的做法是把整帧问题拆成一个个 256 像素的窗口——rfdetr 负责找位置,BasicVSR++ 只在小窗口里重建,最后按 mask 精确嵌回原帧,全程帧数据不离开 GPU。当修复一段 1080p 视频只需半分钟、8 GB 显卡就能跑通时,马赛克修复就不再是"上传-等待-下载",而是显卡上的本地实时操作。
【免费下载链接】jasnaVideo restoration tool项目地址: https://gitcode.com/GitHub_Trending/ja/jasna
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考