AIUI文档中心
AIUI平台说明
什么是AIUI
AIUI平台能力介绍
AIUI交互流程说明
AIUI快速入门
AIUI应用管理说明
应用接入和配置
应用后处理
敏感词
AIUI开发接入
AIUI接入概述
声学接入
交互接入
SDK接入
SDK介绍
参数配置
消息事件
交互状态
结果解析
WebSocketAPI接入
精简协议接入
常用功能
交互控制
语音唤醒
语音合成
用户个性化
自定义参数
离线命令词
翻译模式
流式识别
语义VAD
发音人列表
关键词过滤
情景模式
错误码
星火交互认知大模型说明
大模型概述
开发接入
SDK接入
API接入
大模型API服务鉴权
特色能力
超拟人合成
声音复刻
大模型功能
大模型错误码
软硬件产品接入
RK3328 降噪板
RK3328降噪板白皮书
RK3328降噪板使用手册
RK3328降噪板规格书
RK3328降噪板协议手册
RK3328 AIUI评估板开发套件
RK3328评估板白皮书
RK3328评估板使用手册
RK3328评估板规格书
RK3328评估板开发手册
RK3588 AIUI多模态开发套件
RK3588一体机多模态产品规格书
RK3588多模态套件使用手册
视频传输协议
串口通信协议
音频传输协议
ZG803 离线语音识别套件
ZG803 产品白皮书
USB声卡套件
USB声卡产品白皮书
USB声卡使用指南
AC7911 AIUI语音开发套件
AC7911-产品白皮书
AC7911-快速体验指南
AC7911-开发指南
AC7911-协议手册
AC7911-硬件参数
AIUI评估板接入
集成方式
软件包说明
AIUIServiceKitSDK
串口SDK
评估板参数配置
调试升级
技能工作室
技能概述
名词解析
技能
意图和语料
实体
动态实体
模糊匹配
填槽对话
技能设计规范
语音技能设计规范
开放技能接入审核规范
开放技能图标图片规范
技能开发
创建技能和意图
意图配置
技能测试
技能发布
技能后处理
技能导入导出
云函数APIv2.1
云函数APIv2.0
问答库开发
语句问答
关键词问答
文档问答
设备人设开发
技能协议
语义协议:重要字段和通用字段
技能后处理协议:标准请求
技能后处理协议:请求校验
技能后处理协议:Request_v2.1协议
技能后处理协议:Response_v2.1协议
技能资源限制
硬件设计参考
常见问题
AIUI常见问题
评估板常见问题
动态实体常见问题
联系方式
服务条款
AIUI开放平台服务协议
AIUI开放平台隐私政策
小飞在家用户协议
小飞在家隐私政策
小飞在家开源软件使用许可
讯飞账号隐私政策
讯飞账号用户协议
讯飞带屏音箱用户协议
讯飞带屏音箱隐私政策
AIUI SDK隐私政策
AIUI SDK合规使用说明
本文档使用 MrDoc 发布
-
+
首页
声音复刻
**目 录** 1. 能力介绍 2. 准备工作 2.1. 能力接入 2.2. 合成结果下发说明 2.3. 授权申请 3. 能力使用 3.1. SDK集成 3.1.1. 资源注册 3.1.2. 资源删除 3.1.3. 合成调用 3.2. API集成 3.2.1. 资源注册 3.2.2. 资源删除 3.2.3. 合成调用 4. 错误码 ## 1. 能力介绍 录入一段音频生成AI定制音色。 ## 2. 准备工作 ### 2.1. 能力接入 (1)配置aiui交互大模型(AIUI应用配置下开启) (2)SDK集成:SDK版本<span style="color:red">**不低于 6.6.0001.0041**</span>,且aiui.cfg中指定交互大模型链路,即 <span style="color:red">**aiui_ver:2**</span> (3)API集成:资源注册和删除,接口见下方文档;合成调用使用[大模型接入API](https://aiui-doc.xf-yun.com/project-1/doc-181/)接口实现 ### 2.2. 合成结果说明 声音复刻仅支持下发音频流,不支持url ### 2.3. 授权申请 - 联系商务或发送邮件到 aiui_support@iflytek.com ## 3. 能力使用 >注意: ><span style="color:red">1、声音复刻仅支持主动文本合成</span> ><span style="color:red">2、每个设备(SN)最多注册3个资源id</span> ### 3.1. SDK集成 #### 3.1.1. 资源注册 > <span style="color:red">**注意:**</span> **使应用端需要自行存储res_id,避免丢失。另外注册音频的采样率为 24k。** - 加载音频文件注册,音频要求: > 时长: 建议20s~40s > 文件大小范围:[480KB, 3MB] > 采样率: 24000 > 通道数: 1 > 位深: 16 > 编码格式: 裸音频pcm - 接口调用方式如下(Android示例): ```java // 注册音频保存的路径 String path = ""; JSONObject paramsJson = new JSONObject(); paramsJson.put(AIUIConstant.KEY_RES_PATH, path); // 构建注册事件 AIUIMessage regVoice = new AIUIMessage(AIUIConstant.CMD_VOICE_CLONE,AIUIConstant.VOICE_CLONE_REG, 0, paramsJson.toString(), null); mAIUIAgent.sendMessage(regVoice); ``` - 回调结果处理(Android示例): ```java /** * AIUI 回调 */ private final AIUIListener mAIUIListener = new AIUIListener() { @Override public void onEvent(AIUIEvent aiuiEvent) { switch (aiuiEvent.eventType) { // 声音复刻:资源注册和删除回调 case AIUIConstant.EVENT_CMD_RETURN: { if (aiuiEvent.arg1 == AIUIConstant.CMD_VOICE_CLONE) { int retCode = aiuiEvent.arg2; int dtype = aiuiEvent.data.getInt(AIUIConstant.KEY_SYNC_DTYPE, -1); if (dtype == AIUIConstant.VOICE_CLONE_REG) { // 声音注册结果 if (retCode == AIUIConstant.SUCCESS) { String resId = aiuiEvent.data.getString(AIUIConstant.KEY_RES_ID, ""); showTip("注册成功,res_id=" + resId); } else { showTip("注册失败,error=" + retCode); } } else if (dtype == AIUIConstant.VOICE_CLONE_DEL) { // 声音删除结果 if (retCode == AIUIConstant.SUCCESS) { showTip("删除成功"); } else { showTip("删除失败,error=" + retCode); } } } } } } }; ``` #### 3.1.2. 资源删除 - Android示例: ```java // 注册好的资源id String mCurResId = "resID"; JSONObject paramsJson = new JSONObject(); paramsJson.put(AIUIConstant.KEY_RES_ID, mCurResId); // 构建资源删除事件 AIUIMessage delVoice = new AIUIMessage(AIUIConstant.CMD_VOICE_CLONE, AIUIConstant.VOICE_CLONE_DEL, 0, paramsJson.toString(), null); mAIUIAgent.sendMessage(delVoice); ``` - 删除结果见 “3.1.1. 资源注册”。 #### 3.1.3. 合成调用 请求合成,需配置参数vcn、res_id。 - Android示例: ```java // 注册好的资源id String mCurResId = "resID"; String text = "你好"; // 声音复刻vcn固定x5_clone,附带res_id String params = "vcn=x5_clone,res_id=" + mCurResId; byte[] textData = text.getBytes("utf-8"); AIUIMessage startTTS = new AIUIMessage(AIUIConstant.CMD_TTS, AIUIConstant.START, 0,params,textData); mAIUIAgent.sendMessage(startTTS); ``` ### 3.2. API集成 - 请求地址: ```java http[s]://aiui.xf-yun.com ``` - 鉴权方式: 详见[鉴权文档](https://aiui-doc.xf-yun.com/project-1/doc-404/)说明 - Demo [点击查看](https://gitee.com/iflytek-aiui/AIUICbmLiteDemo/tree/master/res-mngr/voice-clone "点击下载") #### 3.2.1. 资源注册 根据用户输入的音频进行声音复刻,返回资源id。1个SN最多注册3个资源。 - METHOD: POST - PATH: /v2/aiint/voice-clone/sgen/reg - Content-Type: multipart/form-data - HTTP 请求示例: ```java POST /v2/aiint/voice-clone/sgen/reg HTTP/1.1 Host: 127.0.0.1:9996 Content-Length: 412 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="appid" 5c8b403a ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="sn" 12334454543dfsdfsf ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="data"; filename="/D:/文件/tts/2-正常音色文件-zzy.pcm" Content-Type: <Content-Type header here> (data) ------WebKitFormBoundary7MA4YWxkTrZu0gW-- ``` 表单参数说明 | 参数名 | 类型 | 说明 | 必需 | 示例 | | ------ | ------ | ---------------------------------- | ---- | ------------------ | | appid | string | AIUI应用appid | 是 | 5c8b403a | | sn | string | 设备sn号,长度不超过32位 | 是 | 12334454543dfsdfsf | | data | file | 音频文件 | 是 | - | 返回值示例: ```json { "sid": "xxx", "code": 0, "msg": "success", "data": { "res_id": "fsdfwee234324" } } ``` 返回值字段说明 | 参数名 | 类型 | 说明 | 必需 | 示例 | | ---------- | ----- | ------------- | ---- | ----------- | | sid | string | 请求标识 | 是 | - | | code | int | 状态码,0 成功,非0表示请求处理失败 | 是 | 0 | | msg | string | 描述 | 是 | - | | data | object | 返回数据 | 否 | - | | data.res_id | string | 资源id| 否 | fsdfwee234324 | #### 3.2.2. 指定id,删除资源 - METHOD: DELETE - PATH: /v2/aiint/voice-clone/sgen/del - Content-Type: application/json - 请求体示例: ```json { "appid": "5c8b403a", "sn": "12334454543dfsdfsf", "res_id": "fsdfwee234324" } ``` 返回值: ```json { "sid": "xxx", "code": 0, "msg": "success", "data": null } ``` #### 3.2.3. 合成调用 合成调用还是基于[AIUI交互大模型API](https://aiui-doc.xf-yun.com/project-1/doc-181/ "AIUI交互大模型API")接口实现,与其他(一般合成、超拟人合成)相比,主要参数区别如下: - scene 固定 IFLYTEK.tts - vcn 固定 x5_clone - res_id 取值为SN注册的资源id 构建请求json如下 ```json { "header": { "sn": "1234567890", "appid": "a44e0f36", "stmid": "text-1", "status": 3, "scene": "IFLYTEK.tts" }, "parameter": { "tts": { "vcn": "x5_clone", "res_id": "fsdfwee234324", "tts": { "channels": 1, "sample_rate": 16000, "bit_depth": 16, "encoding": "raw" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "text": "5omT55S16K+d57uZ5byg5LiJ", "encoding": "utf8", "status": 3 } } } ``` <details> <summary>点击查看示例代码(python)</summary> ``` import _thread as thread import base64 import datetime import hashlib import hmac import json from urllib.parse import urlparse import time from datetime import datetime from time import mktime from urllib.parse import urlencode from wsgiref.handlers import format_date_time import websocket ## 修改应用应用配置后直接执行即可 # 请求地址 url = "wss://aiui.xf-yun.com/v2/aiint/ws" appid = "xxx" api_key = "xxx" api_secret = "xxx" # 场景 scene = "IFLYTEK.tts" # scene = "main_box" # 请求类型用来设置文本请求还是音频请求,text/audio data_type = 'text' # 请求文本 question = "今天晚上吃点啥好呢,是酱香饼还是麻酱拌凉皮" # 每帧音频数据大小,单位字节 chuncked_size = 1024 audio_save_fp = open('D:\save_hts_audio.pcm', mode='wb+') class AIUIV2WsClient(object): # 初始化 def __init__(self): self.handshake = self.assemble_auth_url(url) # 生成握手url def assemble_auth_url(self, base_url): host = urlparse(base_url).netloc path = urlparse(base_url).path # 生成RFC1123格式的时间戳 now = datetime.now() date = format_date_time(mktime(now.timetuple())) # 拼接字符串 signature_origin = "host: " + host + "\n" signature_origin += "date: " + date + "\n" signature_origin += "GET " + path + " HTTP/1.1" # 进行hmac-sha256进行加密 print(signature_origin) signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'), digestmod=hashlib.sha256).digest() signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8') authorization_origin = f'api_key="{api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"' print('get authorization_origin:', authorization_origin) authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8') # 将请求的鉴权参数组合为字典 v = { "host": host, "date": date, "authorization": authorization, } # 拼接鉴权参数,生成url url = base_url + '?' + urlencode(v) # 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释,比对相同参数时生成的url与自己代码生成的url是否一致 return url def on_open(self, ws): # 连接建立成功后开始发送数据 print("### ws connect open") thread.start_new_thread(self.run, ()) def run(self): if data_type == "text": self.text_req() def text_req(self): aiui_data = { "header": { "sn":"1234567891", "app_id": appid, "stmid": "text-1", "status": 3, "scene": scene, "pers_param":"{\"appid\":\"\",\"uid\":\"iflytek-test\"}" }, "parameter": { "nlp": { "nlp": { "compress": "raw", "format": "json", "encoding": "utf8" }, # 动态实体 "sub_scene": "cbm_v45", "new_session": True }, "tts": { "vcn": "x5_clone", "res_id": "fsdfwee234324", "tts": { "channels": 1, "sample_rate": 16000, "bit_depth": 16, "encoding": "raw" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "text": base64.b64encode(question.encode('utf-8')).decode('utf-8'), "encoding": "utf8", "status": 3 } } } data = json.dumps(aiui_data, indent=2) print('--------text request data--------\n', data,'\n--------text request data--------\n') self.ws.send(data) # 收到websocket消息的处理 def on_message(self, ws, message): data = json.loads(message) # print('原始结果:', message) header = data['header'] code = header['code'] # 结果解析 if code != 0: print('请求错误:', code, json.dumps(data, ensure_ascii=False)) ws.close() if 'nlp' in message: nlp_json = data['payload']['nlp'] nlp_text_bs64 = nlp_json['text'] nlp_text = base64.b64decode(nlp_text_bs64).decode('utf-8') nlp_all = json.dumps(data,indent=2) # print("--------nlp--------\n" , nlp_all) # print("语义结果:",nlp_text,"--------nlp--------\n") if 'tts' in message: tts_all = json.dumps(data,indent=2) print("--------hts_all--------\n",tts_all,"\n--------hts_all_all--------\n") tts_audio = data['payload']['tts']['audio'] tts_content = base64.b64decode(tts_audio) audio_save_fp.write(tts_content) if 'status' in header and header['status'] == 2: # 接受最后一帧结果,关闭连接 ws.close() def on_error(self, ws, error): print("### connection error: " + error) ws.close() def on_close(self, ws, close_status_code, close_msg): print("### connection is closed ###, cloce code:" + str(close_status_code)) def start(self): self.ws = websocket.WebSocketApp( self.handshake, on_open=self.on_open, on_message=self.on_message, on_error=self.on_error, on_close=self.on_close, ) self.ws.run_forever() if __name__ == "__main__": client = AIUIV2WsClient() client.start() ``` </details> ## 4. 错误码 | 错误码 | 说明 | | :----- | :------------------------------------- | | 900400 | 参数非法 | | 900401 | 应用鉴权异常 | | 900402 | 授权已经用完,复刻资源数量已经达到上限 | | 900404 | 资源不存在 | | 900500 | 内部服务错误 | | 900501 | 数据库异常 | | 900601 | 声音复刻失败 |
admin
2024年11月1日 14:41
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码