Long Hair Effect

Description

This API generates an AI long-hair effect video in the cloud.

Version

1.0

Image Requirements

Supported image formats: JPG and PNG.

Request URL

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

Request Method

POST

Content-Type: application/json

Authorization

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 as a JSON string
Yesinit_imagesobject[]Image file list
YestaskstringFixed value: /v1/long_hair_video/long_hair/405293
Yestask_typestringFixed value: formula
Nosync_timeoutintSynchronous timeout; default: 30

The structure of each image parameter in init_images is described below.

RequiredParameterTypeDescription
YesurlstringImage URL or base64 data
YesprofileobjectAttribute information

profile attribute information

RequiredParameterTypeDescription
Yesmedia_profilesobjectImage media attributes

The source document does not provide profile.version; this document does not add a version value.

media_profiles media attributes

RequiredParameterTypeDescription
Yesmedia_data_typestringurl means that url contains an image URL; jpg means that url contains base64-encoded JPG image data

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

RequiredFieldTypeDescription
YesparameterobjectCore algorithm parameter object

parameter algorithm parameter details

The source document does not define any additional algorithm parameters, so pass an empty object {} as parameter. It also does not define rsp_media_type or a result media-type mapping; this document does not add those fields.

Request Example

{
  "task": "/v1/long_hair_video/long_hair/405293",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://wheeai.meitudata.com/static/666162c4139073547bhMUcLeee3093.jpeg",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        }
      }
    }
  ],
  "params": "{\"parameter\":{}}",
  "sync_timeout": 30
}

Response Fields

Note: Generated results are periodically deleted after 24 hours. Download and save them promptly.
FieldTypeDescription
request_idstringRequest identifier
trace_idstringTrace identifier
codeintBusiness status code; 0 means that the request was accepted successfully
error_codeintError code; 0 on success
messagestringBusiness message
tipsanyAdditional information; may be null
dataobject/nullTask status and algorithm result; may be null when the request fails

data field details

FieldTypeDescription
statusintStatus code: -1, task not found; 0, task created; 1, processing; 2, failed; 9, query with the status endpoint; 10, succeeded
resultobjectAlgorithm result
progressnumberTask progress, for example 0.1, 0.85, or 1

result field details

FieldTypeDescription
idstringTask ID
urlsstring[]The source document labels this field as “image URLs.” The API description says that the API generates a video, but the source does not provide a media mapping, so this document does not reinterpret the field

Response Examples

Successful Response

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": 10,
    "result": {
      "id": "50309bd5-a827-4125-bc96-62039c93770b",
      "urls": [
        "https://obs.mtlab.meitu.com/mtopen/rF5GIhp5ReLKgLV91CKj5BO1q2FTLMmc/MTY5Mjg1MzIwMA==/1c39ef92-04f1-40b4-5b7e-8fcfca0c11ea.png"
      ]
    },
    "progress": 1
  }
}

Query-Required Response

Use the status endpoint to retrieve the result, using the returned task ID for the query.

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": "task_id"
    },
    "progress": 0
  }
}

Failed Response

Response Status: 400

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

In the original failed-response example, data is null. To align the example with the unified task response structure below, the original error code 20008 and message UNSUITABLE_IMAGE are retained in data.result. Task identifiers not provided by the source use empty strings, while time and duration values use 0.

{
  "request_id": "",
  "trace_id": "",
  "code": 20008,
  "error_code": 20008,
  "message": "UNSUITABLE_IMAGE",
  "tips": null,
  "data": {
    "status": 2,
    "result": {
      "ErrorCode": 20008,
      "ErrorMsg": "UNSUITABLE_IMAGE",
      "Data": null
    },
    "progress": 0,
    "predict_elapsed": 0,
    "create_time": 0,
    "task_id": "",
    "custom_task_id": "",
    "trace_id": "",
    "client_info": "",
    "init_images": null
  }
}

API-Specific Error Codes and Messages

ErrorCodeError MessageDescription
20001PROCESS_ERRORProcessing error

Common Error Codes and Messages

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 = {
        "parameter": {},
    }
    payload = {
        "task": "/v1/long_hair_video/long_hair/405293",
        "task_type": "formula",
        "init_images": [
            {
                "url": "https://wheeai.meitudata.com/static/666162c4139073547bhMUcLeee3093.jpeg",
                "profile": {
                    "media_profiles": {"media_data_type": "url"},
                },
            }
        ],
        "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/long_hair_video/long_hair/405293",
  "task_type": "formula",
  "init_images": [{
    "url": "https://wheeai.meitudata.com/static/666162c4139073547bhMUcLeee3093.jpeg",
    "profile": {
      "media_profiles": {"media_data_type": "url"}
    }
  }],
  "params": "{\"parameter\":{}}",
  "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([
    'parameter' => (object) [],
]);

$body = json_encode([
    'task' => '/v1/long_hair_video/long_hair/405293',
    'task_type' => 'formula',
    'init_images' => [
        [
            'url' => 'https://wheeai.meitudata.com/static/666162c4139073547bhMUcLeee3093.jpeg',
            'profile' => [
                'media_profiles' => ['media_data_type' => 'url'],
            ],
        ],
    ],
    '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/long_hair_video/long_hair/405293\",\n" +
                "  \"task_type\": \"formula\",\n" +
                "  \"init_images\": [{\n" +
                "    \"url\": \"https://wheeai.meitudata.com/static/666162c4139073547bhMUcLeee3093.jpeg\",\n" +
                "    \"profile\": {\n" +
                "      \"media_profiles\": {\"media_data_type\": \"url\"}\n" +
                "    }\n" +
                "  }],\n" +
                "  \"params\": \"{\\\"parameter\\\":{}}\",\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);
        }
    }
}