Add Watermark Sticker to Video

Description

This API adds a watermark sticker to a video in the cloud.

Version

1.0

Media Requirements

Video requirements:

  • Format: MP4
  • Size: Less than 3 GB

Sticker requirements:

  • Formats: JPG, PNG, GIF
  • Size: Less than 10 MB

API URL

    Production environment: https://openapi.meitu.com
    Task submission endpoint: https://openapi.meitu.com/api/v1/sdk/sync/push
    Task name (task): /v1/Video_watermark_sticker/487154
    Task type (task_type): formula

Method

POST

Content-Type: application/json

Authentication

Open Platform API Signature

Credits cannot be used to pay for API calls. Please visit the MV console to activate this API and purchase or manage resource packages.

Request Parameters

RequiredParameterTypeDescription
YesparamsstringAlgorithm parameters (JSON string)
Yesinit_imagesobject[]Media file list; the first item is the video, and the second item is the watermark sticker
YestaskstringFixed value: /v1/Video_watermark_sticker/487154
Yestask_typestringFixed value: formula
Nosync_timeoutintDefaults to 30; synchronous timeout duration

The structure of each media file in init_images is as follows:

RequiredParameterTypeDescription
YesurlstringURL or base64 data of the video or watermark sticker
YesprofileobjectMedia attribute information

The structure of profile is as follows:

RequiredParameterTypeDescription
Yesmedia_profilesobjectMedia properties
YesversionstringFixed value: v1

The structure of media_profiles is as follows:

RequiredParameterTypeDescription
Yesmedia_data_typestringurl indicates a URL; the corresponding media type indicates base64 data

The params inference parameter is a JSON string with the following structure:

RequiredFieldTypeDescription
Norsp_media_typestringDefaults to url; jpg indicates base64 data
YesparameterobjectCore algorithm parameters

Details of the parameter object:

RequiredParameterTypeDescription
YeswatermarkobjectWatermark sticker parameters

Details of the watermark object:

RequiredParameterTypeDescription
YesgravitystringWatermark type; sticker indicates a sticker watermark
NoopacityfloatWatermark opacity, ranging from 0 to 1
NooffsetxintWatermark offset along the X-axis, in pixels
NooffsetyintWatermark offset along the Y-axis, in pixels
Nosticker_croppedbooleanWhether to crop the watermark sticker; defaults to false

Request Example

{
  "task": "/v1/Video_watermark_sticker/487154",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/demo.mp4",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    },
    {
      "url": "https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/logo.gif",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    }
  ],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"watermark\":{\"gravity\":\"sticker\",\"opacity\":1,\"offsetx\":50,\"offsety\":10,\"sticker_cropped\":false}}}",
  "sync_timeout": 30
}

Response Fields

Generated results are periodically deleted. Download and save them promptly.
FieldTypeDescription
request_idstringRequest identifier
trace_idstringTrace identifier
codeintBusiness status code; 0 indicates that the request was accepted successfully
error_codeintError code; 0 indicates success
messagestringBusiness message
tipsanyAdditional information; may be null
dataobjectTask status and algorithm result

Fields in data:

FieldTypeDescription
statusintStatus code: -1, task not found; 0, created; 1, processing; 2, failed; 9, timed out—use the query API; 10, succeeded
resultobjectAlgorithm result
progressnumberTask progress, ranging from 0 to 1
predict_elapsedintEstimated processing time, in milliseconds
create_timeint64Task creation timestamp, in milliseconds
task_idstringTask ID
custom_task_idstringClient-defined task ID
trace_idstringTrace identifier within data
client_infostringClient information
init_imagesobject[]/nullEchoed input media

Fields in result:

FieldTypeDescription
idstringUnique task identifier
urlsarrayList of output media URLs
imagesarrayList of output media; equivalent to urls
parametersobjectOutput parameter information
dataobjectDetailed algorithm response data
msgstringResponse message
msg_idstringMessage ID
mtlab_resobjectUnderlying algorithm response
media_info_listarrayList of output media information

Fields in result.parameters:

FieldTypeDescription
rsp_media_typestringResponse media type; url indicates a URL

Fields in result.data:

