Remove subtitles and watermarks in one click

Description

Submit a video for one-click cleanup. Processing is asynchronous.

Version

1.0

Video Requirements

Only video input by URL is supported. The source does not specify codec, file size, resolution, or duration limits.

Request URL

Task submission endpoint:

https://openapi.meitu.com/api/v1/sdk/sync/push

Task name (task): /v1/Video_Remove/496462

Task type (task_type): formula

HTTP Method

POST

Content-Type: application/json

Authentication

Use an AK/SK pair with access to this capability and sign requests with the signing SDK. See API Request Signing.

Request Parameters

RequiredParameterTypeDescription
YestaskstringFixed value: /v1/Video_Remove/496462.
Yestask_typestringFixed value: formula.
Yesinit_imagesobject[]Input videos. The API field name remains init_images.
YesparamsstringA JSON-serialized string containing the algorithm parameters.
Nosync_timeoutintegerSynchronous waiting period in seconds. Default: 30.

init_images Element

RequiredParameterTypeDescription
YesurlstringInput video URL. Do not Base64-encode it.
YesprofileobjectVideo properties.

profile

RequiredParameterTypeDescription
YesversionstringGateway media configuration version. Fixed value: v1.
Yesmedia_profilesobjectVideo transfer and processing properties.

media_profiles

RequiredParameterTypeDescription
Yesmedia_data_typestringurl is used as in the source request example, indicating a video URL.
Noskip_framesarray[a,b]: skip a frames at the beginning and b frames at the end, for slicing. Default: [0,0].
Noencoder_rate_scalenumberVideo encoding bitrate scaling factor. The source specifies no default or range.

params

params must be a JSON string. The decoded object contains:

RequiredParameterTypeDescription
YesparameterobjectVideo cleanup parameters.
NoextraobjectAdditional processing information in the algorithm protocol. Omit when not needed.

parameter

RequiredParameterTypeDescription
NouserboxesstringUser interaction box coordinates as a string. Each box has four relative coordinate points in this order: top-left, top-right, bottom-right, bottom-left. No boxes by default.
NoprotectboxesstringProtected-region box coordinates as a string, in the same point order as userboxes. No boxes by default.

Example string value for one box:

[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]

When specifying boxes, the decoded params object can be structured as follows. userboxes and protectboxes remain strings, not arrays:

{
  "parameter": {
    "userboxes": "[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]",
    "protectboxes": "[[0.6,0.6],[0.8,0.6],[0.8,0.8],[0.6,0.8]]"
  }
}

The source allows multiple boxes but does not define how they are grouped, so no multi-box example is provided. Its input media type table uses MP4, inconsistent with url in its request example. Video input here follows the source example's URL-based approach.

Request Example

This example specifies one interaction box through userboxes, with no protected region. Replace the video URL and box coordinates as needed.

{
  "task": "/v1/Video_Remove/496462",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://example.com/input.mp4",
      "profile": {
        "media_profiles": {
          "media_data_type": "url",
          "skip_frames": [
            0,
            0
          ]
        },
        "version": "v1"
      }
    }
  ],
  "params": "{\"parameter\":{\"userboxes\":\"[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]\"}}",
  "sync_timeout": 30
}

Response Fields

The descriptions below use the common gateway task wrapper. The exact result nesting for this task has not been verified against a response sample. Algorithm fields explicitly documented in the source are listed separately below.

FieldTypeDescription
codeintegerGateway business status code. 0 indicates normal request processing, not necessarily task completion.
messagestringGateway response message.
dataobjectTask status and result.
data.task_idstringGateway task ID for Task Query.
data.statusintegerTask status; see below.
data.resultobjectResult wrapper. The structural examples below place algorithm output in data.result.data.
data.statusDescription
-1Task not found.
0Task created.
1Running.
2Failed.
9Synchronous wait timed out. Continue querying; this does not mean the algorithm failed.
10Succeeded.

result

FieldTypeDescription
idstringGateway task identifier.
codeintegerAlgorithm status code.
msgstringAlgorithm response message.
msg_idstringAlgorithm request identifier; not a substitute for the gateway task_id.
dataobjectOriginal algorithm response.

Algorithm Result Fields

