Vocal Separation
Description
This API submits a video vocal-separation task. According to the source document, the algorithm runs asynchronously after a successful submission. You can retrieve the result through the task query API or receive it through the callback URL supplied with the request.
Version
1.0
Media Requirements
The source document lists JPG and PNG as supported image formats. However, its request example uses a MOV video URL and sets media_data_type to MP4. The source document does not specify file-size, resolution, or video-duration limits.
API URL
Production host: https://openapi.meitu.com
Task submission endpoint: https://openapi.meitu.com/api/v1/sdk/sync/push
Task name (task): /v1/ai_audio_spliter/481965
Task type (task_type): formulaMethod
POST
Content-Type: application/json
Authentication
Request Parameters
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | params | string | Algorithm parameters as a JSON string |
| Yes | init_images | object[] | Input media list |
| Yes | task | string | Fixed value: /v1/ai_audio_spliter/481965 |
| Yes | task_type | string | Fixed value: formula |
| No | sync_timeout | int | Synchronous timeout in seconds; default: 30 |
The legacy request table in the source document also lists an optional task_id. It is described as a unique custom task ID that can be used to query task status. The unified gateway does not allow this field at the top level, so it is not included in the request example below.
init_images item fields:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | url | string | Media URL; the source example uses a MOV video URL |
| Yes | profile | object | Media profile |
profile fields:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_profiles | object | Media attributes |
| Yes | version | string | Fixed value: v1 |
media_profiles fields:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_data_type | string | The source example uses MP4 for a media URL |
params is a JSON string. After decoding, it has the following structure:
| Required | Field | Type | Description |
|---|---|---|---|
| No | rsp_media_type | string | Default: url; jpg means base64 output |
| Yes | parameter | object | Algorithm-specific parameters |
parameter fields:
| Required | Field | Type | Description |
|---|---|---|---|
| Yes | task_type | string | Fixed value: spliter |
Request Example
{
"task": "/v1/ai_audio_spliter/481965",
"task_type": "formula",
"init_images": [
{
"url": "https://tos-vesdk-wink-sh.meitudata.com/mtlab_video/68daacf4a6bb1r0zqrmdip600.mov",
"profile": {
"media_profiles": {
"media_data_type": "MP4"
},
"version": "v1"
}
}
],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"task_type\":\"spliter\"}}",
"sync_timeout": 30
}Response Fields
Generated results are cleaned up periodically. Download and save them promptly.| Field | Type | Description |
|---|---|---|
| request_id | string | Request identifier |
| trace_id | string | Trace identifier |
| code | int | Business status code; 0 means the request was accepted |
| error_code | int | Error code; 0 on success |
| message | string | Business message |
| tips | any | Additional information; may be null |
| data | object | Task status and algorithm result |
data fields:
| Field | Type | Description |
|---|---|---|
| status | int | -1: task not found; 0: created; 1: running; 2: failed; 9: timed out and requires the query API; 10: succeeded |
| result | object | Algorithm result |
| progress | number | Task progress |
| predict_elapsed | int | Estimated processing time in milliseconds |
| create_time | int64 | Creation timestamp in milliseconds |
| task_id | string | Task ID |
| custom_task_id | string | Client-supplied custom task ID |
| trace_id | string | Trace identifier inside data |
| client_info | string | Client information |
| init_images | object[]/null | Echo of input media |
result fields:
| Field | Type | Description |
|---|---|---|
| id | int/string | Task ID; the source table declares an int, while the response example uses a string |
| urls | string[] | Result URL list in the success response |
| parameters | object | Task result information in the source field table |
| data | int/object | The source table declares an int, while the failure response uses an error-detail object |
| msg | long/string | The source table declares a long, while the failure response uses an error-message string |
| msg_id | string | Described as a system-generated task ID in the source table and used as a message ID in the failure response |
parameters fields:
| Field | Type | Description |
|---|---|---|
| code | int | 0 indicates a normal result; any other value indicates an error |
| id | string | Unique string identifying each request, also called job_id |
| name | string | User-supplied request parameter |
| created_time | string | Time when task execution was created |
| updated_time | string | Time when task execution finished |
| msg | string | Task execution message |
| latency | float | API latency |
| split_list | list | Separated file URLs; names beginning with vocals_ contain vocals, while names beginning with no_vocals_ contain accompaniment |
| loudnorm_result | dict | Maps loudness values to audio URLs; returned when a unified loudness value is supplied |
Fields of result.data in the failure example:
| Field | Type | Description |
|---|---|---|
| duration | object | Stage durations and timestamps |
| error_code | int | Algorithm error code |
| error_msg | string | Algorithm error message |
| extra | object | Additional data |
| media_info_list | object[] | Media information list |
| msg_id | string | Message ID |
| parameter | object/null | Echo of algorithm parameters |
API-specific errors:
| ErrorCode | Error | Description |
|---|---|---|
| 20001 | PROCESS_ERROR | Processing error |
| 21101 | Invalid parameter | |
| 26101 | Failed to obtain the model | |
| 25402 | Model feature extraction failed, for example because no timbre could be extracted from the input audio or the content was invalid | |
| 20602 | Model inference failed, possibly because of invalid input characters or another processing error | |
| 22201 | Failed to generate the result, including failures when uploading to OBS | |
| 20301 | Unknown exception |
Response Examples
Success
{
"request_id": "",
"trace_id": "",
"code": 0,
"error_code": 0,
"message": "",
"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,
"predict_elapsed": 0,
"create_time": 0,
"task_id": "",
"custom_task_id": "",
"trace_id": "",
"client_info": "",
"init_images": null
}
}Query Required
Use the query API to retrieve the task result.
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": "t_mt1a3i5n7b3da6d589-46b5-4f66-a0bb-8dd22f2a172e"
},
"progress": 0,
"predict_elapsed": 10000,
"create_time": 1759202368761,
"task_id": "t_mt1a3i5n7b3da6d589-46b5-4f66-a0bb-8dd22f2a172e",
"custom_task_id": "",
"trace_id": "9129a3a2-99c4-46ce-8731-0e100e2fbee7",
"client_info": "",
"init_images": null
}
}Failure
Response Status: 400
Content-Type: application/json; charset=utf-8
{
"request_id": "",
"trace_id": "",
"code": 20001,
"error_code": 20001,
"message": "ALGO_MODEL_CRASH",
"tips": null,
"data": {
"status": 2,
"result": {
"id": "t_mt1a3i5n7be8d575cc-2ffb-4e0c-85a8-1824110e31b8",
"code": 20001,
"data": {
"duration": {
"alg_process_time": 0,
"created_timestamp": 1759201989,
"pull_timestamp": 1759201989,
"repost_time": 0,
"upload_time": 0,
"waiting_time": 0
},
"error_code": 20001,
"error_msg": "ALGO_MODEL_CRASH",
"extra": {},
"media_info_list": [],
"msg_id": "c1b09cb2-6e05-4d21-55ab-r007b1f21bec",
"parameter": null
},
"msg": "ALGO_MODEL_CRASH",
"msg_id": "c1b09cb2-6e05-4d21-55ab-r007b1f21bec"
},
"progress": 1,
"predict_elapsed": 10000,
"create_time": 1759201989444,
"task_id": "t_mt1a3i5n7be8d575cc-2ffb-4e0c-85a8-1824110e31b8",
"custom_task_id": "",
"trace_id": "",
"client_info": "",
"init_images": null
}
}General Error Codes
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 = {
"rsp_media_type": "url",
"parameter": {"task_type": "spliter"},
}
payload = {
"task": "/v1/ai_audio_spliter/481965",
"task_type": "formula",
"init_images": [
{
"url": "https://tos-vesdk-wink-sh.meitudata.com/mtlab_video/68daacf4a6bb1r0zqrmdip600.mov",
"profile": {
"media_profiles": {"media_data_type": "MP4"},
"version": "v1",
},
}
],
"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/ai_audio_spliter/481965",
"task_type": "formula",
"init_images": [{
"url": "https://tos-vesdk-wink-sh.meitudata.com/mtlab_video/68daacf4a6bb1r0zqrmdip600.mov",
"profile": {
"media_profiles": {"media_data_type": "MP4"},
"version": "v1"
}
}],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"task_type\":\"spliter\"}}",
"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([
'rsp_media_type' => 'url',
'parameter' => ['task_type' => 'spliter'],
]);
$body = json_encode([
'task' => '/v1/ai_audio_spliter/481965',
'task_type' => 'formula',
'init_images' => [
[
'url' => 'https://tos-vesdk-wink-sh.meitudata.com/mtlab_video/68daacf4a6bb1r0zqrmdip600.mov',
'profile' => [
'media_profiles' => ['media_data_type' => 'MP4'],
'version' => 'v1',
],
],
],
'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/ai_audio_spliter/481965\",\n" +
" \"task_type\": \"formula\",\n" +
" \"init_images\": [{\n" +
" \"url\": \"https://tos-vesdk-wink-sh.meitudata.com/mtlab_video/68daacf4a6bb1r0zqrmdip600.mov\",\n" +
" \"profile\": {\n" +
" \"media_profiles\": {\"media_data_type\": \"MP4\"},\n" +
" \"version\": \"v1\"\n" +
" }\n" +
" }],\n" +
" \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"task_type\\\":\\\"spliter\\\"}}\",\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);
}
}
}