语音通用多任务引擎

描述

语音通用多任务引擎

版本

1.0

图片要求

音频格式:wav、m4a、mp4、mp3、aac 等。

调用 URL

正式环境:https://openapi.meitu.com
任务提交接口:https://openapi.meitu.com/api/v1/sdk/sync/push
任务名称(task):/v1/ai_audio_engine/481991
任务类型(task_type):formula

调用方法

POST

Content-Type: application/json

权限

开放平台接口签名

请求参数

是否必选参数名类型参数说明
必选taskString/v1/ai_audio_engine/481991
必选task_typeStringformula
必选init_imagesObject[]多媒体文件
必选paramsString推理参数
可选sync_timeoutInt默认 30,同步超时时间;接口超时后 status 返回 9,使用查询接口获取结果

init_images 多媒体文件参数,结构说明如下

是否必选参数名类型参数说明
必选urlString音频 URL 或 base64
必选profileobject音频的相关属性信息描述

profile 属性信息描述

是否必选参数名类型参数说明
必选media_profilesobject音频的相关属性信息描述
必选versionstring固定 v1

media_profiles 中参数说明

是否必选参数名类型参数说明
必选media_data_typeStringurl 表示 URL;对应音频类型表示 base64。

params 推理参数是JSON字符串,其结构说明如下

是否必选参数名类型参数说明
rsp_media_typeString默认 url
parameterobject推理参数

parameter 中参数说明

是否必选参数名类型参数说明
task_typeString任务类型,可选值如下

task_type 可选值说明:

说明依赖项目
lufs获取音频响度-
trans_audio音频提取文字并翻译,输出翻译和提取的文字信息-
ducking人声避让关键帧-
train音色训练,会保存音色ai-audio-timbre, ai-audio-spliter, ai-audio-asr
synth已有音色后的生成ai-audio-timbre, ai-audio-spliter, ai-audio-asr
synth_once一次性克隆+生成,不保存音色ai-audio-timbre, ai-audio-spliter, ai-audio-asr
edit声音编辑ai-audio-timbre, ai-audio-spliter, ai-audio-asr
trans已有音色翻译生成ai-audio-timbre, ai-audio-spliter, ai-audio-asr
trans_once音频实时提取音色翻译ai-audio-timbre, ai-audio-spliter, ai-audio-asr
conversion变声ai-audio-spliter, ai-audio-conversion

各 task_type 的详细参数说明:

1. lufsr(原文小节名;task_type 取值为 lufs,获取音频响度)

是否必选参数名类型参数说明
appString调用方app
uidStringuid,没有传0
gidStringgid

2. trans_audio(音频提取文字并翻译)

是否必选参数名类型参数说明
fromString原始语言
toString翻译语言
client_idInt应用clientId
asr_fromStringASR厂商,默认为tencent
trans_typeString翻译厂商,默认为tencent
energy_thresholdDouble音频rms值阈值,默认为0,不做任务处理
appString调用方app
uidStringuid,没有传0
gidStringgid

3. ducking(人声避让关键帧)

是否必选参数名类型参数说明
appString调用方app
uidStringuid,没有传0
gidStringgid

4. train(音色训练,保存音色)

是否必选参数名类型参数说明
prompt_langString输入音频的语种,国内默认为zh,国外默认为en。若为英文则传en
model_nameString可选值qwen、index_tts2。线上模型为index_tts2
versionString模型版本号,暂时为v1/v2/v3,默认为v1
train_limitFloat训练截取长度(秒级),默认为10s,为0将接收的整段音频输入提取特征
spliterBoolTrue/False,输入模型是否需要降噪
spliter_typeString降噪模型类型
asr_textJSON若传输,则默认使用asr_text
appString调用方app
uidStringuid,没有传0
gidStringgid

5. synth(已有音色后的生成)

是否必选参数名类型参数说明
spk_idString模型训练之后的spk_id
textString合成的文字
sp_speedFloat输出音频sp的变速倍数,默认为1.0
speedFloat输出音频变速倍数,默认为1.0。若加速2倍,请传1/2=0.5
durationFloat输出音频期望生成的时长,默认为0,0表示保持模型生成的时长
use_ssmlBoolTrue/False,是否启用SSML,默认为True
gen_langString输出音频语言,支持zh和en,默认为zh
gen_sizeInt分批次合成音频,每批次的字数
appString调用方app
uidStringuid,没有传0
gidStringgid

6. synth_once(一次性克隆+生成,不保存音色)