FieldTypeDescription
msg_idstringAlgorithm request identifier. The source states that this identifier and algorithm results are deleted after 24 hours.
media_info_listobject[]Processing results.
media_info_list[].media_datastringResult media data; a video URL in the URL-based structural example.
media_info_list[].media_profilesobjectResult media properties.
parameterobjectOutput type, algorithm version, and removal status.
parameter.rsp_media_typestringOutput delivery type; url in the structural example.
parameter.versionstringAlgorithm version.
parameter.exist_textbooleanWhether removal was performed on the video. No removal is performed if no content to remove is detected.
error_codeintegerAlgorithm error code in the source error response.
error_msgstringAlgorithm error message in the source error response.

The source response field descriptions still refer to jpg / Base64 and provide no complete successful video response JSON. These descriptions are not treated as confirmation of Base64 video output support.

Use data.task_id, not the algorithm msg_id, for gateway queries. Query and save results promptly. The source's 24-hour statement applies to algorithm identifiers and results, not a confirmed gateway retention policy for this task.

Response Examples

These structural examples combine the common gateway template with algorithm fields from the source. They are not records of real API calls. The actual response for this task determines the field nesting, values, and error messages.

Success Structure Example

{
  "code": 0,
  "message": "success",
  "data": {
    "status": 10,
    "task_id": "example-task-id",
    "result": {
      "id": "example-task-id",
      "code": 0,
      "msg": "success",
      "msg_id": "example-message-id",
      "data": {
        "msg_id": "example-message-id",
        "media_info_list": [
          {
            "media_data": "https://example.com/result.mp4",
            "media_profiles": {
              "media_data_type": "url"
            }
          }
        ],
        "parameter": {
          "rsp_media_type": "url",
          "version": "1.0",
          "exist_text": true
        }
      }
    }
  }
}

Query Required Structure Example

If data.status = 9, use data.task_id with Task Query. Do not resubmit merely because the synchronous wait timed out.

{
  "code": 0,
  "message": "success",
  "data": {
    "status": 9,
    "task_id": "example-task-id",
    "result": {
      "id": "example-task-id"
    }
  }
}

Error Structure Example

The example uses 20001 / ALGO_MODEL_CRASH to illustrate an error structure. It does not mean that every failure returns this error.

{
  "code": 20001,
  "message": "ALGO_MODEL_CRASH",
  "data": {
    "status": 2,
    "task_id": "example-task-id",
    "result": {
      "id": "example-task-id",
      "code": 20001,
      "msg": "ALGO_MODEL_CRASH",
      "msg_id": "example-message-id",
      "data": {
        "error_code": 20001,
        "error_msg": "ALGO_MODEL_CRASH",
        "msg_id": "example-message-id"
      }
    }
  }
}

Common Error Codes

See API Error Codes.

SDK Examples

Each example embeds the complete request body and requires no separate JSON file. Set up the SDK for your language and replace the AK, SK, and video URL.

The examples submit once and print the response. If the task has not completed, retrieve its result using Task Query.

Python

Python Signing SDK

import json

import requests
from sign_sdk import sign

def main():
    key = "YOUR_ACCESS_KEY"
    secret = "YOUR_SECRET_KEY"
    url = "https://openapi.meitu.com/api/v1/sdk/sync/push"
    params = {
        "parameter": {
            "userboxes": "[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]"
        }
    }
    payload = {
        "task": "/v1/Video_Remove/496462",
        "task_type": "formula",
        "init_images": [
            {
                "url": "https://example.com/input.mp4",
                "profile": {
                    "media_profiles": {
                        "media_data_type": "url",
                        "skip_frames": [
                            0,
                            0
                        ]
                    },
                    "version": "v1"
                }
            }
        ],
        "params": json.dumps(params, ensure_ascii=True),
        "sync_timeout": 30
    }
    body = json.dumps(payload, ensure_ascii=True)
    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }
    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, "POST", headers, body)
    with requests.Session() as session:
        response = session.send(
            signed_request, timeout=(10, 60), verify=True, allow_redirects=False
        )
        print("Status:", response.status_code)
        print("Response:", response.text)

if __name__ == "__main__":
    main()

Go

Go Signing SDK

package main

import (
    "fmt"
    "io"
    "net/http"
    "time"

    "github.com/mtlab/api/signer"
)

