Skip to the content.

视频区域修复的时间线与时序融合

VideoWatermarkRemover 将本地 MI-GAN 图片模型的区域修复与相邻帧光流融合连接起来。图片修复模型没有学习视频时序;跨帧贡献来自可检查的光流和已知区域门限。输出保留规范化 RGB8 基准的蒙版外像素,并提供蒙版预览和逐帧记录供复核。调用示例、参数默认值和部署步骤放在 Inference README。

本页描述显式手动请求及两种模式共用的修复链;无蒙版入口的自动视频检测另外记录分割与默认模式合同。

处理链与发布边界

  1. .NET 为调用建立私有、随机命名的工作目录,以有限字节读取源视频与静态蒙版。源视频打开期间禁止其他 Windows 写入者,处理结束前重新计算哈希并核对长度、修改时间;其他系统仍要求调用方保持源文件稳定,不能将这些检查视为文件系统快照。
  2. 单个推理 worker 验证固定模型字节及运行库版本,加载一次 MI-GAN CPU session,检查实际帧和音轨,再按 presentation 顺序处理视频。它只持有前帧、当前帧和后帧的修复状态,逐帧输出视频、灰度蒙版及 JSON 记录。
  3. .NET 通过共享 MediaProcessRunner 调用 FFmpeg,将已经修复的视频与源文件的所有音轨合成;音频统一解码为 pcm_f32le,不使用 -shortest。
  4. 校验 worker 重读源视频、输出和蒙版,逐帧核对 PTS、duration、数量、方向与蒙版外 RGB,逐轨核对实际解码的音频样本。验证完成后删除中间视频,复核整个输出包字节数及源文件哈希,再以同父目录 Directory.Move 发布新目录。

输出目录必须尚不存在。result.mkv 使用 FFV1;mask-preview.mkv 是同时间线的二值灰度视频;frame-metadata.json 保存每帧 PTS、选区、修改数量和邻帧拒绝原因;summary.json 保存模型、运行库及源音轨说明;三个 PNG 为首帧原图、蒙版和结果。未复制字幕、章节、封面和额外视频轨,仅处理首个非封面视频轨。

进程错误、超时、取消、源变化或验证失败均阻止发布,并清理该调用拥有的暂存文件。清理异常不会覆盖已有处理异常。成功移动后若暂存目录清理失败,调用可能报告清理错误,但已经发布的完整目录仍在;宿主可按返回目标路径检查并处理这个边界。取消使用基础媒体进程管理终止整个进程树;同一实例串行执行,释放先标记禁止新操作,再等待活跃调用结束。

坐标与二值选区

解码出的完整 DISPLAYMATRIX 只接受 identity 和精确 90°、180°、270° 正向旋转。逐帧矩阵和尺寸必须一致。反射、非直角、缩放、平移、透视矩阵、非方形像素、隔行、alpha、非 8 位及 HDR / BT.2020 输入明确拒绝;单独读取取整后的 frame.rotation 无法识别这些差异。

矩阵只应用一次,输出方向归零。蒙版坐标基于旋转后的显示尺寸。静态 PNG 必须尺寸完全一致、严格不透明且每个像素为灰度 0 或 255;不缩放、不猜阈值,PNG 的 EXIF 方向不另行解释。白色编辑,黑色保留。

矩形关键帧从相对首个实际视频 PTS 的零时刻开始,时间严格递增,每个时刻的矩形数量一致;同索引矩形的 x、y、宽、高线性插值,末位置保持到结束。关键帧使用 TimeSpan.Ticks,帧时刻使用有理数 PTS,直到向外整数取整才光栅化。这样不会因 0.04 / 0.1 的浮点误差将整数边界额外扩一列。每个关键帧矩形须完整位于画面内。

MI-GAN 输入为 uint8[1,3,H,W] 图片和 uint8[1,1,H,W] 已知区蒙版,已知=255、洞=0。推理洞扩展半径 3,来自固定 pipeline 中 maxpool3 的半径 1 与 Gaussian5 的半径 2;最终合成仍只提交原始二值蒙版内的像素。空蒙版跳过模型运行和光流融合;非空蒙版要求宽高至少 3。

相邻帧融合与退回规则

当前帧和前后相邻帧分别进行 Farneback 稠密光流计算。对每个邻帧:

支持不足或残差过大的邻帧贡献为零,保留独立 MI-GAN 结果。通过门限后,邻帧已知像素权重为 1,邻帧模型生成像素权重为 GeneratedNeighborWeight,当前修复权重为 1;加权平均取整后只写入当前最终蒙版。门限公开配置,但没有作为准确率校准;局部遮挡、重复纹理、错误蒙版、曝光变化和快速运动仍可能使融合变差。

时间与音频契约

PyAV 时间模型以整数 PTS 乘各自 time_base 表达 presentation 时间。本实现不按帧索引推算时间,不丢帧或重复帧。Matroska 输出使用 1 ms 网格,非负 PTS 四舍五入后的误差最多 0.5 ms;碰撞、重复、倒退或缺失 PTS 均拒绝。原本不等间隔的帧仍保持不等间隔,但间隔和 duration 可能因量化各相差至多 1 ms。

正 duration 按源值量化。缺失的中间 duration 可由下一实际 PTS 确定;缺失的末 duration 仅在源轨声明终点确实晚于末 PTS 时由该终点确定。不使用平均帧率或上一帧间隔猜末帧时长;不能确定的输入拒绝。编码后的 PTS 和 duration 共同生成摘要并复核,避免只检查 PTS 而遗漏最后一帧显示长度。

