Speech Synthesis
Description
This API starts a speech synthesis task. After the task is submitted successfully, it is executed asynchronously. You can actively query the algorithm result through the query API or receive the result at the callback URL configured in the request.
Version
1.0
Media Requirements
The speech synthesis algorithm itself does not require an input image or other media file. The unified gateway requires the init_images field to contain a media element; the example uses the JPG format listed in the original image-format field. This media element is not used as an algorithm parameter for speech synthesis.
API URL
Production environment: https://openapi.meitu.com
Task submission endpoint: https://openapi.meitu.com/api/v1/sdk/sync/push
Task name (task): /v1/tts_synthesis/481979
Task type (task_type): formulaMethod
POST
Content-Type: application/json
Authentication
Request Parameters
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | params | string | Algorithm parameters (JSON string) |
| Yes | init_images | object[] | Media file list. The unified gateway requires a media element, but the algorithm itself does not use it |
| Yes | task | string | Fixed value: /v1/tts_synthesis/481979 |
| Yes | task_type | string | Fixed value: formula |
| No | sync_timeout | int | Default: 30. -1 means do not wait. When synchronous execution times out, status is 9; use the query API to retrieve the result |
The init_images media-file parameter has the following structure. The speech synthesis algorithm itself does not require media input, but the unified gateway requires a media element.
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | url | string | Media URL or base64 data; the example uses a JPG URL |
| Yes | profile | object | Attribute information |
The profile attribute information has the following structure.
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_profiles | object | Media attributes |
| Yes | version | string | Fixed value: v1 |
The media_profiles media attributes have the following structure.
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_data_type | string | url indicates a URL; a type such as jpg indicates base64 data |
The params inference parameter is a JSON string with the following structure.
| Required | Field | Type | Description |
|---|---|---|---|
| No | rsp_media_type | string | Default: url; jpg indicates base64 data |
| Yes | parameter | object | Core algorithm parameter object |
Details of the parameter algorithm parameters:
| Required | Field | Type | Description |
|---|---|---|---|
| Yes | timbre_id | Integer | Voice ID |
| Yes | text | String | Source text to synthesize into speech |
| No | speed | String | Speech rate. Supports 0.5–2.0 with one decimal place. This feature is available only for voices that support SSML tags |
| No | style | String | Emotional style. This feature is available only for voices that support SSML tags |
| No | emotion_scale | Integer | Emotional intensity. Must be an integer from 1 to 5 |
Request Example
{
"task": "/v1/tts_synthesis/481979",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"timbre_id\":17,\"text\":\"测试接口连通性\"}}",
"sync_timeout": 30
}Response Fields
Note: Generated results are periodically deleted. 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 that the request was accepted successfully |
| 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 |
Fields in data:
| Field | Type | Description |
|---|---|---|
| status | int | Status code: -1 task not found; 0 created successfully; 1 running; 2 failed; 9 timed out—use the query API; 10 succeeded |
| result | object | Algorithm result |
| progress | number | Task progress |
| predict_elapsed | int | Estimated duration, in milliseconds |
| create_time | int64 | Creation timestamp, in milliseconds |
| task_id | string | Task ID |
| custom_task_id | string | Custom task ID supplied by the client |
| trace_id | string | Trace identifier within data |
| client_info | string | Client information |
| init_images | object[]/null | Echoed input media |
Fields in result:
| Field | Type | Description |
|---|---|---|
| id | string | Algorithm task ID |
| urls | string[] | List of synthesized speech URLs |
| parameters | object | Parameters returned by the algorithm |
| data | object | Data object returned by the algorithm |
| msg | string | Algorithm processing message |
| msg_id | string | Algorithm message ID |
| images | string[] | List of media URLs returned by the algorithm; in this API's example, these are synthesized speech URLs |
| media_info_list | object[] | List of media information returned by the algorithm |
| code | int | Algorithm error code, returned on failure |
Fields in parameters:
| Field | Type | Description |
|---|---|---|
| bypass_cache | int | Returned bypass_cache parameter |
| channel | string | Returned channel parameter |
| client_id | int | Returned client_id parameter |
| emotion_scale | int | Returned emotion_scale parameter |
| ext_voice_id | string | Returned ext_voice_id parameter |
| id | int | Returned id parameter |
| is_emo | int | Returned is_emo parameter |
| is_support_ssml | int | Returned is_support_ssml parameter |
| is_sync | int | Returned is_sync parameter |
| repost_url | string | Returned repost_url parameter |
| speed | string | Returned speed parameter |
| stat_gid | int | Returned stat_gid parameter |
| style | string | Returned style parameter |
| text | string | Source text synthesized into speech |
| timbre_id | int | Voice ID |
| uid | int | Returned uid parameter |
| version | string | Returned version parameter |
| volume | int | Returned volume parameter |
| with_timestamp | int | Returned with_timestamp parameter |
Fields in each media_info_list element:
| Field | Type | Description |
|---|---|---|
| media_data | string | Synthesized speech URL |
| media_extra | object | Extended media information |
| media_profiles | object | Media attributes; media_data_type is url in the example |
Algorithm-specific error codes and messages:
| Error Code | Error Message | Description |
|---|---|---|
| 20001 | PROCESS_ERROR | Processing error |
Response Examples
Successful Response Example
{
"request_id": "",
"trace_id": "",
"code": 0,
"error_code": 0,
"message": "success",
"tips": null,
"data": {
"status": 10,
"result": {
"id": "t_mt1a3i5n7ba95988c3-7e15-427e-b7e3-ad599217c282",
"urls": [
"http://voice.meitudata.com/audio/1759221923c5584b63582de6cb639aa97392454f4b100.mp3"
],
"parameters": {
"bypass_cache": 0,
"channel": "",
"client_id": 0,
"emotion_scale": 0,
"ext_voice_id": "",
"id": 0,
"is_emo": 0,
"is_support_ssml": 0,
"is_sync": 0,
"repost_url": "https://koios-gateway-api.meitu.com/api/v1/task/notify?task_id=t_mt1a3i5n7ba95988c3-7e15-427e-b7e3-ad599217c282\u0026trace_id=a71d1ea3-874c-47b8-8f9c-da5a972af8c1",
"speed": "",
"stat_gid": 0,
"style": "",
"text": "测试接口连通性",
"timbre_id": 17,
"uid": 0,
"version": "",
"volume": 0,
"with_timestamp": 0
},
"data": {},
"msg": "success",
"msg_id": "voice-cf80bdff-c0bc-4579-aac9-15bad1b97bb8",
"images": [
"http://voice.meitudata.com/audio/1759221923c5584b63582de6cb639aa97392454f4b100.mp3"
],
"media_info_list": [
{
"media_data": "http://voice.meitudata.com/audio/1759221923c5584b63582de6cb639aa97392454f4b100.mp3",
"media_extra": {},
"media_profiles": {
"media_data_type": "url"
}
}
]
},
"progress": 1,
"predict_elapsed": 10000,
"create_time": 1759222172863,
"task_id": "t_mt1a3i5n7ba95988c3-7e15-427e-b7e3-ad599217c282",
"custom_task_id": "",
"trace_id": "a71d1ea3-874c-47b8-8f9c-da5a972af8c1",
"client_info": "",
"init_images": null
}
}Pending Query Response Example
Use the query API to retrieve the 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
}
}Failed Response Example
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": {
"timbre_id": 17,
"text": "测试接口连通性",
},
}
payload = {
"task": "/v1/tts_synthesis/481979",
"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=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/tts_synthesis/481979",
"task_type": "formula",
"init_images": [{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {"media_data_type": "url"},
"version": "v1"
}
}],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"timbre_id\":17,\"text\":\"测试接口连通性\"}}",
"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' => [
'timbre_id' => 17,
'text' => '测试接口连通性',
],
]);
$body = json_encode([
'task' => '/v1/tts_synthesis/481979',
'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,
]);
$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/tts_synthesis/481979\",\n" +
" \"task_type\": \"formula\",\n" +
" \"init_images\": [{\n" +
" \"url\": \"https://example.com/input.jpg\",\n" +
" \"profile\": {\n" +
" \"media_profiles\": {\"media_data_type\": \"url\"},\n" +
" \"version\": \"v1\"\n" +
" }\n" +
" }],\n" +
" \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"timbre_id\\\":17,\\\"text\\\":\\\"测试接口连通性\\\"}}\",\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);
}
}
}