func main() {
    body := `{
  "task": "/v1/Video_Remove/496462",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://example.com/input.mp4",
      "profile": {
        "media_profiles": {
          "media_data_type": "url",
          "skip_frames": [
            0,
            0
          ]
        },
        "version": "v1"
      }
    }
  ],
  "params": "{\"parameter\":{\"userboxes\":\"[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]\"}}",
  "sync_timeout": 30
}`
    url := "https://openapi.meitu.com/api/v1/sdk/sync/push"
    headers := make(http.Header)
    headers.Set("Content-Type", "application/json")
    headers.Set(signer.HeaderHost, "openapi.meitu.com")
    signObj := signer.NewSigner("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY")
    req, err := signObj.Sign(url, http.MethodPost, headers, body)
    if err != nil {
        fmt.Println("Sign request failed:", err)
        return
    }
    client := &http.Client{
        Timeout: 60 * time.Second,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            return http.ErrUseLastResponse
        },
    }
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Send request failed:", err)
        return
    }
    defer resp.Body.Close()
    responseBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Read response failed:", err)
        return
    }
    fmt.Println("Status:", resp.StatusCode)
    fmt.Println("Response:", string(responseBody))
}

PHP

PHP Signing SDK

<?php
require_once __DIR__ . '/signer.php';

$params = json_encode([
    'parameter' => [
        'userboxes' => '[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]',
    ],
]);
$body = json_encode([
    'task' => '/v1/Video_Remove/496462',
    'task_type' => 'formula',
    'init_images' => [
        [
            'url' => 'https://example.com/input.mp4',
            'profile' => [
                'media_profiles' => [
                    'media_data_type' => 'url',
                    'skip_frames' => [0, 0],
                ],
                'version' => 'v1',
            ],
        ],
    ],
    'params' => $params,
    'sync_timeout' => 30,
], JSON_UNESCAPED_SLASHES);
$url = 'https://openapi.meitu.com/api/v1/sdk/sync/push';
$headers = [
    'Content-Type' => 'application/json',
    'Host' => 'openapi.meitu.com',
];
$signer = new Signer('YOUR_ACCESS_KEY', 'YOUR_SECRET_KEY');
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
$response = curl_exec($curl);
if ($response === false) {
    echo 'Error: ' . curl_error($curl) . PHP_EOL;
} else {
    echo 'Status: ' . curl_getinfo($curl, CURLINFO_HTTP_CODE) . PHP_EOL;
    echo 'Response: ' . $response . PHP_EOL;
}
curl_close($curl);

Java

Java Signing SDK

import com.meitu.openai.common.Signer;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        String body =
                "{\n" +
                "  \"task\": \"/v1/Video_Remove/496462\",\n" +
                "  \"task_type\": \"formula\",\n" +
                "  \"init_images\": [\n" +
                "    {\n" +
                "      \"url\": \"https://example.com/input.mp4\",\n" +
                "      \"profile\": {\n" +
                "        \"media_profiles\": {\n" +
                "          \"media_data_type\": \"url\",\n" +
                "          \"skip_frames\": [\n" +
                "            0,\n" +
                "            0\n" +
                "          ]\n" +
                "        },\n" +
                "        \"version\": \"v1\"\n" +
                "      }\n" +
                "    }\n" +
                "  ],\n" +
                "  \"params\": \"{\\\"parameter\\\":{\\\"userboxes\\\":\\\"[[0.1,0.1],[0.2,0.1],[0.2,0.2],[0.1,0.2]]\\\"}}\",\n" +
                "  \"sync_timeout\": 30\n" +
                "}";
        String url = "https://openapi.meitu.com/api/v1/sdk/sync/push";
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");
        Signer signer = new Signer("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY");
        Map<String, String> signedHeaders = signer.sign(url, "POST", headers, body);

        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        try {
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(60000);
            connection.setInstanceFollowRedirects(false);
            connection.setDoOutput(true);
            for (Map.Entry<String, String> entry : signedHeaders.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
            byte[] bodyBytes = body.getBytes(StandardCharsets.UTF_8);
            connection.setFixedLengthStreamingMode(bodyBytes.length);
            try (OutputStream output = connection.getOutputStream()) {
                output.write(bodyBytes);
            }
            int status = connection.getResponseCode();
            System.out.println("Status: " + status);
            InputStream responseStream = status >= 400
                    ? connection.getErrorStream() : connection.getInputStream();
            if (responseStream != null) {
                try (InputStream input = responseStream;
                     ByteArrayOutputStream output = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int length;
                    while ((length = input.read(buffer)) != -1) {
                        output.write(buffer, 0, length);
                    }
                    System.out.println("Response: " + output.toString("UTF-8"));
                }
            }
        } finally {
            connection.disconnect();
        }
    }
}