是否必选参数名类型参数说明
textString合成的文字
sp_speedFloat输出音频sp的变速倍数,默认为1.0
speedFloat输出音频变速倍数,默认为1.0
durationFloat输出音频期望生成的时长,默认为0,0表示保持模型生成的时长
use_ssmlBoolTrue/False,是否启用SSML,默认为True
prompt_langString输入音频的语种,国内默认为zh,国外默认为en。若为英文则传en
gen_langString输出音频语言,支持zh和en,默认为zh
gen_sizeInt分批次合成音频,每批次的字数
model_nameString可选值qwen、index_tts2。线上模型为index_tts2
versionString模型版本号,暂时为v1/v2/v3,默认为v1
train_limitFloat训练截取长度(秒级),默认为10s,为0将接收的整段音频输入提取特征
spliterBoolTrue/False,输入模型是否需要降噪
spliter_typeString降噪模型类型
asr_textJSON若传输,则默认使用asr_text,不传内部自己调ASR服务
appString调用方app
uidStringuid,没有传0
gidStringgid
emo_control_methodint情感控制方式,默认为 0。0:参考音频情感;1:手动情感向量;2:独立情感参考音频,详见下方说明
emo_vecfloat[]8 维手动情感向量,emo_control_method=1 时必选
emo_ref_pathString情感参考音频 URL,emo_control_method=2 时必选
emo_weightfloat情感参考音频权重,emo_control_method=2 时可选,默认 1.0,取值范围建议 0.0~1.6

情感控制说明

emo_control_method 用于控制合成音频的情感来源,支持以下三种模式:

模式说明需额外传入参数
0参考音频情感(默认)使用 init_images 中上传的音色参考音频提取情感
1手动情感向量通过 8 维向量精确控制情感强度emo_vec(必选)
2独立情感参考音频使用另一条音频控制情感,音色仍来自参考音频emo_ref_path(必选),emo_weight(可选)

emo_vec 8 维向量顺序: [高兴, 愤怒, 悲伤, 恐惧, 反感, 低落, 惊喜, 平静]

约束说明:

  • emo_vec 必须为长度 8 的数值数组
  • 8 维权重之和不能超过 1.5
  • 不传 emo_control_method 时,默认按 0 处理,即使用音色参考音频的情感

7. edit(声音编辑)

是否必选参数名类型参数说明
textString合成的文字
start_timeFloat需要替换音频的开始时间(毫秒)
end_timeFloat需要替换音频的结束时间(毫秒)
sp_speedFloat输出音频sp的变速倍数,默认为1.0
speedFloat输出音频变速倍数,默认为1.0
durationFloat输出音频期望生成的时长,默认为0,0表示保持模型生成的时长
use_ssmlBoolTrue/False,是否启用SSML,默认为True
prompt_langString输入音频的语种,国内默认为zh,国外默认为en。若为英文则传en
gen_langString输出音频语言,支持zh和en,默认为zh
gen_sizeInt分批次合成音频,每批次的字数
model_nameString可选值voice_mirror。线上模型为voice_mirror
versionString模型版本号,暂时为v1/v2/v3,默认为v3
train_limitFloat训练截取长度(秒级),默认为10s,为0将接收的整段音频输入提取特征
spliterBoolTrue/False,输入模型是否需要降噪
spliter_typeString降噪模型类型
asr_textJSON若传输,则默认使用asr_text,不传内部自己调ASR服务
mixBoolTrue/False,是否叠加背景声,默认为False
singleBoolTrue/False,是否为单人模式;当为True时,取整个音频作为模型输入提取特征;当为False时,取start_time开始的音频作为输入提取特征
appString调用方app
uidStringuid,没有传0
gidStringgid

8. trans(已有音色翻译生成)

是否必选参数名类型参数说明
process_infoJSON Array合成的音频信息,包含start_time、end_time、text、trans_text
spk_idString已有的音色ID
fromString原始语言,默认为中文(zh)
toString翻译语言,默认为英文(en)
use_ssmlBoolTrue/False,是否启用SSML,默认为True
model_nameString模型名
versionString模型版本号
appString调用方app
uidStringuid,没有传0
gidStringgid

9. trans_once(音频实时提取音色翻译)

是否必选参数名类型参数说明
process_infoJSON Array合成的音频信息,包含start_time、end_time、text、trans_text
fromString原始语言,默认为中文(zh)
toString翻译语言,默认为英文(en)
use_ssmlBoolTrue/False,是否启用SSML,默认为True
model_nameString模型名
versionString模型版本号
sp_speedFloat输出音频sp的变速倍数,默认为1.0
speedFloat输出音频变速倍数,默认为1.0
durationFloat输出音频期望生成的时长,默认为0,0表示保持模型生成的时长
train_limitFloat训练截取长度(秒级),默认为10s,为0将接收的整段音频输入提取特征
spliterBoolTrue/False,输入模型是否需要降噪
spliter_typeString降噪模型类型
asr_textJSON若传输,则默认使用asr_text,不传内部自己调ASR服务
singleBoolTrue/False,是否为单人模式;当为True时,取整个音频作为模型输入提取特征;当为False时,取start_time开始的音频作为输入提取特征
appString调用方app
uidStringuid,没有传0
gidStringgid

