1.接口说明

视频去水印 API:上传视频文件或提供视频URL,异步去除视频中的水印区域,返回处理后的结果视频URL。

1.1主要功能

智能水印去除:
自动识别视频中的水印区域并进行修复,保持画面自然。
静态/移动水印支持:
支持静态水印和移动水印的去除,通过 is_move 参数指定。
多输入方式:
支持上传视频文件(file)或提供视频URL(file_url)。

1.2接入场景

适用于短视频平台素材处理、内容二次创作、视频编辑等需要对视频进行水印去除的场景。

2.请求信息

2.1请求地址(URL)

POST http(s)://api.shiliuai.com/api/video_inpaint/v1

2.2请求方式

POST

2.3请求头(header)

参数 类型 说明
APIKEY string 您的 API KEY 获取

2.4请求体(body)

编码方式:multipart/form-data

参数 是否必填 类型 说明
异步提交任务
file 二选一必填 file 视频文件,通过 files 参数上传,与 file_url 二选一,优先使用 file
file_url string 视频文件URL,与 file 二选一,优先使用 file
is_move bool 水印是否会移动,默认为 false
异步获取结果
file_id string 提交任务返回的 file_id

3.返回信息

3.1返回类型

JSON

3.2返回信息

参数 返回类型 说明
code int 错误码
msg string 错误信息(英文)
msg_cn string 错误信息(中文)
request_id string 请求id
file_id string 视频id,可用于异步获取结果
异步模式通用
status string 任务状态,added:已加入,processing:正在处理,done:处理完成,error:错误
wait_time float 大概还需等待时间,例如:1.2(秒)
result_url string 结果视频URL,当 status 为 done 时,有该返回值,可以用该URL获取结果
video_duration float 视频时长(秒),提交任务时有该返回值(私用)

3.3返回示例

// 提交任务成功
{
  "code": 0,
  "msg": "OK",
  "msg_cn": "成功",
  "request_id": "a1b2c3d4e5f6...",
  "file_id": "f7e8d9c0b1a2...",
  "status": "added",
  "wait_time": 1.2,
  "video_duration": 15.5
}

// 轮询 - 处理完成
{
  "code": 0,
  "msg": "OK",
  "msg_cn": "成功",
  "request_id": "a1b2c3d4e5f6...",
  "file_id": "f7e8d9c0b1a2...",
  "status": "done",
  "result_url": "https://cdn.shiliuai.com/result/xxx.mp4"
}

// 失败示例
{
  "code": 4,
  "msg": "Invalid parameter: file or file_url is required",
  "msg_cn": "参数错误:file 或 file_url 必填其中之一"
}

3.4错误码

错误码 说明
0成功
1文件错误
2处理错误
3服务器繁忙
4参数错误(具体错误看 msg 或 msg_cn)
5未知错误
101API-KEY 不正确
102未知用户
103积分已用完
104扣除积分失败

4.示例代码

4.1 Python

# -*- coding: utf-8 -*-
import requests
import json
import time
import os

api_key = '******'  # 你的API KEY
file_path = '...'  # 视频路径

url = 'http(s)://api.shiliuai.com/api/video_inpaint/v1'
headers = {'APIKEY': api_key}
data = {
    "is_move": True
}

with open(file_path, "rb") as file:
    response = requests.post(url=url, headers=headers, files={"file": file}, data=data)

response = json.loads(response.content)
code = response.get('code')

if code == 0:
    file_id = response.get('file_id')
    wait_time = response.get('wait_time')

    # 轮询获取结果
    while True:
        time.sleep(wait_time)

        data = {
            "file_id": file_id
        }
        response = requests.post(url=url, headers=headers, data=data)
        response = json.loads(response.content)
        status = response.get('status')

        if status == 'done':
            # 已完成
            result_url = response.get('result_url')
            response = requests.get(url=result_url)

            if response.status_code == 200:
                result_bytes = response.content
                filename = os.path.basename(result_url)
                with open(filename, "wb") as f:
                    f.write(result_bytes)
            else:
                response = json.loads(response.content)
                print('response:', response)

            break
