本文最后更新于:2023年12月5日 下午

之前介绍了百度语音识别 API 的调用方法,本文记录科大讯飞 API 的使用方法。

简介

科大讯飞语音能力出众,在其开放平台上有丰富的语音应用。这里我主要使用短句语音听写功能。

产品优势

高识别率,高准确率:行业先进的语音识别技术,识别率可达98%

多方言,多语种: 除中文普通话和英文外,支持65个语种、24种方言和1个民族语言,提供四川话、广东话与普通话的混合识别

快速响应,毫秒级返回: 流式接口,实时传输。 响应速度可达毫秒级,用户边说边返回文字

定制训练,专属模型: 无需算法开发,简单上传常用词句。优化识别效果,提高个性化准确率

垂直行业,深度优化: 基于大量垂直领域语料,我们不断对模型进行训练

标点预测,动态修正: 根据中文对话语境,智能断句并匹配标点。动态识别内容,小颗粒返回修正结果

使用流程

准备工作

创建、登录讯飞账号,完成实名认证,

创建应用

点击免费试用,创建应用

领取免费额度

产品价格

领取新用户礼包

给应用下单

回到应用就可以看到免费服务量了

有高级功能可以根据需求开通,建议开启 动态修正 (当前免费)

API 调用

接口文档:https://www.xfyun.cn/doc/asr/voicedictation/API.html#接口说明

可以直接参考示例 Demo 在基础上修改即可

此处以 Python3 demo 为例

记录自己的 应用信息:

将 Python demo 中的 Ws_Param 类的几个参数填好,讲道理就可以运行了。

websocket 错误

找不到 websocket 或报错

1
module 'websocket' has no attribute 'enableTrace' 

都是 webscoket 库不对的问题

解决方案

卸载掉当前的 websocket 安装:

1
pip install websocket-client 
语音识别离谱

结果离谱的话检查一下音频的采样率,建议将采样率调整到 16k

可以参考:修改 wav 音频采样率

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# -*- coding:utf-8 -*-
#
# author: iflytek
#
# 本demo测试时运行的环境为:Windows + Python3.7
# 本demo测试成功运行时所安装的第三方库及其版本如下,您可自行逐一或者复制到一个新的txt文件利用pip一次性安装:
# cffi==1.12.3
# gevent==1.4.0
# greenlet==0.4.15
# pycparser==2.19
# six==1.12.0
# websocket==0.2.1
# websocket-client==0.56.0
#
# 语音听写流式 WebAPI 接口调用示例 接口文档(必看):https://doc.xfyun.cn/rest_api/语音听写(流式版).html
# webapi 听写服务参考帖子(必看):http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=38947&extra=
# 语音听写流式WebAPI 服务,热词使用方式:登陆开放平台https://www.xfyun.cn/后,找到控制台--我的应用---语音听写(流式)---服务管理--个性化热词,
# 设置热词
# 注意:热词只能在识别的时候会增加热词的识别权重,需要注意的是增加相应词条的识别率,但并不是绝对的,具体效果以您测试为准。
# 语音听写流式WebAPI 服务,方言试用方法:登陆开放平台https://www.xfyun.cn/后,找到控制台--我的应用---语音听写(流式)---服务管理--识别语种列表
# 可添加语种或方言,添加后会显示该方言的参数值
# 错误码链接:https://www.xfyun.cn/document/error-code (code返回错误码时必看)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
import websocket
import datetime
import hashlib
import base64
import hmac
import json
from urllib.parse import urlencode
import time
import ssl
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
import _thread as thread

STATUS_FIRST_FRAME = 0 # 第一帧的标识
STATUS_CONTINUE_FRAME = 1 # 中间帧标识
STATUS_LAST_FRAME = 2 # 最后一帧的标识


class Ws_Param(object):
# 初始化
def __init__(self, APPID, APIKey, APISecret, AudioFile):
self.APPID = APPID
self.APIKey = APIKey
self.APISecret = APISecret
self.AudioFile = AudioFile

# 公共参数(common)
self.CommonArgs = {"app_id": self.APPID}
# 业务参数(business),更多个性化参数可在官网查看
self.BusinessArgs = {"domain": "iat", "language": "zh_cn", "accent": "mandarin", "vinfo":1,"vad_eos":10000}

# 生成url
def create_url(self):
url = 'wss://ws-api.xfyun.cn/v2/iat'
# 生成RFC1123格式的时间戳
now = datetime.now()
date = format_date_time(mktime(now.timetuple()))

# 拼接字符串
signature_origin = "host: " + "ws-api.xfyun.cn" + "\n"
signature_origin += "date: " + date + "\n"
signature_origin += "GET " + "/v2/iat " + "HTTP/1.1"
# 进行hmac-sha256进行加密
signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),
digestmod=hashlib.sha256).digest()
signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')

authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
self.APIKey, "hmac-sha256", "host date request-line", signature_sha)
authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
# 将请求的鉴权参数组合为字典
v = {
"authorization": authorization,
"date": date,
"host": "ws-api.xfyun.cn"
}
# 拼接鉴权参数,生成url
url = url + '?' + urlencode(v)
# print("date: ",date)
# print("v: ",v)
# 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释,比对相同参数时生成的url与自己代码生成的url是否一致
# print('websocket url :', url)
return url


