Remove Watermark / Remove Subtitles

Remove watermarks, logos, hard subtitles, and other overlays from a video. You can process a video in one request, or detect candidate regions first and process them after the user reviews them. Both ffmpeg (region blur) and raft (content inpainting) algorithms are supported.

Before / After

subtitle Mode

Before

After

full_screen Mode

Before

After

Choose a Usage Path

The same endpoint, POST /task/video_purify, supports two usage paths. Whether the request includes phase determines which one you are using:

Usage pathHow to callWhen to useWhat you get
Option 1: One-shot processing1 request, omit phaseYou already know you want to remove subtitles, remove text across the full frame, or remove known regionsA processed video
Option 2: Detect and review2 requests: phase=detect first, then phase=purify after the user reviews in your clientThe user wants to see what the system finds, then remove false positives, adjust regions, or add new onesRequest 1 returns a candidate-region JSON file; request 2 returns a processed video

Each path has its own request parameters. Once you choose a path, refer only to the matching parameter table under "Create Task". The two requests in Option 2 create separate tasks, and each is billed by video duration.

Detect-and-Review Flow

  1. Detect: Your client sends a phase=detect request that scans the full frame, the subtitle area, or one custom area. The system returns a JSON file of candidate text regions and does not generate a video. A video can produce thousands of candidates. Detection currently finds text only; graphical logos and translucent patterns must be added manually by the user.
  2. Review: Your client displays the candidates and lets the user build a final list:
    • Remove a false positive: leave it out of the list. If it overlaps another retained region, also add a protection region for it; otherwise the overlapping part is still processed.
    • Adjust position, size, or time: change the region's coordinates, width and height, or start / end.
    • Add a region: draw a box manually (source=manual). Everything inside it is removed during the specified time range.
    • Protect content: add anything that must not be changed to the protection list, protect_regions.
  3. Process: Your client submits the final list with phase=purify. The server processes only the regions in that list. It does not detect again and does not restore candidates that the user removed.

ℹ️ Note: "Client" here means a GUI that the caller develops and maintains (a web app, desktop client, or mobile app). Gitruck Cloud does not provide it. The caller implements video preview, candidate display, region editing, time adjustment, and final submission; the Gitruck Cloud API only performs detection and processing.

Create Task

Basic Information

ItemValue
Request MethodPOST
Request Path/task/video_purify
Content-Typeapplication/json
AuthenticationRaw API key in the Authorization header

Three kinds of requests share this endpoint, each with a different request body:

RequestphasePurpose
One-shot processingOmittedOption 1: generate a processed video directly
DetectiondetectOption 2, step 1: return candidate regions only
Final-list processingpurifyOption 2, step 2: generate a processed video from the final list; can also be called directly, without detection, when the coordinates are already known

💡 Tip: Each request reads only the fields in its own parameter table. Other fields are ignored and do not change how the video is processed. For example, if phase is omitted and purify_scope=subtitle, only subtitles are removed even if regions is also supplied.

Input Video Requirements

The input video is checked before the task is created. If a requirement is not met, the request returns an error code; no task is created and nothing is charged:

ItemRequirementError code if not met
DurationNo longer than 2 hours; no longer than 20 minutes with the raft algorithm6019; 6016 when a raft video is longer than 20 minutes
ResolutionWidth and height are both 4000 px or less. Common 3840×2160 video is accepted; 4096×2160 exceeds the limit. With the raft algorithm, the shorter side must be at least 128 px6022; 6035 when the shorter side is too small for raft
Frame rate120 fps or less6023
File integrityThe file can be parsed and decoded6017 / 6021

The two raft limits are checked only when the video is actually processed. Detection requests and empty-list processing are not affected.

One-Shot Processing

Omit phase. purify_scope selects the processing mode.

Request Parameters

ParameterTypeRequiredDefaultDescription
file_idstringYes-Uploaded video file ID
purify_scopestringNofull_screenProcessing mode: full_screen / subtitle / custom / region; see the table below
roisarrayYes when purify_scope=custom-One or more recognition areas. See "Region Object" for the item structure; id and source are not needed here, and start / end may be omitted. Text is recognized and removed only inside these areas; the rest of the frame is left untouched
regionsarrayYes when purify_scope=region-Regions to remove directly. See "Region Object" for the item structure; id and source are not needed here, and start / end may be omitted
purify_func_typestringNoffmpegProcessing algorithm: ffmpeg blurs the region and is faster; raft inpaints the content, supports videos up to 20 minutes, and cannot guarantee recovery of the original scene

Processing Modes

purify_scopeBehaviorRequired parameter
full_screenRecognizes and removes text across the full frame-
subtitleRecognizes and removes text in the subtitle area only-
customRecognizes and removes text only inside the one or more areas in rois, each optionally limited to a time range; everything else inside the areas and the rest of the frame stay as isrois
regionNo recognition: everything inside each regions box is processed, including the main subject, optionally within a time range. Use it for graphic logos, translucent patterns, or stylized lettering that cannot be recognized, and for badges that appear only during part of the videoregions