else:
    print('请求失败:', response.get('msg_cn', response.get('msg')))

4.2 PHP

<?php
$url = "http(s)://api.shiliuai.com/api/video_inpaint/v1";
$apikey = "******";
$header = array();
array_push($header, "APIKEY:" . $apikey);

$file_path = "...";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);

// 提交任务
$post_data = array(
    "file" => new CURLFile($file_path),
    "is_move" => true
);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);

$response = curl_exec($curl);
$response = json_decode($response, true);

if ($response['code'] == 0) {
    $file_id = $response['file_id'];
    $wait_time = isset($response['wait_time']) ? $response['wait_time'] : 1;

    // 轮询获取结果
    while (true) {
        sleep((int)$wait_time);

        $poll_data = array("file_id" => $file_id);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $poll_data);
        $response = curl_exec($curl);
        $response = json_decode($response, true);

        if (isset($response['status']) && $response['status'] === 'done') {
            $result_url = $response['result_url'];
            // 下载结果视频
            $video_content = file_get_contents($result_url);
            $filename = basename($result_url);
            file_put_contents($filename, $video_content);
            echo "视频去水印成功,已保存 " . $filename;
            break;
        }
    }
}
var_dump($response);

4.3 Java

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import org.json.JSONObject;

public class VideoInpaintApiExample {
    public static void main(String[] args) {
        String apiKey = "******";
        String filePath = "...";
        String apiUrl = "http(s)://api.shiliuai.com/api/video_inpaint/v1";

        try {
            // 提交任务(multipart/form-data)
            String boundary = "----FormBoundary" + System.currentTimeMillis();
            HttpURLConnection conn = (HttpURLConnection) new URL(apiUrl).openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("APIKEY", apiKey);
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            conn.setDoOutput(true);

            try (OutputStream os = conn.getOutputStream()) {
                // file 字段
                os.write(("--" + boundary + "\r\n").getBytes());
                os.write(("Content-Disposition: form-data; name=\"file\"; filename=\""
                        + new File(filePath).getName() + "\"\r\n").getBytes());
                os.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes());
                Files.copy(new File(filePath).toPath(), os);
                os.write(("\r\n").getBytes());
                // is_move 字段
                os.write(("--" + boundary + "\r\n").getBytes());
                os.write(("Content-Disposition: form-data; name=\"is_move\"\r\n\r\n").getBytes());
                os.write(("true\r\n").getBytes());
                os.write(("--" + boundary + "--\r\n").getBytes());
            }

            StringBuilder sb = new StringBuilder();
            try (BufferedReader br = new BufferedReader(
                    new InputStreamReader(conn.getInputStream(), "utf-8"))) {
                String line;
                while ((line = br.readLine()) != null) sb.append(line.trim());
            }
            JSONObject response = new JSONObject(sb.toString());

            if (response.getInt("code") == 0) {
                String fileId = response.getString("file_id");
                double waitTime = response.optDouble("wait_time", 1.0);

                // 轮询获取结果
                while (true) {
                    Thread.sleep((long) (waitTime * 1000));

                    conn = (HttpURLConnection) new URL(apiUrl).openConnection();
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("APIKEY", apiKey);
                    conn.setRequestProperty("Content-Type",
                            "multipart/form-data; boundary=" + boundary);
                    conn.setDoOutput(true);

                    try (OutputStream os = conn.getOutputStream()) {
                        os.write(("--" + boundary + "\r\n").getBytes());
                        os.write(("Content-Disposition: form-data; name=\"file_id\"\r\n\r\n")
                                .getBytes());
                        os.write((fileId + "\r\n").getBytes());
                        os.write(("--" + boundary + "--\r\n").getBytes());
                    }

                    sb = new StringBuilder();
                    try (BufferedReader br = new BufferedReader(
                            new InputStreamReader(conn.getInputStream(), "utf-8"))) {
                        String line;
                        while ((line = br.readLine()) != null) sb.append(line.trim());
                    }
                    response = new JSONObject(sb.toString());

                    if ("done".equals(response.optString("status"))) {
                        String resultUrl = response.getString("result_url");
                        // 下载结果视频
                        try (InputStream is = new URL(resultUrl).openStream();
                             FileOutputStream fos = new FileOutputStream(
                                     new File(resultUrl).getName())) {
                            byte[] buffer = new byte[4096];
                            int read;
                            while ((read = is.read(buffer)) != -1) {
                                fos.write(buffer, 0, read);
                            }
                        }
                        System.out.println("视频去水印成功");
                        break;
                    }
                }
            } else {
                System.out.println("请求失败: " + response.optString("msg_cn",
                        response.optString("msg")));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.4 JavaScript

const fs = require('fs');
const path = require('path');

const apiKey = '******';
const filePath = '...';
const apiUrl = 'http(s)://api.shiliuai.com/api/video_inpaint/v1';

function sleep(seconds) {
  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}

async function main() {
  // 提交任务(multipart/form-data)
  const fileContent = fs.readFileSync(filePath);
  const boundary = '----FormBoundary' + Date.now();
  const body = [
    `--${boundary}`,
    'Content-Disposition: form-data; name="file"; filename="' + path.basename(filePath) + '"',
    'Content-Type: application/octet-stream',
    '',
    fileContent,
    `--${boundary}`,
    'Content-Disposition: form-data; name="is_move"',
    '',
    'true',
    `--${boundary}--`,
  ].map(p => typeof p === 'string' ? Buffer.from(p + '\r\n', 'utf-8') : p);
  const buf = Buffer.concat(body);

  let res = await fetch(apiUrl, {
    method: 'POST',
    headers: { APIKEY: apiKey, 'Content-Type': `multipart/form-data; boundary=${boundary}` },
    body: buf
  });

  let data = await res.json();
  if (data.code !== 0) {
    console.error('请求失败:', data.msg_cn || data.msg);
    return;
  }

  const fileId = data.file_id;
  const waitTime = data.wait_time || 1;

  // 轮询获取结果
  while (true) {
    await sleep(waitTime);

    const pollBoundary = '----FormBoundary' + Date.now();
    const pollBody = [
      `--${pollBoundary}`,
      'Content-Disposition: form-data; name="file_id"',
      '',
      fileId,
      `--${pollBoundary}--`,
    ].map(p => typeof p === 'string' ? Buffer.from(p + '\r\n', 'utf-8') : p);

    res = await fetch(apiUrl, {
      method: 'POST',
      headers: { APIKEY: apiKey, 'Content-Type': `multipart/form-data; boundary=${pollBoundary}` },
      body: Buffer.concat(pollBody)
    });

    data = await res.json();
    if (data.status === 'done') {
      // 下载结果视频
      const resultUrl = data.result_url;
      const dlRes = await fetch(resultUrl);
      if (dlRes.ok) {
        const buffer = Buffer.from(await dlRes.arrayBuffer());
        const filename = path.basename(resultUrl);
        fs.writeFileSync(filename, buffer);
        console.log('视频去水印成功,已保存', filename);
      }
      break;
    }
  }
}

main().catch(console.error);

4.5 Node.js

const fs = require('fs');
const path = require('path');
const FormData = require('form-data');

const apiKey = '******';
const filePath = '...';
const apiUrl = 'http(s)://api.shiliuai.com/api/video_inpaint/v1';

function sleep(seconds) {
  return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}

async function main() {
  // 提交任务
  let form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  form.append('is_move', 'true');

  let res = await fetch(apiUrl, {
    method: 'POST',
    headers: { APIKEY: apiKey, ...form.getHeaders() },
    body: form
  });

  let data = await res.json();
  if (data.code !== 0) {
    console.error('请求失败:', data.msg_cn || data.msg);
    return;
  }

  const fileId = data.file_id;
  const waitTime = data.wait_time || 1;

  // 轮询获取结果
  while (true) {
    await sleep(waitTime);

    form = new FormData();
    form.append('file_id', fileId);

    res = await fetch(apiUrl, {
      method: 'POST',
      headers: { APIKEY: apiKey, ...form.getHeaders() },
      body: form
    });

    data = await res.json();
    if (data.status === 'done') {
      // 下载结果视频
      const resultUrl = data.result_url;
      const dlRes = await fetch(resultUrl);
      if (dlRes.ok) {
        const buffer = Buffer.from(await dlRes.arrayBuffer());
        const filename = path.basename(resultUrl);
        fs.writeFileSync(filename, buffer);
        console.log('视频去水印成功,已保存', filename);
      }
      break;
    }
  }
}

main().catch(console.error);

4.6 cURL

# 1. 提交任务
curl -k 'http(s)://api.shiliuai.com/api/video_inpaint/v1' \
  -H 'APIKEY: 你的APIKEY' \
  -F 'file=@/path/to/video.mp4' \
  -F 'is_move=true'

# 2. 轮询结果(将 file_id 替换为上一步返回的值)
curl -k 'http(s)://api.shiliuai.com/api/video_inpaint/v1' \
  -H 'APIKEY: 你的APIKEY' \
  -F 'file_id=上一步返回的file_id'

# 3. 下载结果视频(当 status 为 done 时,使用返回的 result_url)
curl -k -O 'https://cdn.shiliuai.com/result/xxx.mp4'

4.7 C#

using System;
using System.IO;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string apiKey = "******";
        string filePath = "...";
        string apiUrl = "http(s)://api.shiliuai.com/api/video_inpaint/v1";

        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Add("APIKEY", apiKey);

            // 提交任务(multipart/form-data)
            using (var content = new MultipartFormDataContent())
            {
                var fileBytes = await File.ReadAllBytesAsync(filePath);
                var fileContent = new ByteArrayContent(fileBytes);
                content.Add(fileContent, "file", Path.GetFileName(filePath));
                content.Add(new StringContent("true"), "is_move");

                var response = await client.PostAsync(apiUrl, content);
                var responseString = await response.Content.ReadAsStringAsync();
                var responseObject = JsonSerializer.Deserialize<JsonElement>(responseString);

                if (responseObject.GetProperty("code").GetInt32() == 0)
                {
                    string fileId = responseObject.GetProperty("file_id").GetString();
                    double waitTime = responseObject.TryGetProperty("wait_time", out var wt)
                        ? wt.GetDouble() : 1.0;

                    // 轮询获取结果
                    while (true)
                    {
                        await Task.Delay((int)(waitTime * 1000));

                        var pollContent = new MultipartFormDataContent();
                        pollContent.Add(new StringContent(fileId), "file_id");

                        response = await client.PostAsync(apiUrl, pollContent);
                        responseString = await response.Content.ReadAsStringAsync();
                        responseObject = JsonSerializer.Deserialize<JsonElement>(responseString);

                        if (responseObject.GetProperty("status").GetString() == "done")
                        {
                            string resultUrl = responseObject.GetProperty("result_url").GetString();
                            // 下载结果视频
                            var videoBytes = await client.GetByteArrayAsync(resultUrl);
                            string filename = Path.GetFileName(new Uri(resultUrl).LocalPath);
                            await File.WriteAllBytesAsync(filename, videoBytes);
                            Console.WriteLine("视频去水印成功,已保存 " + filename);
                            break;
                        }
                    }
                }
            }
        }
    }
}

