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 | 未知错误 |
| 101 | API-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()