百变滤镜
描述
为图片应用指定滤镜,并可调整滤镜透明度、美颜透明度和虚化程度。使用素材 ID 选择滤镜效果。
版本
1.0
图片要求
支持 JPG、PNG。通过 URL 传入时,不对 URL 进行 Base64 编码。
调用 URL
任务提交接口:
https://openapi.meitu.com/api/v1/sdk/sync/push任务名称(task):/v1/Image_Filter/496525
任务类型(task_type):formula
调用方法
POST
Content-Type: application/json
权限
使用已开通该能力的 AK/SK,通过签名 SDK 生成请求签名。详见开放平台接口签名。
请求参数
| 是否必选 | 参数名 | 类型 | 参数说明 |
|---|---|---|---|
| 是 | task | string | 固定为 /v1/Image_Filter/496525。 |
| 是 | task_type | string | formula。 |
| 是 | init_images | object[] | 输入图片列表。 |
| 是 | params | string | 算法参数对象序列化后的 JSON 字符串。 |
| 否 | sync_timeout | integer | 同步等待时长,单位为秒,默认值为 30。 |
init_images 元素
| 是否必选 | 参数名 | 类型 | 参数说明 |
|---|---|---|---|
| 是 | url | string | 图片 URL 或 Base64 编码数据,与媒体类型对应。 |
| 是 | profile | object | 图片属性。 |
profile
| 是否必选 | 参数名 | 类型 | 参数说明 |
|---|---|---|---|
| 是 | version | string | 网关媒体配置版本,固定为 v1。 |
| 是 | media_profiles | object | 图片传输属性。 |
| 否 | media_extra | object | 图片附加信息,无需传入时可省略。 |
media_profiles
| 是否必选 | 参数名 | 类型 | 参数说明 |
|---|---|---|---|
| 否 | media_data_type | string | jpg:Base64 编码数据,原算法默认值;url:图片 URL。使用 URL 时显式传入 url。 |
params
解码后的对象包含以下字段:
| 是否必选 | 参数名 | 类型 | 参数说明 |
|---|---|---|---|
| 是 | parameter | object | 滤镜参数。 |
| 否 | extra | object | 额外处理信息,无需传入时可省略。 |
parameter
| 是否必选 | 参数名 | 类型 | 参数说明 |
|---|---|---|---|
| 否 | filterType | string | 滤镜素材 ID,见下方素材表,例如 Fa0145JwLfwjjbch。 |
| 否 | filterAlpha | integer | 滤镜透明度,默认值为 70。原文未说明取值范围。 |
| 否 | beautyAlpha | integer | 美颜透明度,默认值为 0。原文未说明取值范围。 |
| 否 | virtualType | integer | 虚化程度,默认值为 0,取值范围为 0–100,值越大虚化越明显。 |
| 否 | version | string | 算法版本,默认值为 1.0。不同于 profile.version。 |
| 否 | rsp_media_type | string | 原文请求示例使用 url,参数表另列 base64;两者分别表示 URL 和 Base64 返回方式,实际支持情况需以接入结果为准。 |
原文将 filterType 标为整数、默认值为 0,但实际请求示例和素材表均使用字符串 ID。本文按素材 ID 传字符串;建议显式选择下表中的 ID,不依赖原文含义未明的默认值。
原文的请求表、请求示例和返回示例分别出现 base64、url、jpg,未给出统一说明。本文请求沿用原请求示例的 url,返回示例保留原文的 Base64 结构,二者不是同一次实测调用。
滤镜素材
| 素材 ID | 滤镜名称 |
|---|---|
| Fa0145JwLfwjjbch | 彩铅 |
| Fa0415o4g8OfwAw8 | Hana |
| Fa0436P7QKK0zKRL | 中央公园 |
| Fa0108HAz4MlDLVx | 优格 |
| Fa0535samdIjz0Wq | 兰桂坊 |
| Fa0727hdRPZAndOR | 粉镜 |
输入值示例
替换图片 URL。示例使用“彩铅”滤镜。
{
"task": "/v1/Image_Filter/496525",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"parameter\":{\"filterType\":\"Fa0145JwLfwjjbch\",\"filterAlpha\":70,\"beautyAlpha\":0,\"virtualType\":0,\"version\":\"1.0\",\"rsp_media_type\":\"url\"}}",
"sync_timeout": 30
}params 解码后的对象:
{
"parameter": {
"filterType": "Fa0145JwLfwjjbch",
"filterAlpha": 70,
"beautyAlpha": 0,
"virtualType": 0,
"version": "1.0",
"rsp_media_type": "url"
}
}返回值说明
以下按统一网关规范说明响应。算法原始结果位于 data.result.data。响应为结构示例,未经真实接口调用验证。
| 字段 | 类型 | 说明 |
|---|---|---|
| code | integer | 网关业务状态码,0 不代表任务已经完成。 |
| message | string | 响应消息。 |
| data.status | integer | -1 未找到任务;0 已创建;1 执行中;2 失败;9 同步等待超时;10 成功。 |
| data.task_id | string | 网关任务 ID,用于任务查询,不使用算法 msg_id。 |
| data.progress | number | 任务进度。 |
| data.result | object | 算法结果封装。 |
| data.result.id | string | 任务 ID。 |
| data.result.code | integer | 算法状态码。 |
| data.result.data | object | 原始算法响应。 |
result.data
| 字段 | 类型 | 说明 |
|---|---|---|
| media_info_list | object[] | 处理结果图片列表。 |
| media_info_list[].media_data | string | 结果图片数据,原文成功示例为 Base64 数据。 |
| media_info_list[].media_profiles.media_data_type | string | 原文成功示例为 jpg,表示 Base64 数据。 |
| parameter | object | 返回参数。 |
| parameter.rsp_media_type | string | 结果媒体类型;原文字段说明为 jpg,成功示例未包含。 |
返回值示例
以下示例基于统一网关模板和原算法返回资料整理,不是实测返回;请求使用 url,原文返回示例使用 Base64,二者并非同一次调用。结果数据和任务 ID 均为占位值。
请求成功返回示例
{
"code": 0,
"message": "success",
"data": {
"status": 10,
"task_id": "example-task-id",
"result": {
"id": "example-task-id",
"code": 0,
"data": {
"media_info_list": [
{
"media_data": "BASE64_IMAGE_DATA",
"media_profiles": {
"media_data_type": "jpg"
}
}
],
"parameter": {}
}
},
"progress": 1
}
}需要查询返回示例
data.status = 9 表示同步等待超时,不代表任务失败。使用 data.task_id 按任务查询接口继续查询,不要重复提交。
{
"code": 0,
"message": "success",
"data": {
"status": 9,
"task_id": "example-task-id",
"result": {
"id": "example-task-id"
},
"progress": 0
}
}请求失败返回示例
以下为 HTTP 400 的处理失败结构示例,不表示所有错误均返回相同状态和错误码。
{
"code": 20001,
"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",
"data": {
"ErrorCode": 20001,
"ErrorMsg": "process error",
"Data": null
}
}
}
}通用的错误代码与信息
本接口原文列出的 20001 / PROCESS_ERROR 表示处理错误。其他错误详见 API 错误码。
SDK 调用示例
以下示例内嵌完整请求体,无需额外 JSON 文件。按对应文档引入签名 SDK 后,替换 AK、SK 和图片 URL。各示例提交一次并打印响应。
Python
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"
inner_params = {
"parameter": {
"filterType": "Fa0145JwLfwjjbch",
"filterAlpha": 70,
"beautyAlpha": 0,
"virtualType": 0,
"version": "1.0",
"rsp_media_type": "url"
}
}
payload = {
"task": "/v1/Image_Filter/496525",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": json.dumps(inner_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
package main
import (
"fmt"
"io"
"net/http"
"time"
"github.com/mtlab/api/signer"
)
func main() {
body := `{
"task": "/v1/Image_Filter/496525",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"parameter\":{\"filterType\":\"Fa0145JwLfwjjbch\",\"filterAlpha\":70,\"beautyAlpha\":0,\"virtualType\":0,\"version\":\"1.0\",\"rsp_media_type\":\"url\"}}",
"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
require_once __DIR__ . '/signer.php';
$innerParams = json_encode([
'parameter' => [
'filterType' => 'Fa0145JwLfwjjbch',
'filterAlpha' => 70,
'beautyAlpha' => 0,
'virtualType' => 0,
'version' => '1.0',
'rsp_media_type' => 'url'
]
], JSON_UNESCAPED_SLASHES);
$body = json_encode([
'task' => '/v1/Image_Filter/496525',
'task_type' => 'formula',
'init_images' => [
[
'url' => 'https://example.com/input.jpg',
'profile' => [
'media_profiles' => [
'media_data_type' => 'url'
],
'version' => 'v1'
]
]
],
'params' => $innerParams,
'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
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/Image_Filter/496525\",\n" +
" \"task_type\": \"formula\",\n" +
" \"init_images\": [\n" +
" {\n" +
" \"url\": \"https://example.com/input.jpg\",\n" +
" \"profile\": {\n" +
" \"media_profiles\": {\n" +
" \"media_data_type\": \"url\"\n" +
" },\n" +
" \"version\": \"v1\"\n" +
" }\n" +
" }\n" +
" ],\n" +
" \"params\": \"{\\\"parameter\\\":{\\\"filterType\\\":\\\"Fa0145JwLfwjjbch\\\",\\\"filterAlpha\\\":70,\\\"beautyAlpha\\\":0,\\\"virtualType\\\":0,\\\"version\\\":\\\"1.0\\\",\\\"rsp_media_type\\\":\\\"url\\\"}}\",\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();
}
}
}