4.8 易语言

版本 2
.支持库 spec
.支持库 dp1

.子方法 视频去水印_API_示例
.局部变量 局_网址, 文本型
.局部变量 局_提交协议头, 文本型
.局部变量 局_结果, 字节集
.局部变量 局_返回, 文本型
.局部变量 视频数据, 字节集
.局部变量 file_id, 文本型
.局部变量 wait_time, 小数型

视频数据 = 读入文件 ("你的视频路径.mp4")
局_网址 = "http(s)://api.shiliuai.com/api/video_inpaint/v1"
局_提交协议头 = "APIKEY: 你的APIKEY"
局_结果 = 网页_访问_对象 (局_网址, 1, , 视频数据, , 局_提交协议头, , , , , , , , , , , , , )
局_返回 = 到文本 (编码_编码转换对象 (局_结果, , , ))
' 解析 file_id、wait_time 后循环轮询
.判断循环 (真)
    程序_延时 (wait_time × 1000, )
    局_结果 = 网页_访问_对象 (局_网址, 1, "file_id=" + file_id, , , 局_提交协议头, , , , , , , , , , , , , )
    局_返回 = 到文本 (编码_编码转换对象 (局_结果, , , ))
    ' status 为 done 时下载 result_url
.判断循环结束 ()
返回 (局_返回)

