Portrait Background Blending
Description
Blends a user-provided portrait with a reference background to generate a new portrait image. Submit one portrait image and one background image, and use media_type to identify the role of each image.
Image Examples
| Portrait Image | Background Image | Output Image |
|---|---|---|
![]() | ![]() | ![]() |
Image Requirements
JPG and PNG are supported. Provide two images in init_images:
- Background image: set
profile.media_profiles.media_typetomedia_data_bg. - Portrait image: set
profile.media_profiles.media_typetomedia_data_fg.
For image URLs, set media_data_type to url. For Base64-encoded images, set it to jpg. The examples submit the background image first and the portrait image second. Both images must include the appropriate role identifier.
Request URL
- Endpoint:
https://openapi.meitu.com/api/v1/sdk/sync/push - Task name (
task):/v1/bg_portrait_replace/bg_portrait/446025 - Task type (
task_type):formula
HTTP Method
POST
Content-Type: application/json
Authentication
Sign requests using your Access Key (AK) and Secret Key (SK). See API Request Signing.
Request Parameters
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | task | string | Fixed value: /v1/bg_portrait_replace/bg_portrait/446025. |
| Yes | task_type | string | Fixed value: formula. |
| Yes | init_images | object[] | Two input images: a background image and a portrait image. Identify each image's role with media_type. |
| Yes | params | string | No additional algorithm parameters are required. Pass the string "{}", not the JSON object {}. |
| No | sync_timeout | int | Synchronous wait time in seconds. Default: 30. Set to -1 to return without waiting. If data.status = 9, use the Task Status API to retrieve the result. |
| No | rsp_media_type | string | Output transmission type. Default: url for image URLs. Use jpg for Base64-encoded image data. This field belongs at the top level of the request body. The examples use the default URL output. |
init_images Item
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | url | string | Image URL or Base64-encoded image data, matching media_data_type. |
| Yes | profile | object | Image transmission information and role identifier. |
profile
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_profiles | object | Image transmission type and role. |
| Yes | version | string | Fixed value: v1. |
media_profiles
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_data_type | string | url: image URL. jpg: Base64-encoded image data. |
| Yes | media_type | string | media_data_bg: reference background. media_data_fg: user portrait. |
Request Example
This example provides the background and portrait images by URL. Replace the example image URLs with accessible URLs.
{
"task": "/v1/bg_portrait_replace/bg_portrait/446025",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/background.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url",
"media_type": "media_data_bg"
},
"version": "v1"
}
},
{
"url": "https://example.com/portrait.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url",
"media_type": "media_data_fg"
},
"version": "v1"
}
}
],
"params": "{}",
"sync_timeout": 30
}Response Fields
The following descriptions and examples use the default URL output. Result images are periodically deleted after 24 hours. Download and save them promptly.
| Field | Type | Description |
|---|---|---|
| code | int | Request processing status. 0 indicates normal request processing; a nonzero value indicates failure. Also check data.status to determine whether the task has completed. |
| message | string | Response message or error information. |
| data | object/null | Task information. May be null if the request fails. |
data
| Field | Type | Description |
|---|---|---|
| status | int | Task status: -1 not found; 0 created; 1 processing; 2 failed; 9 result query required; 10 succeeded. |
| msg | string | Media attribute description, when included in the response. |
| result | object | Task ID and processing result. |
| progress | number | Task progress, for example 0.1, 0.85, or 1. |
result
| Field | Type | Description |
|---|---|---|
| id | string | Task ID. Pass this value as task_id when querying the result. |
| urls | string[] | Result image URLs available after the task succeeds. |
When data.status is 9, use data.result.id to call the Task Status API. Send a signed GET request to https://openapi.meitu.com/api/v1/sdk/status?task_id=<TASK_ID>.
If the query returns status 0 or 1, the task is not yet complete. When status is 10, retrieve data.result.urls. Status 2 indicates task failure. Tasks expire after 24 hours; historical task queries are not supported.
Response Examples
Successful Response
The task has completed: data.status = 10.
{
"code": 0,
"message": "",
"data": {
"status": 10,
"result": {
"id": "50309bd5-a827-4125-bc96-62039c93770b",
"urls": [
"https://example.com/result.png"
]
},
"progress": 1
}
}Query-Required Response
Query the task result using data.result.id as the task_id parameter.
{
"code": 0,
"message": "",
"data": {
"status": 9,
"result": {
"id": "50309bd5-a827-4125-bc96-62039c93770b"
},
"progress": 0
}
}Failed Response
{
"code": 20008,
"message": "UNSUITABLE_IMAGE",
"data": null
}Error Codes
| Error Code | Error Message | Description |
|---|---|---|
| 20008 | UNSUITABLE_IMAGE | The image does not meet the API requirements. |
For other errors, see API Error Codes.
SDK Examples
The following examples submit a portrait background blending task with the same request parameters. Replace the AK, SK, background image URL, and portrait image URL before running the code.
The examples print the API response. After a successful request, check data.status. If it is 9, query the task result as described above.
Python
Set up the SDK as described in the Python Signing SDK documentation.
import json
import requests
from sign_sdk import sign
def api_call_example():
key = "your_access_key"
secret = "your_secret_key"
url = "https://openapi.meitu.com/api/v1/sdk/sync/push"
headers = {
"Content-Type": "application/json",
sign.HeaderHost: "openapi.meitu.com",
}
payload = {
"task": "/v1/bg_portrait_replace/bg_portrait/446025",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/background.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url",
"media_type": "media_data_bg"
},
"version": "v1"
}
},
{
"url": "https://example.com/portrait.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url",
"media_type": "media_data_fg"
},
"version": "v1"
}
}
],
"params": "{}",
"sync_timeout": 30
}
body = json.dumps(payload, ensure_ascii=False)
signer = sign.Signer(key, secret)
signed_request = signer.sign(url, "POST", headers, body)
with requests.Session() as session:
response = session.send(signed_request, timeout=60)
print("Status:", response.status_code)
print("Response:", response.text)
if __name__ == "__main__":
api_call_example()Go
Set up the SDK as described in the Go Signing SDK documentation.
package main
import (
"fmt"
"io"
"net/http"
"time"
"github.com/mtlab/api/signer"
)
func main() {
key := "your_access_key"
secret := "your_secret_key"
signObj := signer.NewSigner(key, secret)
url := "https://openapi.meitu.com/api/v1/sdk/sync/push"
headers := make(http.Header)
headers.Set(signer.HeaderHost, "openapi.meitu.com")
headers.Set("Content-Type", "application/json")
body := `{
"task": "/v1/bg_portrait_replace/bg_portrait/446025",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/background.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url",
"media_type": "media_data_bg"
},
"version": "v1"
}
},
{
"url": "https://example.com/portrait.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url",
"media_type": "media_data_fg"
},
"version": "v1"
}
}
],
"params": "{}",
"sync_timeout": 30
}`
req, err := signObj.Sign(url, http.MethodPost, headers, body)
if err != nil {
fmt.Println("Failed to sign request:", err)
return
}
client := &http.Client{Timeout: 60 * time.Second}
resp, err := client.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("Failed to read response:", err)
return
}
fmt.Println("Status:", resp.StatusCode)
fmt.Println("Response:", string(responseBody))
}PHP
Set up the SDK as described in the PHP Signing SDK documentation.
<?php
require_once __DIR__ . '/signer.php';
$key = 'your_access_key';
$secret = 'your_secret_key';
$url = 'https://openapi.meitu.com/api/v1/sdk/sync/push';
$headers = [
'Content-Type' => 'application/json',
'Host' => 'openapi.meitu.com',
];
$body = json_encode([
'task' => '/v1/bg_portrait_replace/bg_portrait/446025',
'task_type' => 'formula',
'init_images' => [
[
'url' => 'https://example.com/background.jpg',
'profile' => [
'media_profiles' => [
'media_data_type' => 'url',
'media_type' => 'media_data_bg',
],
'version' => 'v1',
],
],
[
'url' => 'https://example.com/portrait.jpg',
'profile' => [
'media_profiles' => [
'media_data_type' => 'url',
'media_type' => 'media_data_fg',
],
'version' => 'v1',
],
],
],
'params' => '{}',
'sync_timeout' => 30,
], JSON_UNESCAPED_SLASHES);
$signer = new Signer($key, $secret);
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
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
Set up the SDK as described in the Java Signing SDK documentation.
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 {
Signer signer = new Signer("your_access_key", "your_secret_key");
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/bg_portrait_replace/bg_portrait/446025\",\n"
+ " \"task_type\": \"formula\",\n"
+ " \"init_images\": [\n"
+ " {\n"
+ " \"url\": \"https://example.com/background.jpg\",\n"
+ " \"profile\": {\n"
+ " \"media_profiles\": {\n"
+ " \"media_data_type\": \"url\",\n"
+ " \"media_type\": \"media_data_bg\"\n"
+ " },\n"
+ " \"version\": \"v1\"\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"url\": \"https://example.com/portrait.jpg\",\n"
+ " \"profile\": {\n"
+ " \"media_profiles\": {\n"
+ " \"media_data_type\": \"url\",\n"
+ " \"media_type\": \"media_data_fg\"\n"
+ " },\n"
+ " \"version\": \"v1\"\n"
+ " }\n"
+ " }\n"
+ " ],\n"
+ " \"params\": \"{}\",\n"
+ " \"sync_timeout\": 30\n"
+ "}";
Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
try {
connection.setRequestMethod(method);
connection.setConnectTimeout(10000);
connection.setReadTimeout(60000);
connection.setInstanceFollowRedirects(false);
for (Map.Entry<String, String> entry : signedHeaders.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
connection.setDoOutput(true);
try (OutputStream output = connection.getOutputStream()) {
output.write(body.getBytes(StandardCharsets.UTF_8));
}
int status = connection.getResponseCode();
System.out.println("Status: " + status);
InputStream stream = status >= 400
? connection.getErrorStream()
: connection.getInputStream();
if (stream != null) {
try (InputStream input = stream;
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: "
+ new String(output.toByteArray(), StandardCharsets.UTF_8));
}
}
} finally {
connection.disconnect();
}
}
}

