1. 申请账号及获得AppID等

控制台填写资料

控制台-讯飞开放平台

语音听写的文档及接口说明

语音听写(流式版)WebAPI 文档 | 讯飞开放平台文档中心

关键信息:

设置参数

业务数据流参数

data

参数名 类型 必传 描述
status int 音频的状态
0 :第一帧音频
1 :中间的音频
2 :最后一帧音频,最后一帧必须要发送
format string 音频的采样率支持16k和8k
16k音频:audio/L16;rate=16000
8k音频:audio/L16;rate=8000
encoding string 音频数据格式
raw:原生音频(支持单声道的pcm)
speex:speex压缩后的音频(8k)
speex-wb:speex压缩后的音频(16k)
请注意压缩前也必须是采样率16k或8k单声道的pcm。
lame:mp3格式(仅中文普通话和英文支持,方言及小语种暂不支持)
样例音频请参照音频样例
audio string 音频内容,采用base64编码

返回数据解析

返回参数

参数 类型 描述
sid string 本次会话的id,只在握手成功后第一帧请求时返回
code int 返回码,0表示成功,其它表示异常,详情请参考错误码
message string 错误描述
data object 听写结果信息
data.status int 识别结果是否结束标识:
0:识别的第一块结果
1:识别中间结果
2:识别最后一块结果
data.result object 听写识别结果
data.result.sn int 返回结果的序号
data.result.ls bool 是否是最后一片结果
data.result.bg int 保留字段,无需关心
data.result.ed int 保留字段,无需关心
data.result.ws array 听写结果
data.result.ws.bg int 起始的端点帧偏移值,单位:帧(1帧=10ms)
注:以下两种情况下bg=0,无参考意义:
1)返回结果为标点符号或者为空;2)本次返回结果过长。
data.result.ws.cw array 中文分词
data.result.ws.cw.w string 字词
data.result.ws.cw.其他字段
sc/wb/wc/we/wp
int/string 均为保留字段,无需关心。如果解析sc字段,建议float与int数据类型都做兼容

2. 研究demo,发现问题

下载python demo和node js demo

原理都是调用websocket连接方式

nodejs 的demo可以直接运行,需要安装两个库

npm install crypto-js

npm install  ws