音频保证是 实际解码 float32 样本、样本数和 interleaved 通道顺序,不是压缩码流复制或播放器声道角色保证。AAC 的 priming / padding 可能使实际解码样本范围不同于容器声明 duration,以实际解码范围为比较基准。所有轨沿用共同 presentation 原点,保留各轨相对偏移;不各自归零,也不因视频较短截掉音频尾部。PCM 的初始 PTS 同样量化到 1 ms。

逐轨按具体 stream 对象解码,避免全局 stream index 与 audio ordinal 混淆。unsigned PCM 先减中点再归一化;有符号整数按位深归一化;平面样本转为 interleaved float32 后计算 SHA-256。轨内每个解码块核对 首PTS + 已有样本数 / 采样率,容忍源时间基或 1 ms 网格的舍入误差;更大 gap、overlap、采样率或布局变化拒绝。负 presentation 时间戳和空音轨也拒绝。

源未标角色的 1/2 声道可保留原通道顺序;超过两声道且没有角色声明则拒绝。已声明 mono、stereo、2.1、3.0、quad、5.1、5.1(side)、7.1 的角色记录在 manifest / 返回元数据中。Matroska PCM 可能不保存标准 layout 标签,因此不能保证播放器会按源角色自动分配扬声器;验证的是相同通道顺序及实际样本。

资源上界与部署取舍

输入预算在读取时校验;帧数、单帧尺寸及像素、累计像素、实际 presentation 时长、音轨数与实际音频样本值逐项计数。最终字节预算包括结果视频中的 PCM、灰度预览、PNG 和 JSON;FFmpeg -fs 只用于早停,还会检查完整帧、音频样本及实际总字节,截断文件不会发布。

矩形请求另有 MaximumMaskKeyframes、MaximumRectanglesPerKeyframe 和 MaximumMaskRectangles 三个正数预算,默认分别为 512、128、65,536。每个列表先检查 Count,累计矩形数按剩余额度校验,然后只复制已检查的数量;超限发生在启动进程、写 job JSON 和读取视频之前。快照在首次等待前完成,调用进入排队后对原数组或标准集合的修改不会改变本次处理定义。JSON 仅包含这些有界条目及固定宽度的整数坐标和时间 ticks,大小可由请求预算推导,不把请求定义混入压缩视频文件的字节限额。

处理中还保留原始输入快照和一份无音轨中间视频,因此临时空间可能高于最终输出包预算。三帧环限制保存的帧状态,光流张量和模型仍需要额外内存;像素限制不是原生解码器或整个进程的内存硬配额。限额按调用计算,宿主仍需限制排队请求数和实例数,并按部署环境隔离不可信媒体的解码资源。

视频 worker 使用 video-modelmanifest.json 固定的 MI-GAN 字节与 SHA,模型版本与图片修复一致。Python 依赖独立锁定 PyAV 15.1.0、ONNX Runtime 1.20.1、OpenCV wheel 4.13.0.92,验证环境为 Python 3.12、NumPy 2.0.2、Pillow 12.3.0;这里的 Python ONNX 版本与图片 .NET CPU 后端 1.31.0 分开部署。

MI-GAN 代码及权重许可为 MIT;PyAV 自身为 BSD-3-Clause。其链接的 FFmpeg 库以及宿主 FFmpeg 命令行需按各自构建核对 LGPL/GPL 条件,不能将 PyAV 的 BSD 许可扩展到所有原生组件。NuGet 不携带这些 Python 包、权重或 FFmpeg 可执行文件,接口运行期间不下载或安装。

已测证据与局限

固定合成样本使用移动背景和移动文字水印,共 8 帧 512×384,实际 PTS 为 0,40,140,200,360,400,510,630 ms。相同选区下,独立 MI-GAN 的 masked MAE 为 5.99,融合后为 5.33;按已知背景运动补偿的误差闪烁指标从 4.87 降至 3.38。该指标依赖合成参考真值,不作为生产质量分数。编码后蒙版外 RGB 差异为零。

仅检查正反光流时,纯色场景切换曾把修复 MAE 从 5.35 恶化到 19.74;加入已知区域残差和纹理支持后,纯色红蓝、照片反相、棋盘到随机纹理三种切换均拒绝邻帧贡献。低纹理同场景和全蒙版同样退回独立修复;正常移动样本仍保留非零邻帧贡献。

实际音频覆盖 unsigned PCM 的中点归一化、44.1/48 kHz、AAC、非零音轨偏移、非零视频原点、双音轨与已声明 5.1 的较长音轨,并逐字节比较规范化解码样本。细粒度 1/90000 时间基的 VFR 保持非等间隔;0.5 ms 内碰撞示例明确拒绝。90° 归一化与 FFmpeg 的 RGB 对照一致,非直角和反射拒绝。

这些短样本不覆盖所有编解码器、容器、遮挡和运动。模型合成不能恢复被遮住的真实内容,光流也不能保证普遍降低闪烁。自动分割、默认自动模式和学习型视频时序模型不属于此手动处理合同。

正式 worker 在本机 CPU 4 线程处理同尺寸的 8 帧、静态宽蒙版时,含冷启动的 prepare 为 10.89 s,PCM 合成为 0.19 s,完整验证为 2.05 s;每 20 ms 采样的推理进程峰值 RSS 为 1,113,722,880 B,最终包为 961,796 B。该测量说明模型工作集明显大于三帧 RGB 缓冲,不能用这组短视频推算任意分辨率和长度的吞吐量。