10. conversion(变声)

是否必选参数名类型参数说明
spk_idString音色ID(可选项:ziwei、silang、wukong、baishe)
suffixString返回音频格式,默认为mp3。若需要wav,值传wav
appString调用方app
uidStringuid,没有传0
gidStringgid

输入值示例

1、声音克隆-默认模式(使用参考音频情感)

{
	"task": "/v1/ai_audio_engine/481991",
	"task_type": "formula",
	"init_images": [{
		"url": "http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3",
		"profile": {
			"media_profiles": {
				"media_data_type": "url"
			},
			"version": "v1"
		}
	}],
	"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"task_type\":\"synth_once\",\"text\":\"我是你克隆的专属声音,快来用我制作视频吧。This is the voice of your clone, please use it to create videos.\"}}",
	"sync_timeout": 30
}

2、声音克隆-手动情感向量(悲伤为主)

{
	"task": "/v1/ai_audio_engine/481991",
	"task_type": "formula",
	"init_images": [{
		"url": "http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3",
		"profile": {
			"media_profiles": {
				"media_data_type": "url"
			},
			"version": "v1"
		}
	}],
	"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"task_type\":\"synth_once\",\"text\":\"今天天气真不错,你怎么知道的?\",\"emo_control_method\":1,\"emo_vec\":[0,0,0.55,0,0,0,0,0]}}",
	"sync_timeout": 30
}

3、声音克隆-独立情感参考音频

{
	"task": "/v1/ai_audio_engine/481991",
	"task_type": "formula",
	"init_images": [{
		"url": "http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3",
		"profile": {
			"media_profiles": {
				"media_data_type": "url"
			},
			"version": "v1"
		}
	}],
	"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"task_type\":\"synth_once\",\"text\":\"今天天气真不错,你怎么知道的?\",\"emo_control_method\":2,\"emo_ref_path\":\"https://example.com/emo_ref.wav\",\"emo_weight\":0.8}}",
	"sync_timeout": 30
}

返回值说明

注意,生成的结果,会定期清理,请及时下载保存
字段类型说明
request_idstring请求的标识
trace_idstring链路追踪 ID
codeint接口返回的业务状态码。0 表示成功,非 0 表示失败
error_codeint详细错误码(通常与 code 配合使用),0 表示无错误。
messagestring接口返回的提示信息,一般在成功时为 "success",失败时为错误描述
tipsany补充提示,可为 null
dataobject具体业务数据

data 中单个元素的字段说明

字段类型说明
statusint状态码:-1 未找到任务;0 创建成功;1 执行中;2 失败;9 超时,使用查询接口查询;10 成功
resultobject任务结果信息
progressnumber任务进度
predict_elapsedint预计耗时,毫秒
create_timeint64任务创建时间的时间戳(毫秒)
task_idstring系统生成的任务 ID,唯一标识该任务
custom_task_idstring用户自定义任务 ID(若创建任务时传入)
trace_idstring链路追踪 ID
client_infostring客户端信息
init_imagesobject[]/null输入媒体回显

result 中单个元素的字段说明

字段类型说明
idstring(示例中;原参数表标注 int)任务 ID
parametersobject任务结果信息
dataobject(示例中;原参数表标注 int)原参数表说明为预测耗时(秒);返回示例中为任务附加结果对象
msgstring(示例中;原参数表标注 long)任务信息
msg_idstring消息 ID

parameters 中单个元素的字段说明

字段类型说明
codeint0 为正常返回,非 0 为各种异常
nameStringrequest 的 user 参数
idStringJob_ID
created_timeString当前任务执行创建时间
updated_timeString当前任务执行结束时间
msgString当前任务执行的相关信息
out_srcString生成的音频文件
textString合成的文字

返回值示例