FieldTypeDescription
durationobjectProcessing time statistics for each stage
error_codeintAlgorithm error code; 0 indicates success
error_msgstringAlgorithm error message
extraobjectAdditional fields
media_info_listarrayList of media information
msg_idstringMessage ID
parameterobjectEchoed parameters

Fields in duration:

FieldTypeDescription
alg_process_timenumberAlgorithm processing time, in milliseconds
created_timestampnumberTask creation timestamp, in seconds
pull_timestampnumberResource retrieval timestamp, in seconds
repost_timenumberRetry time
upload_timenumberUpload time, in milliseconds
waiting_timenumberQueue waiting time, in milliseconds

Fields in media_info_list:

FieldTypeDescription
media_datastringMedia data URL
media_extraobjectAdditional media information
media_profilesobjectMedia properties

Fields in media_profiles:

FieldTypeDescription
media_data_typestringMedia data type; url indicates that the media data is a URL

Fields in mtlab_res:

FieldTypeDescription
ErrorCodeintUnderlying error code
ErrorMsgstringUnderlying error message
error_codeintError code (compatibility field)
error_msgstringError message (compatibility field)
media_info_listarrayList of media information
msg_idstringMessage ID
parameterobjectParameter information

API-specific error codes and messages:

ErrorCodeError MessageDescription
20001PROCESS_ERRORProcessing error
21105INVALID_NUMBER_OF_PARAMETERSIncorrect number of parameters
21202INPUT_FILE_DOWNLOAD_FAILEDFailed to download the input file
21205VIDEO_FILE_NOT_FOUNDVideo file not found
21206WATERMARK_FILE_NOT_FOUNDWatermark file not found
21207INVALID_OR_UNSUPPORTED_INPUT_VIDEOInvalid or unsupported input video
21208INVALID_OR_UNSUPPORTED_WATERMARK_IMAGEInvalid or unsupported watermark image
22202INVALID_OUTPUT_VIDEO_LINKInvalid output video link
25201INPUT_FILE_EXCEEDS_MAX_SIZEInput file exceeds the maximum size
29001VIDEO_PROCESSING_ERRORVideo processing error
29002INVALID_WATERMARK_OPACITYInvalid watermark opacity
29003INVALID_WATERMARK_SCALE_FACTORInvalid watermark scale factor
29004INVALID_WATERMARK_POSITIONInvalid watermark position
29005INVALID_OR_UNSUPPORTED_VIDEO_CODECInvalid or unsupported video codec
29006INVALID_VIDEO_CODEC_PRESETInvalid video codec preset
29007INVALID_STICKER_CROPPINGInvalid sticker cropping option
29008INVALID_STICKER_HORIZONTAL_OFFSETInvalid horizontal sticker offset
29009INVALID_STICKER_VERTICAL_OFFSETInvalid vertical sticker offset

Response Examples

Successful Response Example

{
  "request_id": "",
  "trace_id": "",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 10,
    "result": {
      "id": "t_mt1a3i5n7be056d8cb-xxxx-4db4-b057-4ac1e397bf97",
      "urls": [
        "https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/d19663bc-2f09-4d08-4c12-76ba9d9dd7b6.mp4"
      ],
      "parameters": {
        "rsp_media_type": "url"
      },
      "data": {
        "duration": {
          "alg_process_time": 112500,
          "created_timestamp": 1770276512,
          "pull_timestamp": 1770276512,
          "repost_time": 0,
          "upload_time": 207,
          "waiting_time": 57
        },
        "error_code": 0,
        "error_msg": "success",
        "extra": {},
        "media_info_list": [
          {
            "media_data": "https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/d19663bc-2f09-4d08-4c12-76ba9d9dd7b6.mp4",
            "media_extra": null,
            "media_profiles": {
              "media_data_type": "url"
            }
          }
        ],
        "msg_id": "88633f1f-xxxx-4a19-6a91-r0099cf15af6",
        "parameter": {
          "rsp_media_type": "url"
        }
      },
      "msg": "success",
      "msg_id": "88633f1f-xxxx-4a19-6a91-r0099cf15af6",
      "images": [
        "https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/d19663bc-2f09-4d08-4c12-76ba9d9dd7b6.mp4"
      ],
      "mtlab_res": {
        "ErrorCode": 0,
        "ErrorMsg": "",
        "error_code": 0,
        "error_msg": "",
        "media_info_list": null,
        "msg_id": "88633f1f-xxxx-4a19-6a91-r0099cf15af6",
        "parameter": null
      },
      "media_info_list": [
        {
          "media_data": "https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/d19663bc-2f09-4d08-4c12-76ba9d9dd7b6.mp4",
          "media_extra": null,
          "media_profiles": {
            "media_data_type": "url"
          }
        }
      ]
    },
    "progress": 1,
    "predict_elapsed": 10000,
    "create_time": 1770276512525,
    "task_id": "t_mt1a3i5n7be056d8cb-xxxx-4db4-b057-4ac1e397bf97",
    "custom_task_id": "",
    "trace_id": "",
    "client_info": "",
    "init_images": null
  }
}