# 收到websocket消息的处理
def on_message(ws, message):
try:
code = json.loads(message)["code"]
sid = json.loads(message)["sid"]
if code != 0:
errMsg = json.loads(message)["message"]
print("sid:%s call error:%s code is:%s" % (sid, errMsg, code))

else:
data = json.loads(message)["data"]["result"]["ws"]
ws.temp_data_list.append(data)
# print(json.loads(message))
result = ""
for i in data:
for w in i["cw"]:
result += w["w"]
ws.temp_result_list.append(result)
print("sid:%s call success!,data is:%s" % (sid, json.dumps(data, ensure_ascii=False)))

except Exception as e:
print("receive msg,but parse exception:", e)



# 收到websocket错误的处理
def on_error(ws, error):
print("### error:", error)


# 收到websocket关闭的处理
def on_close(ws,a,b):
print("### closed ###")


# 收到websocket连接建立的处理
def on_open(ws):
def run(*args):
frameSize = 8000 # 每一帧的音频大小
intervel = 0.04 # 发送音频间隔(单位:s)
status = STATUS_FIRST_FRAME # 音频的状态信息,标识音频是第一帧,还是中间帧、最后一帧

with open(wsParam.AudioFile, "rb") as fp:
while True:
buf = fp.read(frameSize)
# 文件结束
if not buf:
status = STATUS_LAST_FRAME
# 第一帧处理
# 发送第一帧音频,带business 参数
# appid 必须带上,只需第一帧发送
if status == STATUS_FIRST_FRAME:

d = {"common": wsParam.CommonArgs,
"business": wsParam.BusinessArgs,
"data": {"status": 0, "format": "audio/L16;rate=16000",
"audio": str(base64.b64encode(buf), 'utf-8'),
"encoding": "raw"}}
d = json.dumps(d)
ws.send(d)
status = STATUS_CONTINUE_FRAME
# 中间帧处理
elif status == STATUS_CONTINUE_FRAME:
d = {"data": {"status": 1, "format": "audio/L16;rate=16000",
"audio": str(base64.b64encode(buf), 'utf-8'),
"encoding": "raw"}}
ws.send(json.dumps(d))
# 最后一帧处理
elif status == STATUS_LAST_FRAME:
d = {"data": {"status": 2, "format": "audio/L16;rate=16000",
"audio": str(base64.b64encode(buf), 'utf-8'),
"encoding": "raw"}}
ws.send(json.dumps(d))
time.sleep(1)
break
# 模拟音频采样间隔
time.sleep(intervel)
ws.close()

thread.start_new_thread(run, ())


if __name__ == "__main__":
# 测试时候在此处正确填写相关信息即可运行

wsParam = Ws_Param(APPID='xxxxxx', APISecret='xxxxxx',
APIKey='xxxxxx',
AudioFile=r'xxxxxx.wav')
websocket.enableTrace(False)
wsUrl = wsParam.create_url()
ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close)
ws.temp_data_list = list()
ws.temp_result_list = list()
ws.on_open = on_open
ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
print(ws.temp_data_list)
print(ws.temp_result_list)

pass

返回:

1
2
sid:iat000d3aeb@dx188ffeb2e2ba12c802 call success!,data is:[{"cw": [{"sc": 0, "w": "哈"}], "bg": 32}, {"bg": 60, "cw": [{"sc": 0, "w": "哈哈"}]}, {"cw": [{"sc": 0, "w": "哈哈"}], "bg": 92}, {"bg": 128, "cw": [{"sc": 0, "w": "哈"}]}, {"bg": 148, "cw": [{"sc": 0, "w": "哈哈"}]}, {"bg": 180, "cw": [{"sc": 0, "w": "哈哈"}]}, {"bg": 232, "cw": [{"sc": 0, "w": ","}]}, {"bg": 232, "cw": [{"sc": 0, "w": "这"}]}, {"bg": 268, "cw": [{"sc": 0, "w": "下"}]}, {"cw": [{"w": "你们", "sc": 0}], "bg": 276}, {"bg": 300, "cw": [{"sc": 0, "w": "无处可逃"}]}, {"bg": 384, "cw": [{"w": "了", "sc": 0}]}, {"bg": 392, "cw": [{"sc": 0, "w": "吧"}]}]     
sid:iat000d3aeb@dx188ffeb2e2ba12c802 call success!,data is:[{"bg": 411, "cw": [{"sc": 0, "w": "。"}]}]

根据讯飞语音识别的输出结果,每个对象都包含以下字段:

  • “bg”:表示该关键词在原始语音流中的起始位置(单位:帧)。
  • “cw”:表示识别结果的关键词列表。每个关键词对象都包含以下字段:
    • “sc”:句子级别的标识,值为0表示该关键词属于同一句子。
    • “w”:表示识别到的关键词的文本内容。

这个demo 代码有点乱,可以自己整理一下输出结果。

参考资料



文章链接:
https://www.zywvvd.com/notes/study/audio/xfyun-speech-recognition/xfyun-speech-rec/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

科大讯飞语音识别
https://www.zywvvd.com/notes/study/audio/xfyun-speech-recognition/xfyun-speech-rec/
作者
Yiwei Zhang
发布于
2023年6月28日
许可协议