/**** 运行前:请先填写Appid、APIKey、APISecret** 语音听写流式 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/后,找到控制台--我的应用---语音听写---服务管理--上传热词* 注意:热词只能在识别的时候会增加热词的识别权重,需要注意的是增加相应词条的识别率,但并不是绝对的,具体效果以您测试为准。* 错误码链接:https://www.xfyun.cn/document/error-code (code返回错误码时必看)* @author iflytek*/
const CryptoJS = require('crypto-js')
const WebSocket = require('ws')
var fs = require('fs')// 系统配置
const config = {// 请求地址hostUrl: "wss://iat-api.xfyun.cn/v2/iat",host: "iat-api.xfyun.cn",//在控制台-我的应用-语音听写(流式版)获取appid: "d9f99f36",//在控制台-我的应用-语音听写(流式版)获取apiSecret: "YTBkNzkyYWYwMGQ2ZDNiZTYzMDc4NDY1",//在控制台-我的应用-语音听写(流式版)获取apiKey: "d2519c5bab022ec11c27dc5752263604",file: "./16k_10.pcm", //请填写您的音频文件路径uri: "/v2/iat",highWaterMark: 1280
}// 帧定义
const FRAME = {STATUS_FIRST_FRAME: 0,STATUS_CONTINUE_FRAME: 1,STATUS_LAST_FRAME: 2
}// 获取当前时间 RFC1123格式
let date = (new Date().toUTCString())// 设置当前临时状态为初始化
let status = FRAME.STATUS_FIRST_FRAME// 记录本次识别用sid
let currentSid = ""// 识别结果
let iatResult = []let wssUrl = config.hostUrl + "?authorization=" + getAuthStr(date) + "&date=" + date + "&host=" + config.host
let ws = new WebSocket(wssUrl)// 连接建立完毕,读取数据进行识别
ws.on('open', (event) => {console.log("websocket connect!")var readerStream = fs.createReadStream(config.file, {highWaterMark: config.highWaterMark});readerStream.on('data', function(chunk) {send(chunk)});// 最终帧发送结束readerStream.on('end', function() {status = FRAME.STATUS_LAST_FRAMEsend("")});
})// 得到识别结果后进行处理,仅供参考,具体业务具体对待
ws.on('message', (data, err) => {if (err) {console.log(`err:${err}`)return}res = JSON.parse(data)if (res.code != 0) {console.log(`error code ${res.code}, reason ${res.message}`)return}let str = ""if (res.data.status == 2) {// res.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源str += "最终识别结果"currentSid = res.sidws.close()} else {str += "中间识别结果"}iatResult[res.data.result.sn] = res.data.resultif (res.data.result.pgs == 'rpl') {res.data.result.rg.forEach(i => {iatResult[i] = null})str += "【动态修正】"}str += ":"iatResult.forEach(i => {if (i != null) {i.ws.forEach(j => {j.cw.forEach(k => {str += k.w})})}})console.log(str)// ... do something
})// 资源释放
ws.on('close', () => {console.log(`本次识别sid:${currentSid}`)console.log('connect close!')
})// 建连错误
ws.on('error', (err) => {console.log("websocket connect err: " + err)
})// 鉴权签名
function getAuthStr(date) {let signatureOrigin = `host: ${config.host}\ndate: ${date}\nGET ${config.uri} HTTP/1.1`let signatureSha = CryptoJS.HmacSHA256(signatureOrigin, config.apiSecret)let signature = CryptoJS.enc.Base64.stringify(signatureSha)let authorizationOrigin = `api_key="${config.apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signature}"`let authStr = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(authorizationOrigin))return authStr
}// 传输数据
function send(data) {let frame = "";let frameDataSection = {"status": status,"format": "audio/L16;rate=16000","audio": data.toString('base64'),"encoding": "raw"}switch (status) {case FRAME.STATUS_FIRST_FRAME:frame = {// 填充commoncommon: {app_id: config.appid},//填充businessbusiness: {language: "zh_cn",domain: "iat",accent: "mandarin",dwa: "wpgs" // 可选参数,动态修正},//填充datadata: frameDataSection}status = FRAME.STATUS_CONTINUE_FRAME;break;case FRAME.STATUS_CONTINUE_FRAME:case FRAME.STATUS_LAST_FRAME://填充frameframe = {data: frameDataSection}break;}ws.send(JSON.stringify(frame))
}

播放的目录下的样例pcm文件,可以正常返回

C:\Users\pocea\Desktop\KXWELL\dev\语音识别\iat_ws_nodejs_demo>node iat-ws-node.js
websocket connect!
中间识别结果:四月
中间识别结果【动态修正】:四月十四日
中间识别结果【动态修正】:四月十三日
中间识别结果【动态修正】:四月十三日中国
中间识别结果【动态修正】:四月十三日中国台北
中间识别结果【动态修正】:四月十三日中国台北选手
中间识别结果【动态修正】:四月十三日中国台北选手代之
中间识别结果【动态修正】:四月十三日中国台北选手戴资颖在比赛
中间识别结果【动态修正】:4月13日,中国台北选手戴资颖在比赛中发球
中间识别结果:4月13日,中国台北选手戴资颖在比赛中发球,当日
中间识别结果:4月13日,中国台北选手戴资颖在比赛中发球,当日,在新加坡室内体育场举行的新加坡羽毛球公开赛女子单打半决赛中
中间识别结果:4月13日,中国台北选手戴资颖在比赛中发球,当日,在新加坡室内体育场举行的新加坡羽毛球公开赛女子单打半决赛中 ,中国台北选手戴资颖以2:1战胜日本选手山口茜
中间识别结果:4月13日,中国台北选手戴资颖在比赛中发球,当日,在新加坡室内体育场举行的新加坡羽毛球公开赛女子单打半决赛中 ,中国台北选手戴资颖以2:1战胜日本选手山口茜,晋级决赛
最终识别结果:4月13日,中国台北选手戴资颖在比赛中发球,当日,在新加坡室内体育场举行的新加坡羽毛球公开赛女子单打半决赛中 ,中国台北选手戴资颖以2:1战胜日本选手山口茜,晋级决赛。
本次识别sid:iat000dff5a@dx17a8f6bd0b67a1c802
connect close!

这里的动态修正怎么用还没搞明白。

# -*- 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 threadSTATUS_FIRST_FRAME = 0  # 第一帧的标识
STATUS_CONTINUE_FRAME = 1  # 中间帧标识
STATUS_LAST_FRAME = 2  # 最后一帧的标识
'''
正常运行返回结果:
sid:iat000d6ced@dx17a8fa05ca4a493802 call success!,data is:[{"bg": 64, "cw": [{"sc": 0, "w": "这"}]}, {"bg": 84, "cw": [{"sc": 0, "w": "是"}]}, {"bg": 104, "cw": [{"sc": 0, "w": "一"}]}, {"bg": 124, "cw": [{"sc": 0, "w": "段"}]}, {"bg": 144, "cw": [{"sc": 0, "w": "测试"}]}, {"bg": 184, "cw": [{"sc": 0, "w": "音频"}]}]
sid:iat000d6ced@dx17a8fa05ca4a493802 call success!,data is:[{"bg": 0, "cw": [{"w": "。", "sc": 0}]}]
0:00:02.382220
'''class Ws_Param(object):# 初始化def __init__(self, APPID, APIKey, APISecret, AudioFile):self.APPID = APPIDself.APIKey = APIKeyself.APISecret = APISecretself.AudioFile = AudioFile# 公共参数(common)self.CommonArgs = {"app_id": self.APPID}# 业务参数(business),更多个性化参数可在官网查看self.BusinessArgs = {"domain": "iat", "language": "zh_cn", "accent": "mandarin", "vinfo":1,"vad_eos":2000}# 生成urldef 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"}# 拼接鉴权参数,生成urlurl = 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"]# print(json.loads(message))result = ""for i in data:for w in i["cw"]:result += w["w"]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):print("### closed ###")# 收到websocket连接建立的处理
def on_open(ws):def run(*args):frameSize = 8000  # 每一帧的音频大小intervel = 0.4 # 发送音频间隔(单位: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": "lame"}}  #mp3格式定义lame, pcm格式为rawd = 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": "lame"}}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": "lame"}}ws.send(json.dumps(d))time.sleep(1)break# 模拟音频采样间隔time.sleep(intervel)ws.close()thread.start_new_thread(run, ())if __name__ == "__main__":# 测试时候在此处正确填写相关信息即可运行time1 = datetime.now()wsParam = Ws_Param(APPID='d9f99f36', APISecret='YTBkNzkyYWYwMGQ2ZDNiZTYzMDc4NDY1',APIKey='d2519c5bab022ec11c27dc5752263604',AudioFile=r'./iat_mp3_16k.mp3')websocket.enableTrace(False)wsUrl = wsParam.create_url()ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close)ws.on_open = on_openws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})time2 = datetime.now()print(time2-time1)

3. 对齐文件格式

python的例子一直有个问题,开始用wav文件来测试,实际是不行的,看来科大讯飞的API还不支持,改为用PCM文件来测试,但问题又来了,怎么来生成测试文件?又怎么播放测试文件,确认结果呢?所有有了上一篇文章,怎么写一个PCM PLAYER. PCM recorder还要晚一点,要不就用QT把两者打包成一个工具也不错,呵呵。

这里的关键就是文件格式和设置参数要对应

就是连接上传参数这里

d = {"common": wsParam.CommonArgs,
                         "business": wsParam.BusinessArgs,
                         "data": {"status": 0, "format": "audio/L16;rate=16000",
                                  "audio": str(base64.b64encode(buf), 'utf-8'),
                                  "encoding": "lame"}}  #mp3格式定义lame, pcm格式为raw

实测MP3和PCM都可以正常识别

4. 待研究

需要解决唤醒,断句等问题,因为需要实时流处理,所以还要考虑处理速度能不能满足识别后控制设备的要求。

科大讯飞语音接口调用实现语音识别相关推荐

  1. 微信小程序+.NET(四) 科大讯飞语音接口-iat语音听写

      科大讯飞语音接口-iat语音听写   Demo下载链接:https://download.csdn.net/download/jinglell/11566402   首先,来看科大讯飞给的msc. ...

  2. 微信小程序+.NET(六) 科大讯飞语音接口-tts语音生成

      科大讯飞语音接口-tts语音生成   Demo下载链接:https://download.csdn.net/download/jinglell/11566459 语音生成是另一个难点,我的应用场景 ...

  3. python科大讯飞语音接口不能用_【】科大讯飞语音识别支持python吗

    科大讯飞语音识别支持python吗 我上过一门课的大作业是用Python自己实现一个小型语音识别系统.不过,如果你不是专攻这个方向的,而只是想使用现成的语音识别模块的话,你不会想自己写的. pytho ...

  4. 【人工智能】科大讯飞API接口调用(第一集)

    前言 这学期有一门人工智能教育课程,恰巧又有这么一个实践,要求进行人工智能接口调用 于是首选了科大讯飞,下面是详细过程记录 科大讯飞接口调用 以下是流程以及实现细节描述 调用流程 第一步 来到科大讯飞 ...

  5. 科大讯飞TTS接口调用保存为mp3格式

    不废话,直接上code package com.iflytek.voicecloud.webapi.demo;import com.google.gson.Gson; import com.googl ...

  6. 【语音从零之五】用科大讯飞语音包实现语音打开已安装应用程序

    [更新]有人说不会使用科大讯飞的语音包,这里是传送门,可以参考从零系列的前四篇文章 (一)利用科大讯飞语音包实现Android语音识别Demo (二)科大讯飞语音包Mscdemo的使用 (三)自定义类 ...

  7. Spring Boot+VUE集成科大讯飞语音在线合成解决方案

    在项目中需要用到将景点文字合成语音,通过语音方式向用户介绍景点信息,需要用到文字转语音的在线合成解决方案.通过对各种文字转语音合成方案与效果比较,觉得讯飞的效果最好,语音拟人效果.文章断词都非常不错, ...

  8. python 科大讯飞 文本转语音接口 + QT简单界面

    文本转语音 前提 源码 解释 缺陷 打包 由于是实验做的,且有点赶,也就没有怎么整理和疏通,只要能运行就行了.所以仅供借鉴,问题肯定很多,在这只是记录一下所学. 前提 首先你需要注册科大讯飞AI开放平 ...

  9. 为什么李开复说科大讯飞不懂语音,99%的语音识别项目要死掉?

    原标题:为什么李开复说科大讯飞不懂语音,99%的语音识别项目要死掉? 全文约3000字,阅读时间预计5分钟. 3月3日,李开复老师出席了在海南三亚万豪酒店举行的"2017年投资界百人论坛&q ...

  10. 安卓调用系统语音识别功能全解(谷歌语音服务):获取识别结果,使用语音识别进行搜索。

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓调用系统语音识别功能全解(谷歌语音服务):获取识别结果,使用语音识别进行搜索. 首先要添加权限 <uses-permission andro ...

最新文章

  1. jdk 细粒度锁_使用JDK 8轻松进行细粒度排序
  2. mysql优化和索引_mysql优化和索引
  3. MessageQueue的使用方法(二)
  4. 学习vue3系列ref
  5. vue 拷贝 数组_vue源码中值得学习的方法
  6. php mysql 拖拉 报表_php+mysql 生成统计报表
  7. 对研发经理这一岗位的个人理解
  8. 程序员交接文档格式(自己整理,仅供参考,付md文档)
  9. Jack的E680刷机过程全记录
  10. 高通msm8953平台摄像头移植
  11. .计算机自动关机或重启,电脑自动关机或重启怎么治
  12. 前端----let关键字、const关键字
  13. linux 节点互信,Linux 集群节点互信ssh配置
  14. AlphaTest烘焙的阴影不正确
  15. EMC 设计经验总结
  16. dnf剑魂buff等级上限_DNF加百利商店什么装备值得买?除了远古遗愿这些装备也不容错过...
  17. 追风筝的人 第五章
  18. 读书笔记:SQL 查询中的SQL*Plus 替换变量(DEFINE变量)和参数
  19. 计算机信息处理员证书可以在东莞入户,东莞入户办理:人才入户东莞有哪些职称考?可靠吗?...
  20. win10安装Ubuntu双系统超级详细教程(UEFI启动模式)

热门文章

  1. flowchart流程图编程语言下载_c语言流程图生成器下载
  2. c语言彩票号码生成器
  3. 三体第一部(01到12节)-附带感想
  4. mac 生成公钥和私钥
  5. android viewflipper 动画,Android ViewFlipper动画
  6. Go语言编程快速入门
  7. Fiddler抓包快速入门-windows网页抓包
  8. hfss和matlab,matlab-hfss联合仿真教程(初学)--第一节(利用MATLAB编写脚本建立HFSS工程)...
  9. Python txt转换为excel
  10. ReactNative 仿造 ofo 共享单车快速开发的app