Query Required Response Example

Use the query API to retrieve the result.

Response Status: 200

content-type: application/json; charset=utf-8

{
  "request_id": "",
  "trace_id": "",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 9,
    "result": {
      "id": "t_mt1a3i5n7be056d8cb-xxxx-4db4-b057-4ac1e397bf97"
    },
    "progress": 0,
    "predict_elapsed": 10000,
    "create_time": 1770276512525,
    "task_id": "t_mt1a3i5n7be056d8cb-xxxx-4db4-b057-4ac1e397bf97",
    "custom_task_id": "",
    "trace_id": "ec2460cf-xxxx-48ed-9a97-32596617c779",
    "client_info": "",
    "init_images": null
  }
}

Failed Response Example

Response Status: 400

content-type: application/json; charset=utf-8

{
  "request_id": "",
  "trace_id": "",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 2,
    "result": {
      "error_code": 20001,
      "error_msg": "PROCESS_ERROR"
    },
    "progress": 0,
    "predict_elapsed": 0,
    "create_time": 1770276512525,
    "task_id": "t_mt1a3i5n7be056d8cb-xxxx-4db4-b057-4ac1e397bf97",
    "custom_task_id": "",
    "trace_id": "ec2460cf-xxxx-48ed-9a97-32596617c779",
    "client_info": "",
    "init_images": null
  }
}

General Error Codes

See API Error Codes.

SDK Examples

Python

import json

import requests
from sign_sdk import sign

def api_call_example():
    key = "your_api_key"
    secret = "your_api_secret"
    url = "https://openapi.meitu.com/api/v1/sdk/sync/push"
    method = "POST"

    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }
    inner_params = {
        "rsp_media_type": "url",
        "parameter": {
            "watermark": {
                "gravity": "sticker",
                "opacity": 1,
                "offsetx": 50,
                "offsety": 10,
                "sticker_cropped": False,
            }
        },
    }
    payload = {
        "task": "/v1/Video_watermark_sticker/487154",
        "task_type": "formula",
        "init_images": [
            {
                "url": "https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/demo.mp4",
                "profile": {
                    "media_profiles": {"media_data_type": "url"},
                    "version": "v1",
                },
            },
            {
                "url": "https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/logo.gif",
                "profile": {
                    "media_profiles": {"media_data_type": "url"},
                    "version": "v1",
                },
            },
        ],
        "params": json.dumps(inner_params, ensure_ascii=False),
        "sync_timeout": 30,
    }
    body = json.dumps(payload, ensure_ascii=False)

    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, method, headers, body)
    response = requests.Session().send(signed_request)
    print(f"Status: {response.status_code}")
    print(f"Response: {response.text}")

if __name__ == "__main__":
    api_call_example()

Go

package main

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

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