4.9 天诺

public static string Api_VideoInpaint(string apiKey, string videoPath)
{
    string url = "http(s)://api.shiliuai.com/api/video_inpaint/v1";
    var headers = new Dictionary<string, string>
    {
        {"APIKEY", apiKey}
    };
    // 使用 multipart/form-data 上传视频文件
    var files = new Dictionary<string, string>
    {
        {"file", videoPath}
    };
    var formData = new Dictionary<string, string>
    {
        {"is_move", "true"}
    };
    string response = CustomHelp.HttpPostMultipart(url, files, formData, headers);
    // 解析 file_id,按 wait_time 轮询
    // status 为 done 时下载 result_url
    return response;
}

4.10 按键精灵-电脑版

Import "Encrypt.dll"
VBSBegin
Function api_video_inpaint(apiKey, videoPath)
    url = "http(s)://api.shiliuai.com/api/video_inpaint/v1"
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "POST", url, False
    http.setRequestHeader "APIKEY", apiKey
    ' multipart/form-data 上传视频文件
    Dim boundary : boundary = "----FormBoundary" & Timer
    http.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & boundary
    ' 读取视频文件并构造 multipart body
    Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
    Dim inFile : Set inFile = fso.GetFile(videoPath)
    Dim ts : Set ts = inFile.OpenAsTextStream(1, -2)
    Dim fileData : fileData = ts.Read(inFile.Size)
    ts.Close
    Dim body : body = "--" & boundary & vbCrLf
    body = body & "Content-Disposition: form-data; name=""file""; filename=""" & inFile.Name & """" & vbCrLf
    body = body & "Content-Type: application/octet-stream" & vbCrLf & vbCrLf
    body = body & fileData & vbCrLf
    body = body & "--" & boundary & vbCrLf
    body = body & "Content-Disposition: form-data; name=""is_move""" & vbCrLf & vbCrLf
    body = body & "true" & vbCrLf
    body = body & "--" & boundary & "--" & vbCrLf
    http.send body
    api_video_inpaint = http.responseText
