AIUI文档中心
AIUI文档导览
1. AIUI平台服务
1.1 AIUI平台介绍
1.2 AIUI应用介绍
1.3 AIUI服务链路介绍
1.4 AIUI平台能力概述
1.5 快速体验
2. AIUI应用配置
2.1 应用发布
2.2 语义精简协议介绍
2.3 基础配置
2.4 语义模型配置
2.5 回复角色配置
2.6 语音识别配置
2.7 结构化语义配置
2.8 星火大模型配置
2.9 语音合成配置
2.10 应用后处理配置
2.11 三方大模型配置
2.12 流畅全双工交互配置
2.13 表情标签配置
2.14 长时记忆配置
2.15 声纹识别配置
3. AIUI SDK开发
3.1 AIUI SDK接入流程
3.2 AIUI SDK基础信息
3.2.1 SDK接口说明
3.2.2 参数配置说明
3.2.3 消息事件说明
3.2.4 SDK状态说明
3.2.5 数据发送方式
3.2.6 回调解析说明
3.2.7 交互结果协议说明
3.3 AIUI SDK基础能力
3.3.1 流式识别
3.3.2 离线识别
3.3.3 语音唤醒
3.3.4 语音合成
3.3.5 用户个性化
3.3.6 自定义参数
3.4 传统语义链路接入
3.4.1 链路配置说明
3.4.2 个性化数据使用
3.5 通用大模型链路接入
3.5.1 链路配置说明
3.5.2 个性化数据使用
3.5.3 超拟人合成
3.5.4 声音复刻
3.6 极速超拟人链路接入
3.6.1 链路配置说明
3.6.2 个性化数据使用
3.6.3 流式合成
3.6.4 声音复刻
3.6.5 RTOS系统SDK接入
3.7 错误码列表
3.8 发音人列表
4. AIUI API开发
4.1 传统语义链路
4.1.1 交互API
4.1.2 用户个性化API
4.1.3 合成能力使用
4.2 通用大模型链路
4.2.1 服务鉴权
4.2.2 交互API
4.2.3 用户个性化API
4.2.4 声音复刻API
4.2.5 合成能力使用
4.3 极速超拟人链路
4.3.1 服务鉴权
4.3.2 交互API
4.3.3 用户个性化API
4.3.4 声音复刻API
4.3.5 合成能力使用
4.3.6 声纹管理API
5. 自定义业务
技能工作室概述
名词解析
技能
意图和语料
实体
动态实体
模糊匹配
填槽对话
技能设计规范
语音技能设计规范
开放技能接入审核规范
开放技能图标图片规范
技能开发
创建技能和意图
意图配置
技能测试
技能发布
技能后处理
技能导入导出
云函数APIv2.1
云函数APIv2.0
智能体开发
智能体对接
问答库开发
语句问答
关键词问答
文档问答
设备人设开发
技能协议
语义协议:重要字段和通用字段
技能后处理协议:标准请求
技能后处理协议:请求校验
技能后处理协议:Request_v2.1协议
技能后处理协议:Response_v2.1协议
技能资源限制
6. 硬件模组
RK3328 降噪板
RK3328降噪板白皮书
RK3328降噪板使用手册
RK3328降噪板规格书
RK3328降噪板协议手册
RK3328 AIUI评估板开发套件
RK3328评估板白皮书
RK3328评估板使用手册
RK3328评估板规格书
RK3328评估板开发手册
RK3588s 极简通用多模态开发套件
RK3588s 极简多模态套件白皮书
RK3588s 极简多模态套件使用手册
RK3588 AIUI多模态开发套件
RK3588一体机多模态产品规格书
RK3588多模态套件使用手册
视频传输协议
识别语义传输协议
音频传输协议
AIUI类型消息事件
ZG803 离线语音识别套件
ZG803 产品白皮书
USB声卡套件
USB声卡产品白皮书
USB声卡使用指南
AC7911B AIUI语音开发套件
AC7911B-产品白皮书
AC7911B-快速体验指南
AIUI评估板接入
集成方式
软件包说明
AIUIServiceKitSDK
串口SDK
评估板参数配置
调试升级
7. 常见问题处理
7.1 AIUI常见问题
7.2 评估板常见问题
7.3 动态实体常见问题
8. 联系方式
9. 服务条款
AIUI开放平台服务协议
AIUI开放平台隐私政策
小飞在家用户协议
小飞在家隐私政策
小飞在家开源软件使用许可
讯飞账号隐私政策
讯飞账号用户协议
讯飞带屏音箱用户协议
讯飞带屏音箱隐私政策
AIUI SDK隐私政策
AIUI SDK合规使用说明
本文档使用 MrDoc 发布
-
+
首页
4.3.5 合成能力使用
<div style="max-width: 100%; margin: 20px auto;"> <!-- 便签卡片容器 --> <div style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); overflow: hidden; font-family: 'Comic Sans MS', cursive, sans-serif;"> <!-- 便签头部 --> <div style="background-color: #F4F8FA; padding: 1px 10px; border-bottom: 1px solid #dee2e6; display: flex; justify-content: space-between; align-items: center;"> <div style="color: #0E42D2; font-weight: bold;font-size: 1.3rem;">合成能力使用概述</div> <div> </div> </div> <!-- 带横线的内容区域 --> <div style="padding: 25px; line-height: 29px; background-image: linear-gradient(transparent 26px, #dee2e6 27px, #dee2e6 27px, transparent 27px); background-size: 100% 28px; min-height: 100px; color: #333;"> <div>本文档主要介绍在<strong>极速超拟人交互链路</strong>下使用API协议进行主动合成服务调用说明。</div> <div style="color: #333; font-weight: bold;font-size: 0.9rem;">合成类型主要包括: </div> <a href="#通用合成调用" style="color: #6f42c1; font-weight: 500;"> <strong>- 1、通用合成调用>>>点击跳转   </strong></a> <a href="#超拟人合成调用" style="color: #6f42c1; font-weight: 500;"> <br><strong>- 2、超拟人合成调用>>>点击跳转   </strong></a> <a href="#声音复刻合成调用" style="color: #6f42c1; font-weight: 500;"> <br><strong>- 3、声音复刻合成调用>>>点击跳转   </strong></a> <a href="#极速超拟人合成调用" style="color: #6f42c1; font-weight: 500;"> <br><strong>- 4、极速超拟人合成调用>>>点击跳转   </strong></a> <a href="#流式合成调用" style="color: #6f42c1; font-weight: 500;"> <br><strong>- 5、流式合成调用>>>点击跳转   </strong></a> <div></div> </div> <!-- 便签底部 --> </div> </div> </div> ## 1. 调用说明 <div style="display: flex; align-items: flex-start; gap: 16px; padding: 16px; background: #fff5f6; border-radius: 5px; border-left: 4px solid #e83e8c; box-shadow: 0 4px 12px rgba(255, 215, 0, 0.08); margin-bottom: 16px; transition: transform 0.2s ease, box-shadow 0.2s ease;"> <div> <div style="font-weight: 600; margin-bottom: 4px;">温馨提示</div> <div style="font-size: 14px; line-height: 1.5;">1、极速超拟人链路新增流式合成能力,是需要绑定使<b>极速超拟人发音人</b>才可以,其他类别发音人不支持使用</div> </div> </div> <div id="通用合成调用"> </div> ### 1.1 通用合成 **该合成类型指的是使用`普通发音人`进行文本合成,合成文本需`一帧发送完毕`。** #### 1.1.1 确认参数 普通类发音人除部分免费外,其它发音人需要联系讯飞商务授权,具体发音人信息见【[发音人列表](https://aiui-doc.xf-yun.com/project-1/doc-93/ "发音人列表")】。 示例普通发音人:小娟 - vcn:**x2_xiaojuan** 情景模式固定取值: - scene:**IFLYTEK.tts** #### 1.1.2 请求构建 `header.status` 和 `payload.text.status` 取值保持一致,可以是 **2 或 3**。 `构建请求`如下: ``` json { "header": { "sn": "1234567890", "appid": "a44e0f36", "stmid": "text-1", "interact_mode": "oneshot", // 文本类请求固定传oneshot "status": 3, "scene": "IFLYTEK.tts" // 文本合成类请求固定取值(注意超拟人合成时取值方式) }, "parameter": { "tts": { "vcn": "x2_xiaojuan", // 普通发音人取值 "speed": 50, "volume": 50, "pitch": 50, "tts": { "channels": 1, "sample_rate": 16000, "bit_depth": 16, "encoding": "raw" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "text": "5omT55S16K+d57uZ5byg5LiJ", // 待合成文本:需经过base64编码 "encoding": "utf8", "status": 3 } } } ``` <div id="超拟人合成调用"> </div> ### 1.2 超拟人合成 **该合成类型指的是使用`超拟人发音人`进行文本合成,合成文本需`一帧发送完毕`。** #### 1.2.1 确认参数 在极速超拟人链路下,所有超拟人也都免费开放开发者使用。各超拟人发音人信息见【[发音人列表](https://aiui-doc.xf-yun.com/project-1/doc-93/ "发音人列表")】。 示例超拟人发音人:聆小琪 - vcn:**x4_lingxiaoqi_oral** 情景模式固定取值: - scene:**IFLYTEK.tts** #### 1.2.2 请求构建 `header.status` 和 `payload.text.status` 取值保持一致,可以是 **2 或 3**。 `构建请求`如下: ``` json { "header": { "sn": "1234567890", "appid": "a44e0f36", "stmid": "text-1", "interact_mode": "oneshot", // 文本类请求固定传oneshot "status": 3, "scene": "IFLYTEK.tts" // 超拟人合成固定传值 }, "parameter": { "tts": { "vcn": "x4_lingxiaoqi_oral", // 超拟人发音人取值 "speed": 50, "volume": 50, "pitch": 50, "tts": { "channels": 1, "sample_rate": 16000, "bit_depth": 16, "encoding": "raw" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "text": "5omT55S16K+d57uZ5byg5LiJ", // 待合成文本:需经过base64编码 "encoding": "utf8", "status": 3 } } } ``` <div id="声音复刻合成调用"> </div> ### 1.3 声音复刻合成 **该合成类型指的是使用`声音复刻创建的发音人`进行文本合成,合成文本除默认支持的`一帧发送完毕`,现升级也支持`分帧发送`。** - 合成文本整帧合成调用见下方说明 - 合成文本分帧发送调用参考本章节<a href="#流式合成调用" style="color: #6f42c1; font-weight: 500;"><strong>【1.5 流式合成】</strong></a>说明 #### 1.3.1 确认参数 声音复刻合成类请求,首先需要开发者按照`声音复刻API`注册获取资源id(`res_id`),资源注册详见【[4.3.4 声音复刻API](https://aiui-doc.xf-yun.com/project-1/doc-413/ "4.3.4 声音复刻API")】说明。 声音复刻合成参数示例: - vcn: - **x5_clone** // 声音复刻v4版本资源使用时,固定取值 - **x6_clone** // 声音复刻omni_v版本资源使用时,固定取值 - res_id:**fsdfwee234324** // 创建的资源id - scene:**IFLYTEK.tts** // 固定取值 #### 1.3.2 请求构建 `header.status` 和 `payload.text.status` 取值保持一致,可以是 **2 或 3**。 `构建请求`如下: ``` json { "header": { "sn": "1234567890", // 与资源注册sn保持一致 "appid": "a44e0f36", // 与资源注册appid保持一致 "stmid": "text-1", "interact_mode": "oneshot", // 文本类请求固定传oneshot "status": 3, "scene": "IFLYTEK.tts" }, "parameter": { "tts": { "vcn": "x5_clone", // 声音复刻合成固定传值 "res_id": "fsdfwee234324", // 声音复刻资源id "speed": 50, "volume": 50, "pitch": 50, "tts": { "channels": 1, "sample_rate": 16000, "bit_depth": 16, "encoding": "raw" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "text": "5omT55S16K+d57uZ5byg5LiJ", // 待合成文本:需经过base64编码 "encoding": "utf8", "status": 3 } } } ``` <div id="极速超拟人合成调用"> </div> ### 1.4 极速超拟人合成 **该合成类型指的是使用`极速超拟人发音人`进行文本合成,合成文本除默认支持的`一帧发送完毕`,也支持`分帧发送`。** - 合成文本整帧合成调用见下方说明 - 合成文本分帧发送调用参考本章节<a href="#流式合成调用" style="color: #6f42c1; font-weight: 500;"><strong>【1.5 流式合成】</strong></a>说明 #### 1.4.1 确认参数 在极速超拟人链路下,所有极速超拟人都是免费开放开发者使用。各极速超拟人发音人信息见【[发音人列表](https://aiui-doc.xf-yun.com/project-1/doc-93/ "发音人列表")】。 示例极速超拟人发音人:聆小玥 - vcn:**x5_lingxiaoyue_flow** 情景模式固定取值: - scene:**IFLYTEK.tts** #### 1.4.2 请求构建 `header.status` 和 `payload.text.status` 取值保持一致,可以是 **2 或 3**。 `构建请求`如下: ``` json { "header": { "sn": "1234567890", "appid": "a44e0f36", "stmid": "text-1", "interact_mode": "oneshot", // 文本类请求固定传oneshot "status": 3, "scene": "IFLYTEK.tts" // 超拟人合成固定传值 }, "parameter": { "tts": { "vcn": "x5_lingxiaoyue_flow", // 极速超拟人发音人取值 "speed": 50, "volume": 50, "pitch": 50, "tts": { "channels": 1, "sample_rate": 16000, "bit_depth": 16, "encoding": "raw" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "text": "5omT55S16K+d57uZ5byg5LiJ", // 待合成文本:需经过base64编码 "encoding": "utf8", "status": 3 } } } ``` <div id="流式合成调用"> </div> ### 1.5 流式合成 `流式合成`即使用特定发音人对合成文本进行分帧发送,常用于大模型流式输出的文本合成实现。现阶段支持流式合成方式的发音人类型有: - **`极速超拟人`** - **`声音复刻`** #### 1.5.1 确认参数 类型1:使用极速超拟人发音人 - vcn:**x5_lingxiaoyue_flow** // 聆小玥 - scene:**IFLYTEK.tts** // 固定取值 类型2:使用声音复刻发音人 - vcn: - **x5_clone** // 声音复刻v4版本资源使用时,固定取值 - **x6_clone** // 声音复刻omni_v版本资源使用时,固定取值 - res_id:**fsdfwee234324** // 创建的资源id - scene:**IFLYTEK.tts** // 固定取值 #### 1.5.2 请求构建 <div style="display: flex; align-items: flex-start; gap: 16px; padding: 16px; background: #fff5f6; border-radius: 5px; border-left: 4px solid #e83e8c; box-shadow: 0 4px 12px rgba(255, 215, 0, 0.08); margin-bottom: 16px; transition: transform 0.2s ease, box-shadow 0.2s ease;"> <div> <div style="font-weight: 600; margin-bottom: 4px;">温馨提示</div> <div style="font-size: 14px; line-height: 1.5;">1、<b>header.status</b> 和 <b>payload.text.status</b> 取值保持一致,首帧传值0,中间帧传1,尾帧传2。</div> <div style="font-size: 14px; line-height: 1.5;">2、与极速通用协议中间帧可省略参数(parameter)不一样,<b>流式合成每一帧都需要携带参数。</b></div> </div> </div> `构建请求`如下: ``` json 示例分段合成文本如下: {"好嘞,","音量已经","调到一半","啦。"} 首帧:【header.status=0,payload.text.status=0】 {"payload":{"text":{"format":"plain","text":"5aW95Zie77yM","encoding":"utf8","status":0}},"parameter":{"tts":{"vcn":"x5_lingxiaoyue_flow","volume":100,"tts":{"sample_rate":16000,"channels":1,"encoding":"lame","bit_depth":16},"pitch":50,"speed":50}},"header":{"appid":"6bd8c032","sn":"d275e4eba6080fyh","stmid":"text-1","interact_mode":"oneshot","status":0,"scene":"IFLYTEK.tts"}} 中间帧:【header.status=1,payload.text.status=1】 {"payload":{"text":{"format":"plain","text":"6Z+z6YeP5bey57uP","encoding":"utf8","status":1}},"parameter":{"tts":{"vcn":"x5_lingxiaoyue_flow","volume":100,"tts":{"sample_rate":16000,"channels":1,"encoding":"lame","bit_depth":16},"pitch":50,"speed":50}},"header":{"appid":"6bd8c032","sn":"d275e4eba6080fyh","stmid":"text-1","interact_mode":"oneshot","status":1,"scene":"IFLYTEK.tts"}} {"payload":{"text":{"format":"plain","text":"6LCD5Yiw5LiA5Y2K","encoding":"utf8","status":1}},"parameter":{"tts":{"vcn":"x5_lingxiaoyue_flow","volume":100,"tts":{"sample_rate":16000,"channels":1,"encoding":"lame","bit_depth":16},"pitch":50,"speed":50}},"header":{"appid":"6bd8c032","sn":"d275e4eba6080fyh","stmid":"text-1","interact_mode":"oneshot","status":1,"scene":"IFLYTEK.tts"}} 尾帧:【header.status=2,payload.text.status=2】 {"payload":{"text":{"format":"plain","text":"5ZWm44CC","encoding":"utf8","status":2}},"parameter":{"tts":{"vcn":"x5_lingxiaoyue_flow","volume":100,"tts":{"sample_rate":16000,"channels":1,"encoding":"lame","bit_depth":16},"pitch":50,"speed":50}},"header":{"appid":"6bd8c032","sn":"d275e4eba6080fyh","stmid":"text-1","interact_mode":"oneshot","status":2,"scene":"IFLYTEK.tts"}} ``` ## 2. 示例代码 下面提供`极速超拟人链路流式合成`调用示例,开发者配置自己的应用信息即可体验 <details> <summary>点击查看python代码</summary> ``` python import _thread as thread import base64 import datetime import hashlib import hmac import json import traceback 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/v3/aiint/sos" # 应用配置 appid = "" api_key = "" api_secret = "" sn="test-sn" # 场景 scene = "IFLYTEK.tts" vcn = "x5_lingxiaoyue_flow" # 请求类型用来设置文本请求还是音频请求,text/audio data_type = 'text' ## 音频请求需要先设置audio_path ## 当前音频格式默认pcm 16k 16bit,修改音频格式需要修改audioReq中的payload中音频相关参数 # data_type = 'audio' # 音频请求上传的音频文件路径:示例 audio_path = "D:/weather.pcm" # 文本请求输入的文本 question = "你是谁,明天下雨吗" # 流式合成文本数据 usePgsTts = True ttsTextList = ["好嘞,","音量已经","调到一半","啦。"] # 下面两个参数配合音频采样率设置,16k 16bit的音频: 每 40毫秒 发送 1280字节 # 每帧音频数据大小,单位字节 frame_size = 1280 # 每帧音频发送间隔 sleep_inetrval = 0.04 class AIUIV3WsClient(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() if data_type == "audio": self.audio_req() def text_req(self): # 流式合成 if "IFLYTEK.tts" == scene and usePgsTts: for index, item in enumerate(ttsTextList): if index == 0: # 首帧文本 0 req = self.genTextReq(item, 0) elif index == len(ttsTextList) - 1: # 尾帧文本 2 req = self.genTextReq(item, 2) else: # 中间帧文本 1 req = self.genTextReq(item, 1) self.ws.send(req) else: req = self.genTextReq(question, 2) self.ws.send(req) def audio_req(self): f = open(audio_path, 'rb') try: f.seek(0, 2) eof = f.tell() f.seek(0, 0) first = True status = 0 while True: d = f.read(frame_size) if not d: break if f.tell() >= eof: # 尾帧 status = 2 elif not first: # 中间帧 status = 1 req = self.genAudioReq(d, status) first = False self.ws.send(req) # 发送间隔 time.sleep(sleep_inetrval) finally: f.close() def genTextReq(self, data, status): aiui_data = { "header": { "appid": appid, "sn": sn, "stmid": "text-1", "status": status, "scene": scene, "interact_mode": "oneshot" }, "parameter": { "nlp": { "nlp": { "compress": "raw", "format": "json", "encoding": "utf8" }, "new_session": True }, # 合成参数 "tts": { # 发音人 "vcn": vcn, "tts": { "channels": 1, "bit_depth": 16, "sample_rate": 16000, "encoding": "lame" } } }, "payload": { "text": { "compress": "raw", "format": "plain", "encoding": "utf8", "status": status, "text": base64.b64encode(data.encode('utf-8')).decode('utf-8') } } } return json.dumps(aiui_data) def genAudioReq(self, data, status): # 构造pcm音频请求参数 aiui_data = { "header": { "appid": appid, "sn": sn, "stmid": "audio-1", "status": status, "scene": scene, "interact_mode": "continuous" }, "parameter": { "nlp": { "nlp": { "compress": "raw", "format": "json", "encoding": "utf8" }, "new_session": True }, # 合成参数 "tts": { # 发音人 "vcn": vcn, "tts": { "channels": 1, "bit_depth": 16, "sample_rate": 16000, "encoding": "raw" } } }, "payload": { "audio": { "encoding": "raw", "sample_rate": 16000, "channels": 1, "bit_depth": 16, "status": status, "audio": base64.b64encode(data).decode(), } } } return json.dumps(aiui_data) # 收到websocket消息的处理 def on_message(self, ws, message): try: 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() sid = header.get('sid', "sid") payload = data.get('payload', {}) parameter = data.get('parameter', {}) if 'event' in payload: # 事件结果 event_json = payload['event'] event_text_bs64 = event_json['text'] event_text = base64.b64decode(event_text_bs64).decode('utf-8') print("事件,", event_text) if 'iat' in payload: # 识别结果 iat_json = payload['iat'] iat_text_bs64 = iat_json['text'] iat_text = base64.b64decode(iat_text_bs64).decode('utf-8') print("识别结果,seq:", iat_json['seq'], ",status:" , iat_json['status'], ",", self.parse_iat_result(iat_text)) if 'cbm_tidy' in payload: # 语义规整结果(历史改写),意图拆分 cbm_tidy_json = payload['cbm_tidy'] cbm_tidy_text_bs64 = cbm_tidy_json['text'] cbm_tidy_text = base64.b64decode(cbm_tidy_text_bs64).decode('utf-8') cbm_tidy_json = json.loads(cbm_tidy_text) print("语义规整结果:") intents = cbm_tidy_json['intent'] for intent in intents: print(" intent index:", intent['index'], ",意图语料:", intent['value']) if 'cbm_intent_domain' in payload: # 意图拆分后的落域结果 cbm_intent_domain_json = payload['cbm_intent_domain'] cbm_intent_domain_text_bs64 = cbm_intent_domain_json['text'] cbm_intent_domain_text = base64.b64decode(cbm_intent_domain_text_bs64).decode('utf-8') index = self.get_intent_index(parameter, "cbm_intent_domain") print("intent index:", index, ",落域结果:", cbm_intent_domain_text) if 'cbm_semantic' in payload: # 技能结果 cbm_semantic_json = payload['cbm_semantic'] cbm_semantic_text_bs64 = cbm_semantic_json['text'] cbm_semantic_text = base64.b64decode(cbm_semantic_text_bs64).decode('utf-8') cbm_semantic_json = json.loads(cbm_semantic_text) index = self.get_intent_index(parameter, "cbm_semantic") if cbm_semantic_json['rc'] != 0: print("intent index:", index, ",技能结果:说法:", cbm_semantic_json['text'], ",", cbm_semantic_text) else: print("intent index:", index, ",技能结果:说法:", cbm_semantic_json['text'], ",命中技能:", cbm_semantic_json['category'], ",回复:", cbm_semantic_json['answer']['text']) if 'nlp' in payload: # 语义结果,经过大模型润色的最终结果 nlp_json = payload['nlp'] nlp_text_bs64 = nlp_json['text'] nlp_text = base64.b64decode(nlp_text_bs64).decode('utf-8') print("语义结果 seq:", nlp_json['seq'], ",status:", nlp_json['status'], ",nlp.text: ", nlp_text) if 'tts' in payload: # 将结果保存到文件,文件后缀名需要根据tts参数中的encoding来决定 audioData = payload['tts']['audio'] if audioData != None: audioBytes = base64.b64decode(audioData) print("tts结果: ", len(audioBytes), " 字节") with open(sid + "." + self.get_suffix(payload['tts']['encoding']), 'ab') as file: file.write(audioBytes) if 'status' in header and header['status'] == 2: # 接收最后一帧结果,关闭连接 ws.close() except Exception as e: traceback.print_exc() pass def parse_iat_result(self, iat_res): iat_text = "" iat_res_json = json.loads(iat_res) for cw in iat_res_json['text']['ws']: for cw_item in cw["cw"]: iat_text += cw_item['w'] return iat_text def get_intent_index(self, parameter, key): if key in parameter: return parameter[key]['loc']['intent'] return "-" def get_suffix(self, encoding): if encoding == 'raw': return 'pcm' if encoding == 'lame': return 'mp3' return 'unknow' def on_error(self, ws, error): print("### connection error: ", str(error)) ws.close() def on_close(self, ws, close_status_code, close_msg): print("### connection is closed ###, cloce code:", 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 = AIUIV3WsClient() client.start() ``` </details>
admin
2026年2月4日 11:11
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码