去水印 / 去字幕

检测确认流程已实现。本文新增的保护区、精确写回和无转码空清单行为随协议 v2 部署生效;调用前以 GET /task/video_purify/capabilities 返回的 review_protocol: 2 为准。未传 phase 的旧调用保持兼容。

检测文字候选,并通过文字框或手动区域处理水印、Logo、硬字幕等叠加元素,支持全屏净化、仅字幕区域净化、自定义区域净化、指定区域直接去除(可限定时间段),以及 ffmpeg / raft 两种去水印算法。

示例效果

subtitle 模式

处理前

处理后

full_screen 模式

处理前

处理后

两种使用方式

怎么选择

这个接口支持两种用法,请根据用户的实际需求选择:

客户端由调用方自行准备

本文所说的“客户端”不是同合云提供的现成界面,而是调用方自行准备、开发和维护的 GUI。它可以是 Web 端、桌面客户端或移动 App,具体形态由调用方决定。

调用方需要自行实现视频预览、检测结果展示、区域的新增/删除/修改、位置和大小调整、时间范围调整以及最终确认提交等可视化操作。同合云接口只负责返回检测结果和执行去水印,不负责提供这套用户界面。

方式一:一次性完成

如果用户已经知道要处理什么内容、处理哪一块区域,可以直接发起一次请求。接口按照 full_screen、subtitle、custom 或 region 的设置完成去水印任务并生成处理结果。这条路径不需要传 phase 这个参数,兼容原有调用方式。

方式二:先检测、再确认、再处理(检测确认模式)

如果用户想先看看系统找到了哪些水印,或者需要在检测结果上手动增删改查,就使用这条路径。它适合“系统负责找,用户负责决定”的场景。

第一步,调用方开发的客户端让系统扫描全屏、字幕区域,或者用户指定的一块区域。系统当前使用文字检测,返回候选文字位置;图形 Logo 和半透明图案需要调用方手动补框,不会生成处理后的视频。一个视频可能找到几千个候选区域,客户端需要拿到完整的检测结果。

第二步,客户端在 GUI 中让用户检查和编辑这些候选区域:

  • 删除误检:从最终清单中移除候选;若它与其他保留框重叠,需添加保护框才能保证不被覆盖。
  • 调整位置和大小:修改区域的坐标和宽高。
  • 调整时间:修改这个区域需要处理的开始和结束时间。
  • 新增处理区域:手动画一个区域,表示这个区域在指定时间内的全部内容都要去掉。

用户编辑完成后,客户端得到一份最终清单。用户不想处理的候选不放进清单,想处理的候选和新增区域都放进清单。

第三步,客户端把最终清单提交给同一个接口。服务端只处理清单里的区域,不会重新检测,也不会把用户删掉的区域自动加回来。实际处理范围为去除框的并集减去保护框的并集,保护框优先。

如果用户删除了全部候选,最终清单可以是空数组。协议 v2 会直接复制原文件,不转码、不启动修复引擎;HTTP 建单仍沿用既有计费。CLI 会本地直接返回源文件,不提交空处理任务。

下面的内容是给客户端和后端实现时查阅的字段约定。

接口字段和实现约定

  • 使用 phase=detect 请求检测结果,只返回候选区域,不生成去水印视频。
  • 客户端下载检测结果,在 GUI 中对候选区域进行增删改查。
  • 使用 phase=purify 提交客户端最终保留的 regions,执行真实去水印。

处理请求中的 regions 是唯一权威集合:删除候选就是从数组中移除,修改候选就是修改对应字段,新增整块去水印区域就是追加一个 source=manual 的区域。服务端不会在处理请求中重新检测,也不会自动恢复被删除的候选。

检测结果可能达到数千个区域,完整检测结果通过 JSON 文件产物提供,执行请求支持提交大规模 regions;如果单个任务超过视频时长、分辨率或请求体等服务端资源限制,服务端会拒绝该任务。

检测请求和执行请求分别创建任务,分别按现有视频时长规则计费。调用方可以根据自己的产品流程决定是否先检测。

新增请求参数

参数名类型必填默认值说明
phasestring使用检测确认模式时是—detect:只检测;purify:按最终 regions 执行
detect_scopestringphase=detect 时否full_screen检测范围:full_screen(全局)/ subtitle(字幕区域)/ custom(detect_roi 指定区域)
detect_roiobjectdetect_scope=custom 时是—检测区域,格式为 {x,y,w,h},坐标为 0-1 归一化画面比例
regionsarrayphase=purify 时是—最终去除清单;每项须包含下文的区域对象全部字段,可为空数组
protect_regionsarray否[]phase=purify 的保护清单,结构与 regions 相同;与去除区域重叠时保护优先
source_file_idstring否—phase=purify 的源文件绑定校验;提供时须与 file_id 一致