请求成功返回示例

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": "t_mt1a3i5n7bca14033a-6268-46ee-823e-c968beeb5b23",
            "parameters": {
                "clone_ori_path": "https://deepnet-baikal.obs.cn-north-4.myhuaweicloud.com/temporary/spliter/vocals_5c0e5136-ba21-42e9-b737-820e414bb0f1.wav",
                "code": 0,
                "create_time": "2025-09-30 17:34:09",
                "duration": 4.07,
                "id": "9939fbd5-7c74-47e1-9a71-d2130719bb71",
                "latency": 1.85,
                "msg": "success",
                "name": "0",
                "out_src": "https://deepnet-baikal.obs.cn-north-4.myhuaweicloud.com/temporary/zeroshot/9939fbd5-7c74-47e1-9a71-d2130719bb71_0.wav",
                "src": "https://action-public-release.obs.cn-north-4.myhuaweicloud.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3?AccessKeyId=7YW1EYVPMUCUAFBLPDIN\u0026Expires=1759311244\u0026Signature=MF5vq%2B9y357Sjn23NmjWS5SHkf4%3D",
                "text": "You’re drinking energy drinks? Babe, it’s time to level up.",
                "ts_info": {

                },
                "updated_time": "2025-09-30 17:34:11"
            },
            "data": {
                "duration": {
                    "alg_process_time": 2087,
                    "created_timestamp": 1759224849,
                    "pull_timestamp": 1759224849,
                    "repost_time": 0,
                    "upload_time": 0,
                    "waiting_time": 78
                },
                "error_code": 0,
                "error_msg": "success",
                "extra": {

                },
                "media_info_list": [

                ],
                "msg_id": "a27d3c85-adb1-44a5-79ff-r0072bef0160",
                "parameter": {
                    "clone_ori_path": "https://deepnet-baikal.obs.cn-north-4.myhuaweicloud.com/temporary/spliter/vocals_5c0e5136-ba21-42e9-b737-820e414bb0f1.wav",
                    "code": 0,
                    "create_time": "2025-09-30 17:34:09",
                    "duration": 4.07,
                    "id": "9939fbd5-7c74-47e1-9a71-d2130719bb71",
                    "latency": 1.85,
                    "msg": "success",
                    "name": "0",
                    "out_src": "https://deepnet-baikal.obs.cn-north-4.myhuaweicloud.com/temporary/zeroshot/9939fbd5-7c74-47e1-9a71-d2130719bb71_0.wav",
                    "src": "https://action-public-release.obs.cn-north-4.myhuaweicloud.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3?AccessKeyId=7YW1EYVPMUCUAFBLPDIN\u0026Expires=1759311244\u0026Signature=MF5vq%2B9y357Sjn23NmjWS5SHkf4%3D",
                    "text": "You’re drinking energy drinks? Babe, it’s time to level up.",
                    "ts_info": {

                    },
                    "updated_time": "2025-09-30 17:34:11"
                }
            },
            "msg": "success",
            "msg_id": "a27d3c85-adb1-44a5-79ff-r0072bef0160"
        },
        "progress": 1,
        "predict_elapsed": 10000,
        "create_time": 1759224844659,
        "task_id": "t_mt1a3i5n7bca14033a-6268-46ee-823e-c968beeb5b23",
        "custom_task_id": "",
        "trace_id": "e69535d2-23cd-40e3-bb27-addf15cd1457",
        "client_info": "",
        "init_images": null
    }
}

需要查询返回示例

使用 查询接口 查询 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
    }
}

请求失败返回示例

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
    }
}

当前API特有的错误代码与信息

ErrorCode状态代码错误信息说明

通用的错误代码与信息

详见 API 错误码

SDK 调用示例

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": "synth_once",
            "text": "我是你克隆的专属声音,快来用我制作视频吧。",
        },
    }
    payload = {
        "task": "/v1/ai_audio_engine/481991",
        "task_type": "formula",
        "init_images": [{
            "url": "http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3",
            "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/ai_audio_engine/481991",
  "task_type": "formula",
  "init_images": [{
    "url": "http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3",
    "profile": {
      "media_profiles": {"media_data_type": "url"},
      "version": "v1"
    }
  }],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"task_type\":\"synth_once\",\"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' => [
        'task_type' => 'synth_once',
        'text' => '我是你克隆的专属声音,快来用我制作视频吧。',
    ],
]);
$body = json_encode([
    'task' => '/v1/ai_audio_engine/481991',
    'task_type' => 'formula',
    'init_images' => [[
        'url' => 'http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3',
        '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/ai_audio_engine/481991\",\n" +
                "  \"task_type\": \"formula\",\n" +
                "  \"init_images\": [{\n" +
                "    \"url\": \"http://action-public.meitudata.com/voice_clone/68c12c8a20160928587d19j69h5423.mp3\",\n" +
                "    \"profile\": {\n" +
                "      \"media_profiles\": {\"media_data_type\": \"url\"},\n" +
                "      \"version\": \"v1\"\n" +
                "    }\n" +
                "  }],\n" +
                "  \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"task_type\\\":\\\"synth_once\\\",\\\"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);
        }
    }
}