func main() {
	key := "your_api_key"
	secret := "your_api_secret"
	signObj := signer.NewSigner(key, secret)

	url := "https://openapi.meitu.com/api/v1/sdk/sync/push"
	method := http.MethodPost
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")

	body := `{
  "task": "/v1/Video_watermark_sticker/487154",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/demo.mp4",
      "profile": {
        "media_profiles": {"media_data_type": "url"},
        "version": "v1"
      }
    },
    {
      "url": "https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/logo.gif",
      "profile": {
        "media_profiles": {"media_data_type": "url"},
        "version": "v1"
      }
    }
  ],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"watermark\":{\"gravity\":\"sticker\",\"opacity\":1,\"offsetx\":50,\"offsety\":10,\"sticker_cropped\":false}}}",
  "sync_timeout": 30
}`

	req, err := signObj.Sign(url, method, headers, body)
	if err != nil {
		fmt.Println("Failed to sign request:", err)
		return
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Read response failed:", err)
		return
	}
	fmt.Println("Response:", resp.StatusCode, string(responseBody))
}

PHP

<?php
require 'signer.php';

$key = 'your_api_key';
$secret = 'your_api_secret';
$signer = new Signer($key, $secret);

$url = 'https://openapi.meitu.com/api/v1/sdk/sync/push';
$method = 'POST';
$headers = ['Content-Type' => 'application/json'];

$innerParams = json_encode([
    'rsp_media_type' => 'url',
    'parameter' => [
        'watermark' => [
            'gravity' => 'sticker',
            'opacity' => 1,
            'offsetx' => 50,
            'offsety' => 10,
            'sticker_cropped' => false,
        ],
    ],
]);

$body = json_encode([
    'task' => '/v1/Video_watermark_sticker/487154',
    'task_type' => 'formula',
    'init_images' => [
        [
            'url' => 'https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/demo.mp4',
            'profile' => [
                'media_profiles' => ['media_data_type' => 'url'],
                'version' => 'v1',
            ],
        ],
        [
            'url' => 'https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/logo.gif',
            'profile' => [
                'media_profiles' => ['media_data_type' => 'url'],
                'version' => 'v1',
            ],
        ],
    ],
    'params' => $innerParams,
    'sync_timeout' => 30,
]);

$curl = $signer->sign($url, $method, $headers, $body);
$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

if ($status === 0) {
    echo 'Error: ' . curl_error($curl);
} else {
    echo "Status: {$status}\n";
    echo "Response: {$response}\n";
}
curl_close($curl);
?>

Java

package com.meitu.openai.common;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
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 {
        Signer signer = new Signer("your_api_key", "your_api_secret");
        String url = "https://openapi.meitu.com/api/v1/sdk/sync/push";
        String method = "POST";

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");

        String body = "{\n" +
                "  \"task\": \"/v1/Video_watermark_sticker/487154\",\n" +
                "  \"task_type\": \"formula\",\n" +
                "  \"init_images\": [\n" +
                "    {\n" +
                "      \"url\": \"https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/demo.mp4\",\n" +
                "      \"profile\": {\n" +
                "        \"media_profiles\": {\"media_data_type\": \"url\"},\n" +
                "        \"version\": \"v1\"\n" +
                "      }\n" +
                "    },\n" +
                "    {\n" +
                "      \"url\": \"https://meitu-commons-test.obs.cn-north-4.myhuaweicloud.com/faas/demo/logo.gif\",\n" +
                "      \"profile\": {\n" +
                "        \"media_profiles\": {\"media_data_type\": \"url\"},\n" +
                "        \"version\": \"v1\"\n" +
                "      }\n" +
                "    }\n" +
                "  ],\n" +
                "  \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"watermark\\\":{\\\"gravity\\\":\\\"sticker\\\",\\\"opacity\\\":1,\\\"offsetx\\\":50,\\\"offsety\\\":10,\\\"sticker_cropped\\\":false}}}\",\n" +
                "  \"sync_timeout\": 30\n" +
                "}";

        Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        connection.setRequestMethod(method);
        for (Map.Entry<String, String> entry : signedHeaders.entrySet()) {
            connection.setRequestProperty(entry.getKey(), entry.getValue());
        }
        connection.setDoOutput(true);
        connection.getOutputStream().write(body.getBytes(StandardCharsets.UTF_8));

        int status = connection.getResponseCode();
        InputStream stream = status >= 400
                ? connection.getErrorStream()
                : connection.getInputStream();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            System.out.println("Response: " + status + " " + response);
        }
    }
}