Extensions/Subtitle Safe Zone · 视频字幕稳定避让
ComfyUI Extension

Subtitle Safe Zone · 视频字幕稳定避让

Plan a stable subtitle region across video frames using protection masks and visual complexity.

By jinny-wj·Created 4 days ago·Updated a day ago· 0
jinny-wj/ComfyUI-Subtitle-Safe-Zone
Nodes
On cloudLocal install
Stars0
Updateda day ago
Readme

视频字幕稳定避让 / Subtitle Safe Zone

一个 ComfyUI 自定义节点原型。给一段视频或一句字幕所在的帧范围推荐固定矩形区域,尽量避开主体和复杂画面,避免逐帧重新定位造成字幕跳动。

当前版本 0.1.1(开发版)。已完成本地 CPU/MPS 测试和真实 ComfyUI 工作流测试;A100 尚未实测。

输入视频帧 → 评估整段的候选字幕区域 → 输出坐标、区域遮罩、预览和检查结果。

效果示例

导入 示例工作流 JSON,无需额外图片或视频即可运行。工作流使用 8 帧 640×360 的纯色测试画面,并把下半幅设置为白色保护遮罩。

下半幅受保护: 即使位置偏好为底部,节点仍把推荐字幕框移到上方可用区域。绿色表示所有检查帧满足遮罩覆盖阈值。

下半幅受保护时的字幕区域推荐

全画面受保护: 下图是失败案例。橙色框表示未找到满足遮挡阈值的候选位置,不能把它当成安全区域。可将工作流的全画幅 SolidMask 值设为 1 来复现。

全画面受保护时的失败提示

这些是节点实际输出的调试预览,绿色/橙色框不是烧录字幕。本节点只规划区域。

安装

ComfyUI/custom_nodes/ 中执行 git clone https://github.com/jinny-wj/ComfyUI-Subtitle-Safe-Zone.git,保存工作流后重启 ComfyUI。搜索 Subtitle Safe Zone视频字幕稳定避让

使用 ComfyUI 已有的 NumPy 与 PyTorch,无新增模型、网络请求或付费 API。本目录不附带也不修改 ComfyUI。没有自动 pip 安装或依赖升级步骤;先在独立测试实例验证,再替换正式插件目录。安装前可使用 tools/check_environment.py 只读清点宿主环境。

连接方法

  1. VHS Load VideoIMAGE 输出接本节点的 images
  2. 可选:把人物、产品等主体的逐帧分割遮罩接到 protect_mask白色表示不能被遮挡,黑色表示允许。可以把多个主体的遮罩合并后输入。
  3. preview 接 ComfyUI 自带 Preview Image,检查首、中、尾最多三帧上的同一个字幕框。
  4. xywidthheight 是以左上角为原点的像素坐标和框尺寸,供后续文字布局使用。下游节点须采用相同坐标语义;居中锚点需要自行换算。
  5. region_mask 是单张 [1,H,W] 遮罩,白色为推荐区域,含义与保护遮罩不同。它没有文字,不是字形遮罩。

第一版负责区域规划,不负责语音识别、字幕排版、SRT 解析、烧录字幕或自动检测人脸。原始视频帧应另接后续合成节点;preview 只是最多三帧的调试预览,不能当完整视频输出。

参数

| 参数 | 含义 | | --- | --- | | box_width_ratio / box_height_ratio | 字幕框占画面宽高的比例,默认 60% / 14%;应为文字描边和内边距留足空间 | | margin_ratio | 四周避让边距,以画面短边计算,默认 4% | | preferred | 在避让约束允许时偏好 bottom / top / center | | start_frame / end_frame | 从 0 开始的帧范围,包含起始、不含结束;-1 表示视频末尾 | | sample_step | 默认 1,逐帧检查;增大会加快处理,也可能漏掉短暂遮挡 | | max_overlap | 允许的最大遮罩覆盖比例,默认 0.02;严格避让用 0 | | protect_mask | 可选,尺寸必须和视频一致;支持单张广播,或帧数与视频相同的遮罩序列 |

例如 24 fps 视频中,字幕显示在第 2–5 秒,可设置 start_frame=48end_frame=120。这里的帧号指输入 IMAGE 批次,若视频加载时裁剪或改过帧率,需要据此重新计算。每句字幕可单独规划,当前没有多句之间的位置优化。

如何选择位置

在边距范围内生成最多 9×9 个候选框,计算各候选框在所分析帧上的最大主体遮罩覆盖比例。优先从满足遮挡阈值的框中选择纹理、运动较少的位置,再考虑顶部/底部偏好。全部不满足时,返回最大遮挡比例最小的候选,并明确报告失败。

主体遮罩按原分辨率分析;画面纹理和运动以低分辨率采样估计。逐帧处理,不会额外复制整个视频到 CPU,但上游仍需持有视频 IMAGE 批次。

如何解读结果

  • 绿色框:输入了保护遮罩,检查了范围内全部帧,选中的框均满足指定遮挡比例。
  • 橙色框:缺少遮罩、使用了不完整抽帧,或者找不到满足阈值的位置。查看 report_jsonwarnings
  • mask_constraint_met 仅在上述绿色条件下为 true;它不代表人工审美认可或字幕绝对不挡主体。
  • 遮罩为软值时,覆盖比例是区域内遮罩值的平均数。即使默认 2% 达标,也可能挡住一个小而重要的细节,严格场景请设置 0 并扩大主体保护遮罩。
  • 单张遮罩被视为固定保护区域,不会自动追踪移动主体。
  • 不接遮罩时只能估计纹理/运动复杂度;静止的人脸也可能被误选为可放字区域。
  • 使用有限候选网格,报告“无可用位置”仅指这些候选,不代表图像上不存在其他解。
  • 本节点不识别镜头切换;建议按单镜头或单句字幕的时间区间输入。

验证

使用装有 NumPy 的 Python 运行:

python -m unittest discover -s tests -v

测试覆盖移动主体、全屏保护、时间范围、抽帧不确定性、无遮罩降级、无效数据和区域覆盖计算。已在 ComfyUI 0.33.1 / Python 3.13.12 / PyTorch 2.10.0 / NumPy 2.4.4 / macOS ARM64 验证;19 项测试包含 CPU/MPS 检查,4 个 ComfyUI 测试工作流成功。

示例与迁移

导入 无需外部素材的示例工作流,点击运行即可验证遮罩避让。

旧合并原型的迁移和回退见 MAINTENANCE.md。本仓库不包含画中画;画中画位于 ComfyUI-Video-PiP