检测确认模式下,phase=purify 不使用 purify_scope;最终要处理的范围完全由 regions 决定。原有 purify_scope、roi 和 regions 参数继续保留给未传 phase 的一次性处理方式。

保护、精确范围与恢复

phase=purify 可传 protect_regions(默认空数组,结构与 regions 相同),保护范围在最终羽化之后扣除。source_file_id 可选;提供时必须与 file_id 相同,检测文件的 source.file_id 可用于绑定源素材。坐标相对旋转后显示画布,时间为秒,区间为 [start,end);video.fps_exact 保存有理帧率。区域边界写回限定在最终范围内,但有损成片编码仍可能改变邻近像素,不能承诺逐像素完全一致。VFR 源仍按现有 CFR 网格输出。

ffmpeg 是区域模糊,raft 是内容修复;修复不保证恢复遮挡前的真实画面。删除一个候选不会自动抵消其他重叠去除框。万级区域没有固定 16 框限制,但不承诺任意时长、分辨率或数量都能完成。

Agent 可以用 gtrk purify detect video.mp4 --json 获取完整区域文件与摘要;用 gtrk purify edit regions.json --delete-id det-000001 --out final.json 编辑,再 gtrk purify apply final.json --json 执行。目标范围已明确时使用 gtrk purify run video.mp4 --detect-scope subtitle --json。gtrk purify resume journal.json --json 复用已提交任务;提交响应丢失时停止并要求核对云端,不自动重发。CLI 在新的处理请求前检查协议 v2,旧服务不会静默丢弃保护框。

区域对象

检测确认模式的 regions 每项必须包含 id、source、x、y、w、h、start、end;最终提交时 end 也必须明确提供:

  • id:稳定区域标识;检测结果由服务端生成,客户端新增区域时自行生成唯一 ID。
  • source:detected(检测结果)或 manual(客户端新增)。
  • x、y、w、h:0-1 归一化画面比例,区域不能越出画面。
  • start、end:从视频开头计算的秒数,必须满足 start≥0 且 end>start。

同一份最终清单中的 id 必须唯一。区域可以重叠,服务端会在算法内部合并或复用重叠遮罩,但不会修改调用方提交的清单。

检测结果中的区域统一使用秒,不对外暴露算法内部的帧号。当前检测器不对外承诺稳定的识别文本或置信度字段。

检测结果文件

phase=detect 完成后,output_result 提供 JSON 文件 ID、下载路径和候选数量。完整 JSON 文件中的 regions 数组可以包含数千个候选区域,客户端编辑后将最终数组提交到 phase=purify。

JSON 文件结构固定为:

{
  "version": 1,
  "source": {"file_id": "537489015178246"},
  "video": {
    "width": 1920,
    "height": 1080,
    "duration": 120.0,
    "fps": 30,
    "fps_exact": "30/1"
  },
  "regions": []
}

查询协议能力

使用保护区与最终清单处理前,先查询服务能力。该查询需要鉴权,不创建任务、不计费;返回 data.review_protocol: 2 后再使用本文的 v2 行为。能力声明不能代替实际任务执行成功的验收。

curl https://api.ai-mcn.tv:10000/task/video_purify/capabilities \
  -H "Authorization: YOUR_API_KEY"
{"code": 200, "data": {"review_protocol": 2}, "msg": "success"}

创建任务

基本信息

项目值
请求方法POST
请求路径/task/video_purify
Content-Typeapplication/json
鉴权方式Authorization 请求头(直接传 API Key)

请求参数(Body)

参数名类型必填默认值说明
file_idstring是—已上传视频文件的 ID
purify_scopestring否"full_screen"净化范围:full_screen(全屏检测去除所有水印)/ subtitle(仅净化字幕区域)/ custom(仅净化 roi 指定区域)/ region(按 regions 给出的框直接去除,可限定时间段)
roiobjectcustom 时必填—自定义净化区域,归一化坐标(0-1 画面比例):{"x","y","w","h"},需 w>0、h>0、x+w≤1、y+h≤1
regionsarrayregion 时必填—兼容模式下按给定区域直接去除;检测确认模式下由 phase=purify 提交最终区域集合,检测结果和执行请求都支持千级区域
purify_func_typestring否"ffmpeg"ffmpeg(默认,区域模糊)/ raft(内容修复,仅支持 20 分钟以内视频);修复不保证还原被遮挡前的真实画面

请求示例

只处理已知角标,并保护与之重叠的画面文字:

此请求无需先检测。框内全部内容都会被处理,示例坐标须按实际视频调整;保护区可限定到更短的时间段。

curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "source_file_id": "537489015178246",
    "phase": "purify",
    "purify_func_type": "ffmpeg",
    "regions": [
      {"id": "corner-1", "source": "manual", "x": 0.8, "y": 0.02, "w": 0.18, "h": 0.08, "start": 0, "end": 5}
    ],
    "protect_regions": [
      {"id": "keep-1", "source": "manual", "x": 0.8, "y": 0.08, "w": 0.08, "h": 0.02, "start": 2, "end": 5}
    ]
  }'

