VideoWipe
本地硬字幕去除、视频去水印、去 Logo。
先预览检测结果,再擦烧录字幕和时间戳。命令行、Docker、或本地网页。
自动检测烧录文字 · 按轨道审阅 · 修复背景 · 保留原音轨。
视频留在本机,不上传云端。
English
·
网站
·
快速开始
·
常见问题
·
Docker
---
## 开发状态
v0.11.1 改善白闪和交叉淡化期间的字幕恢复,保留检测失败帧的安全保护,并以实际运行验证 macOS 可用性,不再把 GUI 编译字段作为唯一判断依据。
本次复查的白闪、叠化、中文复杂背景和合成描边字幕片段均已由用户按正常播放标准验收通过。这不代表逐像素还原或所有视频都能完整擦除。原用户截图案例因缺少原片和输出视频,仍未验证。macOS 干净安装与实际运行检查通过,继续核验发行版来源和原生二进制 RECORD 完整性。较强的对比度恢复会增加检测开销;验证结果及指标取舍见发布说明。
维护或接续实施先读[当前任务入口](NEXT_WORK.md)。历史取舍见[交付记录](plans/PRODUCT_EXPERIENCE_DELIVERIES.md),工具使用见[诊断说明](scripts/QUALITY_DIAGNOSTICS.md)。验证结果和已知限制见 [v0.11.1 发布说明](https://github.com/KKenny0/videowipe/releases/tag/v0.11.1)。
## 本地硬字幕去除、视频去水印
**VideoWipe** 是一个可自托管的 **硬字幕去除** / **烧录字幕擦除** / **视频去水印** 工具。它找出画面里的 **硬字幕(烧录字幕)**、**水印**、**Logo** 和 **时间戳**,让你 **先审阅每条轨道**,再只擦你勾过的区域。
它对应这些常见需求:
- 怎么去掉视频里的硬字幕 / 烧录字幕 / 硬字幕去除
- 本地去水印、去 Logo、视频 delogo
- 不想上传到在线「一键去字幕」网站
- 能用命令行、Docker、自己的 Worker 跑的开源方案
清理后的 MP4 **保留原始音轨**。
如果你要的是 Windows 下一键安装的桌面软件,更成熟的选择是 [video-subtitle-remover (VSR)](https://github.com/YaoFANGUK/video-subtitle-remover)。VideoWipe 适合另一种用法:擦之前先看检测框,能在无界面环境跑,或者把检测 → 审阅 → 修复嵌进自己的流程。
> 注意:VideoWipe **不处理** 软字幕(`.srt` / `.ass` 轨道)。它只擦 **烧进画面** 的文字。
## 快速开始
**环境:** Python 3.10+,以及 ONNX Runtime 或 PyTorch。模型权重首次运行时自动下载到 `~/.videowipe/weights/`。
尚未发布到 PyPI,请从源码安装:
```bash
git clone https://github.com/KKenny0/videowipe.git
cd videowipe
pip install -e ".[onnx]"
# 自动检测并擦除画面上的文字叠加
videowipe clean input.mp4 -o result/
```
更想用浏览器(依然是本机):
```bash
# Apple Silicon(M1/M2/M3/M4):自动使用 MPS
pip install -e ".[web,torch]"
# 其他 CPU 环境
pip install -e ".[web,onnx]"
videowipe serve
# 打开 http://127.0.0.1:8000 — 上传、预览轨道、下载清理后的 MP4
```
不想装 Python?直接看 [Docker](#docker)。
可选依赖:`.[torch]`(PyTorch)、`.[ocr]`(OCR 识别)、`.[propainter]`(仅适配依赖,不含模型本体)。
### 先试擦一小段
**选目标 → 试擦 3 秒 → 检查全片。**

*开发版真实界面记录。橙色表示实际处理范围;截图用于介绍操作,不代表最新画质已通过验收。*
1. **选择要擦的内容。** 查看目标卡片,不勾选需要保留的内容。
2. **先看一小段效果。** 使用推荐的 3 秒窗口,同步对比原片和结果;必要时调整目标或添加保护区。
3. **处理并检查全片。** 按建议位置复查,再下载结果。一段试擦满意,不代表整片都没有问题。
修改会自动保存,相同设置的试擦可以复用。[详细说明](docs/cleanup-workspace_CN.md)介绍任务恢复、保护区域、缓存限制和 SDK 用法。
## 功能一览
| | |
|--|--|
| **硬字幕擦除** | 烧录字幕,支持多语种画面 |
| **水印 / Logo / 时间戳** | 角落常驻标记、屏显时钟等 |
| **自动检测** | 不必手动画 mask(需要时仍可自备) |
| **先预览再擦** | 按轨道选择 remove / keep,并带时间段 |
| **本地优先** | 命令行、网页、Docker、Python SDK,无需云账号 |
| **保留原音** | 输出 MP4 带上源视频音轨 |
| **多语种检测** | 中文、英文、韩文等开箱可用 |
| **可换修复模型** | 默认 STTN;可选 [ProPainter](https://github.com/sczhou/ProPainter) 或任意外部修复命令 |
| **可批量 / 可嵌入** | 同一引擎连续处理多条视频 |
## 效果示例
### 字幕擦除
| 处理前 | 处理后 |
|--------|--------|
|
|
|
观看示例视频
### 自动检测(无需手动画框)
内置检测器能在多语种内容上定位文字区域:
| 视频 | 候选 | 选中 | 类型 |
|------|------|------|------|
| 中文剧集 | 4 | 2 | 顶部字幕、底部字幕 |
| 英文片段 | 2 | 2 | 底部字幕 |
| 音乐视频(韩文 + 缅甸文) | 7 | 5 | 顶部水印、底部多语字幕 |
`--detect-mode balanced`(采样约 50 帧)下的结果。绿色框为将要清理的区域。
### 本地网页界面
视频、目标卡片和下一步操作放在同一工作区。选片后查看自动推荐的试擦,
确认后原地播放、检查和下载全片。目标卡片使用实际出现帧,暂停时可切换原片与结果。
## 适合谁用?
VideoWipe 面向已经确定要擦烧录字、但不想把决定权交给黑盒的人。
- **剪辑和资料整理**:二次剪辑前清理私有或归档素材(请自行遵守版权与平台条款)
- **自己托管的人**:不愿意把原片传到在线去字幕站
- **开发者**:需要「检测 → 审阅 → 修复」作为本机命令行、Docker 任务或 Python Worker
如果你要的是免安装的 Windows `.exe`,那是 VSR 的主场。
### 常见场景
- 擦掉剧集、课程、语言学习片里的 **底部硬字幕**
- 清理 **角落 Logo / 水印** 再复用
- 去掉 **时间戳** 或平台角标
- 多语种视频 **先看检测框**,只擦需要的那几条
- 在无桌面环境的 **Worker 上批量跑**
## 工作原理
三步:
1. **检测** — 采样视频帧,找出文字区域,并按时间聚成稳定轨道(多语种,可不手动画 mask)。
2. **规划** — 生成可审阅的 **WipePlan**:每条轨道有类型(字幕 / 水印 / Logo / 时间戳)、remove|keep、时间段和精确 mask。
3. **修复** — 仅对标记为 remove 的轨道按帧生效;默认用 **STTN** 从邻帧补全;需要更高画质时可接 ProPainter 等外部模型。
例如,`videowipe clean input.mp4 -o result/` 会通过 `WipeEngine` 执行以下路径:
```text
输入视频 → 检测文字 → 生成 WipePlan → 按帧应用移除 mask
→ STTN 修复 → 写出保留原音轨的 MP4
```
**默认 CLI 命令会直接继续修复,不会停下来等待审阅。** 可按需要选择审阅方式或提供移除区域:
| 输入 / 选项 | 执行路径 |
|-------------|----------|
| `--preview` | 检测并保存计划及预览产物后停止,不加载修复模型。可编辑计划 JSON 后再执行。 |
| `--plan plan/wipe_plan.json` | 读取并校验已审阅的计划,然后修复,不重新自动检测。 |
| `--mask mask.png` | 跳过自动检测和规划,按提供的 mask 修复。与 `--plan` 互斥。 |
若要在 CLI 中交互选择后再修复,使用 `--confirm`。本地网页界面提供上文的“选择目标 → 短片试跑 → 完整结果”流程。
## 和其他做法对比
| | 在线去字幕站 | [VSR](https://github.com/YaoFANGUK/video-subtitle-remover) | 手动画 mask(AE / 达芬奇) | **VideoWipe** |
|--|--------------|------------------------------------------------------------|---------------------------|---------------|
| 隐私 | 需上传 | 本地 | 本地 | **本地** |
| 自动找烧录字 | 有时有 | 有 | 全靠手 | **有** |
| 擦之前能审阅 | 少见 | 有限 | 靠人工 | **有(WipePlan / 网页)** |
| 无界面 / Docker / Worker | 否 | 桌面软件 | 桌面软件 | **命令行、Docker、Python** |
| Windows 一键 `.exe` | 有时有 | **有** | 不适用 | 无(源码或 Docker) |
| 接入自己的流程 | 难 | 难 | 难 | **Python SDK + CLI** |
### VideoWipe 不做什么
- 不是 **软字幕** 工具(`.srt` / `.ass`)
- 不是 **翻译** 或重新打轴产品
- 不是每段素材都完美无痕——快运动、细纹理、半透明标记更难,请 **先预览**
- 不是云 SaaS——由你在本机或自己的机器上运行
## 命令行用法
```bash
# 推荐:自动检测并擦除
videowipe clean input.mp4 -o result/
# 只要字幕,只要画面底部
videowipe clean input.mp4 --target subtitle --region bottom -o result/
# 自然语言意图
videowipe clean input.mp4 --intent "去掉底部中文字幕" -o result/
# 只预览检测结果(不做修复)
videowipe clean input.mp4 --preview -o plan/
# 执行已审阅的计划
videowipe clean input.mp4 --plan plan/wipe_plan.json -o result/
# 自备 mask 时
videowipe clean input.mp4 -m mask.png -o result/
```
#### `clean` 选项
| 参数 | 说明 | 默认 |
|------|------|------|
| `--target` | 清理类型(可重复):`subtitle`、`timestamp`、`watermark`、`logo` | 自动检测全部 |
| `--region` | 屏幕区域(可重复):`top`、`bottom`、`top-left`、`top-right`、`bottom-left`、`bottom-right`、`center` | 全部区域 |
| `--intent` | 自然语言清理意图 | — |
| `--preview` | 只写检测产物,不修复 | 关 |
| `--plan` | 执行已有 `wipe_plan.json`(与 `-m, --mask` 互斥) | — |
| `--confirm` | 显示检测目标并确认后再处理 | 关 |
| `--detect-mode` | `fast`(24 帧);`balanced`(50)/ `sensitive`(80)会对检测出的 remove 段做更密复核 | `balanced` |
| `--ocr` | OCR:`auto`、`off`、`rapidocr` | `auto` |
| `--agent` | 本地 LLM CLI,用于意图选择(如 `claude`、`codex`) | — |
| `--external-command` | 外部修复命令(绕过内置 STTN) | — |
| `-g, --gap` | 每个修复分段的帧数;`25` 平衡性能和质量,值越大上下文越多,但计算和内存成本超线性增长 | `25` |
| `-d, --dual` | 输出中并排显示原片 | 关 |
| `-m, --mask` | mask 图片路径 | 自动 |
#### Agent 选择诊断
`clean` 命令将 Agent 状态写到 stderr。SDK 可读取 `WipeResult.agent_decision`;沿用返回路径的 `process()` 时,可读取 `WipeEngine.agent_decision`。规划还会将记录保存到 `agent_decision.json` 和 `WipePlan.request["agent_decision"]`。
`status` 包含 `not_requested`、`success`、`command_unavailable`、`timeout`、`execution_failed` 和 `invalid_output`。只有同时提供 Agent 和意图才调用 Agent。合法空选择属于成功,会保留所有候选;失败继续按本地规则选择。重复 ID 会去重,缺少字段、类型非法和未知 ID 均拒绝。
`selection_source` 区分 `agent`、`local_rules`、`user_selection`、`saved_plan` 和 `manual_mask`。执行已有计划时,结果表示本次未调用 Agent,原计划仍保留当时的规划记录。新增诊断仅保存固定原因码和选择来源,不保存 Agent 命令、生成的提示词或进程输出。返回候选列表或 `None` 的旧自定义选择接口继续可用;无法细分原因的旧接口失败标记为 `legacy_selector_failed`。
旧命令:detext
`detext` 主要只处理字幕。新用法请优先用 `clean`。
```bash
videowipe detext -v input.mp4 -o result/
videowipe detext -v input.mp4 -m mask.png -o result/
```
| 参数 | 说明 | 默认 |
|------|------|------|
| `-v, --video` | 输入视频 | 必填 |
| `-m, --mask` | mask 路径 | 自动 |
| `-o, --output` | 输出目录 | `result/` |
| `-w, --weight` | 模型权重(PyTorch `.pth`/`.pt`,或 ONNX 前缀) | 自动 |
| `-g, --gap` | 每个修复分段的帧数;值越大计算和内存成本越高 | `25` |
| `-d, --dual` | 并排原片 | 关 |
| `--external-command` | 外部修复命令 | — |
## Docker
**CPU:**
```bash
docker pull ghcr.io/kkenny0/videowipe:latest
docker run --rm -v "$(pwd)":/data ghcr.io/kkenny0/videowipe clean /data/input.mp4 -o /data/result/
```
**GPU:**
```bash
docker pull ghcr.io/kkenny0/videowipe:gpu
docker run --rm --gpus all -v "$(pwd)":/data ghcr.io/kkenny0/videowipe:gpu clean /data/input.mp4 -o /data/result/
```
或用脚本自动选 CPU / GPU 镜像:
```bash
./scripts/docker-videowipe.sh clean input.mp4 -o result/
```
| 镜像 | 体积 | GPU | 说明 |
|------|------|-----|------|
| `ghcr.io/kkenny0/videowipe:latest` | ~480 MB | 否 | 仅 CPU,体积最小 |
| `ghcr.io/kkenny0/videowipe:gpu` | ~1.4 GB | 是 | 预构建 GPU 镜像 |
| `videowipe:gpu` | ~1.4 GB | 是 | 本地构建标签 |
浮动标签 `latest` / `gpu` 跟随当前 main 构建;正式版本请到 GHCR 查带版本号的标签。
从源码构建镜像
```bash
docker build --target runtime-cpu -t videowipe:latest .
docker build --target runtime-gpu --build-arg VARIANT=gpu -t videowipe:gpu .
```
GPU 镜像需要 NVIDIA 运行时才能走 CUDA;否则 ONNX Runtime 会回退到 CPU。
```bash
docker run --rm -v "$(pwd)":/data videowipe:latest clean /data/input.mp4 -o /data/result/
docker run --rm --gpus all -v "$(pwd)":/data videowipe:gpu clean /data/input.mp4 -o /data/result/
```
## 更高画质修复(可选)
默认后端是 **STTN**(可用 CPU + ONNX)。难修的镜头可接外部模型。
[ProPainter](https://github.com/sczhou/ProPainter) 已验证为更高画质选项:
```bash
git clone https://github.com/sczhou/ProPainter.git ../models/ProPainter
videowipe clean input.mp4 --model propainter --propainter-dir ../models/ProPainter
# 等价写法:
videowipe clean input.mp4 --external-command "python scripts/propainter_wipe.py"
```
> **说明:** ProPainter 在 480p 大约需要 16GB 显存,模型许可证为 NTU S-Lab License 1.0(非商业)。
画质对比:ProPainter vs STTN
多语种音乐视频(韩文 + 缅甸文字幕,852×480,约 10 秒),同一 mask。
| 原片 | ProPainter(GPU fp16) | STTN(CPU ONNX) |
|------|------------------------|------------------|
|
|
|
|
## Python API(流水线 / 批量)
在支持的 Mac 上,Torch 自动使用 MPS(CUDA → MPS → CPU);Python API 仍可显式指定 `device="cpu"`。时间遮罩在当前输出段没有移除像素时跳过相应裁剪带,有目标的裁剪带仍使用完整上下文。
命令行、网页、Docker 用的是同一套引擎。要做批处理或接入自己的 Worker 时用这里。
```python
from videowipe import remove_text
# mask 可选;省略时自动检测
remove_text(video="input.mp4", output="result/")
```
带目标选择的完整 clean 流水线:
```python
from videowipe import WipeEngine
engine = WipeEngine(task="clean", detect_mode="balanced", ocr="auto")
engine.process(
video="input.mp4",
targets=["subtitle", "watermark"],
regions=["bottom"],
intent="去掉中文字幕和 Logo 水印",
output="result/",
)
engine.cleanup()
```
长驻引擎批量处理(避免重复加载模型):
```python
from videowipe import CancellationToken, WipeEngine, WipeRequest
with WipeEngine(task="detext") as engine:
result = engine.run(
WipeRequest(video="clip1.mp4", mask="mask.png", output_dir="result/clip1"),
cancellation=CancellationToken(),
)
print(result.output_path, result.backend, result.timings)
```
示例见 [examples/batch_worker.py](examples/batch_worker.py)、[examples/custom_inpainter.py](examples/custom_inpainter.py)。
审阅与修改 WipePlan
可不加载修复模型先生成计划;只改 JSON 里每条轨道的 `action` / `segments`(不要改 sidecar `.npz` mask),再执行:
```python
from videowipe import CancellationToken, WipeEngine, WipeRequest
engine = WipeEngine(task="clean")
plan = engine.plan(
WipeRequest(video="input.mp4", output_dir="plan/"),
on_candidates=lambda snapshot: print(snapshot["default_selected_ids"]),
cancellation=CancellationToken(),
)
engine.cleanup()
with WipeEngine(task="clean") as engine:
result = engine.run(WipeRequest(
video="input.mp4",
output_dir="result/",
plan="plan/wipe_plan.json",
))
```
可选的 `on_candidates` 在候选证据保存后、时间细化前收到独立元数据快照,可用于提前展示审阅界面;执行仍需等待 `plan()` 返回。回调异常会向上传播。
```bash
videowipe clean input.mp4 --preview -o plan/
videowipe clean input.mp4 --plan plan/wipe_plan.json -o result/
```
计划就是普通 JSON,不绑定任何 LLM 或云服务。计划与源视频绑定,换片执行会被拒绝。
## 常见问题
**能去掉软字幕(`.srt` / `.ass`)吗?**
不能。软字幕是独立文件或轨道。VideoWipe 只擦 **烧进画面** 的硬字幕。
**视频会离开我的电脑吗?**
默认路径全在本机(命令行、本机网页 `127.0.0.1`、带挂载的 Docker)。不会上传到 VideoWipe 云端。
**音轨还在吗?**
在。输出 / 下载的 MP4 保留源视频音轨。
**必须有显卡吗?**
不必。CPU + ONNX Runtime 即可。有 GPU 时会更快,ProPainter 等路径也更吃显存。
**上 PyPI 了吗?**
还没有。请从本仓库安装,或拉 Docker 镜像。
**硬字幕和水印可以分开选吗?**
可以。用 `--target subtitle` / `--target watermark` / `--region bottom`、自然语言 `--intent`,或网页里按轨道开关。
**STTN 和 ProPainter 怎么选?**
STTN 是默认(更轻、CPU 友好)。ProPainter 在难修区域往往更好,但更吃显存,且该模型为非商业许可。
**一定能修得看不出痕迹吗?**
不能保证。快速运动、细纹理、半透明标记更难。长任务前请用 **预览 / 确认**。
**能嵌进自己的产品或 Worker 吗?**
可以。把 VideoWipe 当可嵌入引擎:一个 `WipeEngine`、稳定的请求/结果类型、可换修复后端。产品边界是检测 → 计划 → 修复,不是完整剪辑台或云工作室。
**和 video-subtitle-remover(VSR)有什么区别?**
VSR 是带 Windows 安装包的桌面软件。VideoWipe 强调先预览再擦,并且能用命令行、Docker、本地网页或自己的 Worker 跑。要解决的是同一件事(硬字幕去除 / 视频去水印),用法不一样。
## 支持项目
如果 VideoWipe 帮你省下了去字幕、去水印的时间:
支持会用于模型打包、Docker 镜像、检测调参和文档维护。
## 相关项目
| 项目 | 关系 |
|------|------|
| [Video-Auto-Wipe](https://github.com/a312863063/Video-Auto-Wipe) | 本仓库的上游来源 |
| [video-subtitle-remover (VSR)](https://github.com/YaoFANGUK/video-subtitle-remover) | 同一需求上最常见的桌面软件 |
| [STTN](https://github.com/researchmm/STTN) | 默认画面修复模型 |
| [OnnxOCR](https://github.com/jingsongliujing/OnnxOCR) | 内置文字检测 |
| [ProPainter](https://github.com/sczhou/ProPainter) | 可选的更高画质修复(不随包装) |
| [InpaintDelogo](https://github.com/Purfview/InpaintDelogo) | AviSynth+ 去 Logo 插件,另一套栈 |
## 致谢
基于 [STTN](https://github.com/researchmm/STTN) 与原始 [Video-Auto-Wipe](https://github.com/a312863063/Video-Auto-Wipe)。内置文字检测来自 [OnnxOCR](https://github.com/jingsongliujing/OnnxOCR)。
## 许可证
GNU General Public License v3.0,详见 [LICENSE](LICENSE)。
本仓库衍生自 GPL-3.0 许可的 Video-Auto-Wipe。若分发 VideoWipe 或衍生合并作品,请自行核对 GPL-3.0 对你分发方式的要求。
## Star 趋势