End Function
VBSEnd

apiKey = "你的APIKEY"
res = api_video_inpaint(apiKey, "你的视频路径.mp4")
TracePrint res

4.11 按键精灵-手机版

Import "yd.luae"
Import "zm.luae"

Dim videoPath = "/sdcard/Pictures/test.mp4"

Function api_video_inpaint(apiKey, videoPath)
    Dim url = "http(s)://api.shiliuai.com/api/video_inpaint/v1"
    Dim headers = {null}
    headers["APIKEY"] = apiKey
    Dim body = "{""file_url"":""" & videoPath & """,""is_move"":true}"
    Dim res = yd.HttpPost(url, body, headers)
    api_video_inpaint = yd.JsonDecode(res)
End Function

Dim apiKey = "你的APIKEY"
Dim res = api_video_inpaint(apiKey, videoPath)
TracePrint res["code"]

' 轮询获取结果
Dim fileId = res["file_id"]
Dim waitTime = res["wait_time"]
Do
    Delay waitTime * 1000
    Dim pollBody = "{""file_id"":""" & fileId & """}"
    res = yd.HttpPost(url, pollBody, headers)
    res = yd.JsonDecode(res)
Loop While res["status"] <> "done"

' 下载结果视频
Dim resultUrl = res["result_url"]
yd.DownloadFile(resultUrl, "/sdcard/Pictures/result.mp4")
TracePrint "视频去水印成功"

4.12 触动精灵

require("tsnet")
require "TSLib"
local ts = require("ts")
local json = ts.json

function api_video_inpaint(apiKey, videoPath)
    local url = "http(s)://api.shiliuai.com/api/video_inpaint/v1"
    local headers = {}
    headers["APIKEY"] = apiKey
    headers["Content-Type"] = "application/json"
    local body = json.encode({ file_url = videoPath, is_move = true })
    local resp = httpPost(url, body, { headers = headers })
    return json.decode(resp)
end

local apiKey = "你的APIKEY"
local videoPath = "/var/mobile/Media/test.mp4"
local data = api_video_inpaint(apiKey, videoPath)

if data.code == 0 then
    local fileId = data.file_id
    local waitTime = data.wait_time or 1
    while true do
        mSleep(waitTime * 1000)
        local pollBody = json.encode({ file_id = fileId })
        local resp = httpPost(url, pollBody, { headers = { ["APIKEY"] = apiKey, ["Content-Type"] = "application/json" } })
        data = json.decode(resp)
        if data.status == "done" then
            -- 下载结果视频
            local resultUrl = data.result_url
            local res = httpGet(resultUrl)
            if res then
                local filename = string.match(resultUrl, "([^/]+)$")
                writeFile("/var/mobile/Media/" .. filename, res)
            end
            break
        end
    end
end

4.13 懒人精灵

function api_video_inpaint(apiKey, videoPath)
    local url = "http(s)://api.shiliuai.com/api/video_inpaint/v1"
    local headers = {}
    headers["APIKEY"] = apiKey
    headers["Content-Type"] = "application/json"
    local body = jsonLib.encode({ file_url = videoPath, is_move = true })
    local resp = httpPost(url, body, { headers = headers })
    return jsonLib.decode(resp)
end

local apiKey = "你的APIKEY"
local videoPath = "/sdcard/Pictures/test.mp4"
local data = api_video_inpaint(apiKey, videoPath)

if data.code == 0 then
    local fileId = data.file_id
    local waitTime = data.wait_time or 1
    while true do
        sleep(waitTime * 1000)
        local pollBody = jsonLib.encode({ file_id = fileId })
        local resp = httpPost(url, pollBody, { headers = { ["APIKEY"] = apiKey, ["Content-Type"] = "application/json" } })
        data = jsonLib.decode(resp)
        if data.status == "done" then
            local resultUrl = data.result_url
            downloadFile(resultUrl, "/sdcard/Pictures/result.mp4")
            break
        end
    end
end

4.14 EasyClick

function api_video_inpaint(apiKey, videoPath)
    local url = "http(s)://api.shiliuai.com/api/video_inpaint/v1"
    local headers = {
        ["APIKEY"] = apiKey,
        ["Content-Type"] = "application/json"
    }
    local body = JSON.stringify({ file_url = videoPath, is_move = true })
    local params = {
        url = url,
        method = "POST",
        headers = headers,
        requestBody = body
    }
    local res = http.request(params)
    return JSON.parse(res.body)
end

function main()
    local apiKey = "你的APIKEY"
    local videoPath = "/sdcard/Pictures/test.mp4"
    local data = api_video_inpaint(apiKey, videoPath)

    if data.code == 0 then
        local fileId = data.file_id
        local waitTime = data.wait_time or 1
        while true do
            sleep(waitTime * 1000)
            local pollBody = JSON.stringify({ file_id = fileId })
            local params = {
                url = "http(s)://api.shiliuai.com/api/video_inpaint/v1",
                method = "POST",
                headers = { ["APIKEY"] = apiKey, ["Content-Type"] = "application/json" },
                requestBody = pollBody
            }
            local res = http.request(params)
            data = JSON.parse(res.body)
            if data.status == "done" then
                logd("视频去水印成功")
                break
            end
        end
    else
        logd("请求失败:", data.msg_cn or data.msg)
    end
end

main()