💡 Tip: In region mode, smaller boxes that fit the element tightly give better results. Box edges get a soft transition of a few pixels.

💡 Tip: In custom mode, multiple areas are detected in one pass and billed once by video duration. When text crosses an area's edge, only the part inside the area is processed. Areas that fit the text closely give better results.

Request Examples

subtitle mode (remove subtitles):

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 mode (remove text in the bottom 20% of the frame for the whole video, and the title in the top-left corner for the first 10 seconds only):

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",
    "rois": [
      {"x": 0.0, "y": 0.78, "w": 1.0, "h": 0.2},
      {"x": 0.02, "y": 0.02, "w": 0.3, "h": 0.1, "start": 0, "end": 10}
    ]
  }'

region mode (remove the top-right badge for the first 5 seconds, and a bottom area from 120 seconds to the end):

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}
    ]
  }'

Detection

Option 2, step 1. Returns candidate regions only and does not generate a video. Billed by video duration.

Request Parameters

ParameterTypeRequiredDefaultDescription
file_idstringYes-Uploaded video file ID
phasestringYes-Must be detect
detect_scopestringNofull_screenDetection scope: full_screen (full frame) / subtitle (subtitle area) / custom (area set by detect_roi)
detect_roiobjectYes when detect_scope=custom-Detection area {"x","y","w","h"}, with the same value rules as x, y, w, h in "Region Object"

Detection requests do not need purify_func_type; choose the algorithm in step 2.

Request Examples

Full-frame detection:

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"
  }'

Detect only in the bottom 25% of the frame:

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}
  }'

When the task completes, get the detection file's download path from "Query Task Result". See "Detection Result File" for its structure.

Final-List Processing

Option 2, step 2. Submits the user-approved final list and generates a processed video. When you already know the coordinates and need protection regions, you can also call it directly without detection.

Request Parameters

ParameterTypeRequiredDefaultDescription
file_idstringYes-Uploaded video file ID
phasestringYes-Must be purify
regionsarrayYes-Final removal list. See "Region Object" for the item structure; every field is required. May be an empty array, meaning nothing is processed
protect_regionsarrayNo[]Protection list with the same structure as regions; protection wins where it overlaps a removal region
source_file_idstringNo-source.file_id from the detection file. When provided, it must equal file_id; this prevents submitting one video's detection result for another video
purify_func_typestringNoffmpegProcessing algorithm; same as in "One-Shot Processing"

Processing Rules

  • The effective treatment area is the union of all removal regions minus the union of all protection regions. Removing one candidate does not cancel other removal regions that overlap it; add a protection region for content that must stay.
  • The server processes only the submitted list. It does not detect again and does not restore candidates that the user removed.
  • If regions is an empty array, the server copies the source file without transcoding or running repair. The task is still billed by video duration, and the query result has unchanged set to true.
  • Thousands of regions can be submitted. A task that exceeds server resource limits such as video duration, resolution, or request size returns 6016.
  • Protection regions, exact-bound processing, and empty-list copies require server protocol version 2. Confirm it first with "Check Protocol Capabilities".

Request Examples

Submit the reviewed list (keep one detected region and add one manual region):

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": "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}
    ]
  }'

Skip detection: remove a known corner badge and protect overlapping text (adjust the example coordinates for the actual video):

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": "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}
    ]
  }'

Region Object

Each item in regions, rois, and protect_regions is a region object. One-shot processing and final-list processing require different fields:

FieldTypeOne-shot (region / custom mode)Final-list processingDescription
idstringNot usedRequiredUnique region ID within one list. Detected regions come with IDs such as det-000001; generate your own for regions added in the client
sourcestringNot usedRequireddetected (from detection) or manual (added by the user)
x, ynumberRequiredRequiredTop-left corner in normalized frame coordinates (0-1)
w, hnumberRequiredRequiredWidth and height in normalized frame coordinates (0-1); must be greater than 0, with x+w≤1 and y+h≤1
startnumberOptional, default 0RequiredStart time in seconds from the beginning of the video; must be ≥0 and less than the video duration
endnumberOptional, default end of videoRequiredEnd time in seconds; must be greater than start. Values past the video duration are treated as the end of the video
  • Coordinates are relative to the displayed, rotation-corrected frame, as seen in a player.
  • Time ranges are half-open: [start, end).
  • Regions may overlap. The server merges masks internally but does not modify the submitted list.
  • In final-list processing, changes are written only inside the regions, and soft edge transitions do not enter protection regions. Lossy video encoding may still slightly change nearby pixels, so pixel-exact output is not guaranteed. Variable-frame-rate (VFR) sources are output at a constant frame rate (CFR).

Detection Result File

When a detection task completes, download the file from output_result.regions_download_url. It has this structure:

{
  "version": 1,
  "source": {"file_id": "537489015178246"},
  "video": {
    "width": 1920,
    "height": 1080,
    "duration": 120.0,
    "fps": 30,
    "fps_exact": "30/1"
  },
  "regions": [
    {"id": "det-000001", "source": "detected", "x": 0.7, "y": 0.04, "w": 0.22, "h": 0.09, "start": 0.0, "end": 5.2, "score": 0.9132}
  ]
}
FieldDescription
versionFile format version, currently 1
source.file_idFile ID of the detected video; use it as source_file_id in final-list processing
videoVideo width, height, duration (seconds), and frame rate; fps_exact is the exact rational frame rate, such as 30000/1001
regionsCandidate regions, possibly thousands. Each item already contains every field required for final-list processing and can be submitted as regions after editing. Each item also has score (0-1): how confident the detector is that the area is text; higher means more text-like

Use score to filter out false detections, for example by showing only candidates whose score is at or above a threshold you choose per video. Real text such as subtitles and titles also scores high, so score tells you how text-like an area is; deciding which text to remove is still up to the user. In rare cases no confidence is available and a candidate has no score; treat it as unscored. Detection results do not include recognized text.

Success Example

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

Query Task Result

Basic Information

ItemValue
Request MethodGET
Request Path/task/video_purify/{task_id}
AuthenticationRaw API key in the Authorization header

Output Result (output_result)

Detection tasks and processing tasks return different fields:

ParameterTypeDescription
phasestringdetect or purify for tasks created with phase; not returned for one-shot tasks
file_idstringProcessing tasks: processed video file ID
download_urlstringProcessing tasks: download path for the processed video
unchangedbooleantrue when final-list processing received an empty regions array, meaning the output is a copy of the source
regions_file_idstringDetection tasks: JSON file ID for the detection results
regions_download_urlstringDetection tasks: download path for the detection results
region_countnumberDetection tasks: number of candidate regions, which may be in the thousands
videoobjectDetection tasks: video metadata, including width, height, duration, fps, and fps_exact

Success Examples

Processing task completed:

{
  "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"
  }
}

Detection task completed:

{
  "code": 200,
  "msg": "success",
  "data": {
    "task_id": "537489015178250",
    "status": "completed",
    "progress": 100,
    "output_result": {
      "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,
        "fps_exact": "30/1"
      }
    },
    "create_time": "2026-04-05T08:00:00Z",
    "update_time": "2026-04-05T08:00:40Z"
  }
}

Check Protocol Capabilities

Protection regions, exact-bound processing, and empty-list copies require server protocol version 2. Before using them, call this endpoint and confirm that data.review_protocol is 2. This authenticated request creates no task and incurs no charge.

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

Use the gtrk CLI

Agents can run the same flow with gtrk purify commands:

CommandPurpose
gtrk purify detect video.mp4 --jsonDetect and get the complete region file with a summary
gtrk purify edit regions.json --delete-id det-000001 --out final.jsonEdit the region list
gtrk purify apply final.json --jsonProcess the final list
gtrk purify run video.mp4 --detect-scope subtitle --jsonComplete everything in one step when the target scope is already clear
gtrk purify resume journal.json --jsonReuse tasks that were already submitted
  • Before submitting a processing request, the CLI checks that the server supports the required protocol capabilities.
  • If the final list is empty, the CLI returns the local source file without creating a processing task.
  • If a submission response is lost, the CLI stops and asks you to reconcile with the cloud task instead of resubmitting automatically.

Error Codes

Error CodeHTTP StatusDescriptionResolution
6013400Missing file_idPass the file_id field
6016400Invalid parameters or regions: a parameter required by the current request is missing, coordinates are out of range, end is not greater than start, region data or request size exceeds server resource limits, or the video is longer than 20 minutes in raft modeCheck the parameters against the table for the request you are sending and against "Region Object"; split or narrow a task that exceeds server resource limits; keep raft mode videos within 20 minutes
6014400File type does not match the taskUpload a video file
6004404File not foundVerify the file_id
6017400Video file cannot be parsed: the file is corrupted, malformed, or has conflicting metadata such as frame ratesRe-export the video with an editing or transcoding tool and upload it again
6019400Video duration is 0 or longer than 2 hoursTrim the video and upload it again
6021400Video integrity check failed: some positions cannot be decoded, or the end of the file is incompleteUse another source file, or re-export a complete video and upload it again
6022400Video resolution exceeds the limit: width or height is greater than 4000 pxScale the video so that width and height are both 4000 px or less, then upload it again
6023400Video frame rate exceeds 120 fpsConvert the video to 120 fps or less (such as 60 fps) and upload it again
6035400Video frame too small: raft mode requires the shorter side to be at least 128 px (the error message states the current size)Switch to purify_func_type: ffmpeg, or provide a larger source video
6502401Authentication failedCheck the Authorization header
6202402Insufficient balanceRecharge in the Dashboard