检测确认模式:第一次请求(检测):

curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "phase": "detect",
    "detect_scope": "full_screen"
  }'

检测确认模式:第一次请求(只扫描指定区域):

curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "phase": "detect",
    "detect_scope": "custom",
    "detect_roi": {"x": 0.0, "y": 0.75, "w": 1.0, "h": 0.25}
  }'

检测确认模式:第二次请求(确认后执行):

curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "phase": "purify",
    "purify_func_type": "raft",
    "regions": [
      {
        "id": "det-000001",
        "source": "detected",
        "x": 0.70,
        "y": 0.04,
        "w": 0.22,
        "h": 0.09,
        "start": 0.0,
        "end": 5.2
      },
      {
        "id": "manual-000001",
        "source": "manual",
        "x": 0.05,
        "y": 0.05,
        "w": 0.25,
        "h": 0.20,
        "start": 2.0,
        "end": 8.0
      }
    ]
  }'
curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "purify_scope": "subtitle",
    "purify_func_type": "raft"
  }'

custom 模式示例(仅净化底部 20% 区域):

curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "purify_scope": "custom",
    "roi": {"x": 0.0, "y": 0.78, "w": 1.0, "h": 0.2}
  }'

region 模式示例(去除右上角角标的前 5 秒,以及底部区域从第 120 秒到结尾):

curl -X POST https://api.ai-mcn.tv:10000/task/video_purify \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "purify_scope": "region",
    "purify_func_type": "raft",
    "regions": [
      {"x": 0.8, "y": 0.02, "w": 0.18, "h": 0.08, "start": 0, "end": 5},
      {"x": 0.3, "y": 0.85, "w": 0.4, "h": 0.1, "start": 120}
    ]
  }'

custom 与 region 怎么选

  • custom:在 roi 范围内识别文字,只去除识别到的文字,范围里的其它内容保持原样。
  • region:不做识别,框内全部内容都会被处理(包括画面主体),适合图形台标、半透明图案、艺术字这类识别不到的元素,也适合只在某段时间出现的角标。
  • ffmpeg 方式在框内做模糊,raft 方式做修复补全;框越小、越贴近要去除的元素,效果越好。框的边缘会有几个像素的柔和过渡。

成功响应示例

{
  "code": 200,
  "msg": "success",
  "data": {
    "task_id": "537489015178247",
    "task_type": "video_purify",
    "status": "queued"
  }
}

查询任务结果

基本信息

项目值
请求方法GET
请求路径/task/video_purify/{task_id}
鉴权方式Authorization 请求头(直接传 API Key)

响应参数(output_result)

参数名类型说明
phasestring本次任务的阶段:detect / purify
file_idstringphase=purify 时返回,处理后的视频文件 ID
download_urlstringphase=purify 时返回,处理后视频的下载路径
regions_file_idstringphase=detect 时返回,检测结果 JSON 文件 ID
regions_download_urlstringphase=detect 时返回,检测结果 JSON 文件下载路径
region_countnumberphase=detect 时返回,候选区域数量,可达到数千级
videoobjectphase=detect 时返回的视频元数据:width、height、duration、fps

检测请求完成时,output_result 不包含视频文件,而是包含检测结果 JSON 文件信息:

{
  "phase": "detect",
  "regions_file_id": "537489015178249",
  "regions_download_url": "/download/a1/regions.json",
  "region_count": 2387,
  "video": {
    "width": 1920,
    "height": 1080,
    "duration": 120.0,
    "fps": 30
  }
}

成功响应示例

{
  "code": 200,
  "msg": "success",
  "data": {
    "task_id": "537489015178247",
    "status": "completed",
    "progress": 100,
    "output_result": {
      "file_id": "537489015178248",
      "download_url": "/download/a1/output.mp4"
    },
    "create_time": "2026-04-05T08:00:00Z",
    "update_time": "2026-04-05T08:01:00Z"
  }
}

错误码

错误码HTTP 状态码说明解决方案
6013400file_id 缺失传入 file_id 参数
6016400参数或区域非法,对应请求所需参数缺失,坐标越界,end 不大于 start,区域数量或请求体超过服务端资源限制,或 raft 模式视频时长超过 20 分钟检查当前请求的参数和区域对象;若大规模任务仍超过服务端资源限制,请拆分任务或缩小视频范围,并确保 raft 模式视频不超过 20 分钟
6035400视频画面短边过小:raft 模式要求画面短边 ≥128 像素(报错信息会写明当前尺寸)改用 purify_func_type: ffmpeg,或提供画面更大的源片
6014400文件类型与接口不匹配传入视频文件
6004404文件不存在检查 file_id 是否正确
6502401鉴权失败检查 Authorization 请求头
6202402余额不足前往仪表盘充值