调用API接口的准备工作
首先,是需要在有道智云的个人页面上创建实例、创建应用、绑定应用和实例,获取到应用的id和密钥。具体个人注册的过程和应用创建过程详见文章分享一次批量文件翻译的开发过程
开发过程详细介绍
下面介绍具体的代码开发过程。
首先研究官方文档给出的API输入输出规范。该API采用https方式通信,简单来说,就是将预先录制好的声音文件编码处理,签名后提交给API,解析API返回的json即可得到评分结果。
接口地址:
https接口: https://openapi.youdao.com/iseap
API输入所需参数如下表:
字段名类型含义必填备注
qtext要评测的音频文件的Base64编码字符串True必须是Base64编码
texttext要评测的音频文件对应的文本Truehave a good day
langTypetext源语言True支持语言
appKeytext应用IDTrue可在 应用管理 查看
salttextUUIDTrueUUID
curtimetext时间戳(秒)TrueTimeStamp
signtext签名,通过sha256(应用ID+input+salt+curtime+应用密钥)生成;input的生成规则见表下的备注Truesha256(应用ID+input+salt+curtime+应用密钥)
signTypetext签名类型Truev2
formattext语音文件的格式,wavtruewav
ratetext采样率,推荐 16000 采用率true16000
channeltext声道数, 仅支持单声道,请填写固定值1true1
typetext上传类型, 仅支持base64上传,请填写固定值1true1
其中签名sign生成方法如下:signType=v2; sign=sha256(应用ID+input+salt+curtime+应用密钥)。这里需要注意的是input的计算方式为:input=q前10个字符 + q长度 + q后10个字符(当q长度大于20)或 input=q字符串(当q长度小于等于20)。
接口的输出参数如下:
字段含义
errorCode识别结果错误码,一定存在。 详细信息可见 错误代码列表
refText请求的文本
start音频中句子开始时间,单位是秒
end音频中句子结束时间,单位是秒
integrity句子完整度得分
fluency句子流利度得分
pronunciation句子准确度得分
speed语速,单词/分钟
overall句子综合评分
words单词评分数组
-word单词
-start单词开始时间,单位是秒
-end单词结束时间,单位是秒
-pronunciation单词准确度得分
-phonemes音标数组
--phoneme音标
--start音标开始时间,单位是秒
--end音标结束时间,单位是秒
--judge判断音素是否错误,true为发音正确,false为发音错误,同时calibration给出提示
--calibration如果发音错误,提示用户该发音像什么
--prominence重音程度,分数越高,当前音标越可能是重音,分数在[0 100]
--stress_ref元音重音参考/标准答案,如果为true,说明参考答案认为该元音应该发重音,辅音时无意义
--stress_detect在一个单词中,用户该音标发音为重音
Demo开发:
这个demo使用python3开发,包括maindow.py,audioandprocess.py,isebynetease.py 三个文件,分别为demo的界面、录音以及其他逻辑处理和智能语音评测接口调用方法的封装。
界面部分:
UI 部分大体分为三部分,文章处理区域、录音区域和评分展示区域。
其布局代码如下:
x
root=tk.Tk()
root.title("youdao ise test")
frm=tk.Frame(root)
frm.grid(padx='50',pady='50')
# 选取文章
btn_get_file_path=tk.Button(frm,text='选择课文 :',command=get_file)
btn_get_file_path.grid(row=0,column=0)
text1=tk.Text(frm,width='70',height='2')
text1.grid(row=0,column=1)
# 文章内容展示
text2=tk.Text(frm,width='70',height='5')
text2.grid(row=1,column=1)
# 开始和停止录音
btn_start_rec=tk.Button(frm,text='录音',command=start_rec,width=10)
btn_start_rec.grid(row=2,column=0)
lb_Status=tk.Label(frm,text='Ready',anchor='w',fg='green')
lb_Status.grid(row=2,column=1)
btn_stop_rec=tk.Button(frm,text="结束录音",command=stop_rec)
btn_stop_rec.grid(row=2,column=2)
# 打分按钮和结果展示
btn_score=tk.Button(frm,text="评分",command=start_score,width=10)
btn_score.grid(row=3,column=0)
text3=tk.Text(frm,width='70',height='10')
text3.grid(row=3,column=1)
root.mainloop()
其中启动按钮btn_score的绑定事件start_score()来收集带所有的文本文件,启动合成,并打印运行结果:
xxxxxxxxxx
defstart_score():
result=au_model.get_score(file_dict)
forrinresult:
text3.insert(tk.END,r)
audioandprocess.py
这里主要实现了文件处理、录音和处理接口返回的功能。首先定义一个Audio_model
xxxxxxxxxx
classAudio_model():
def__init__(self,audio_path,is_recording):
self.current_file='' # 当前录音对应的原文路径
self.is_recording=is_recording # 录音状态标识
self.audio_chunk_size=1600 # 以下均为录音必要参数
self.audio_channels=1
self.audio_format=pyaudio.paInt16
self.audio_rate=16000
record_and_save()方法进行录音并保存到项目的record路径中,录音文件名与原文的文件名相同,便于对应。
xxxxxxxxxx
defrecord_and_save(self):
self.is_recording=True
file_name=self.get_file_name(self.current_file)
self.audio_file_name='./record/'+file_name+'.wav'
threading.Thread(target=self.record,args=(self.audio_file_name,)).start()
get_score()方法实现了调用isebynetease.py中封装的工具并解析返回值的功能:
xxxxxxxxxx
defget_score(self,dict):
result=[]
#self.is_recording=False
forpathindict:
file_content=self.get_content(path)
file_name=self.get_file_name(path)
audio_path='./record/'+file_name+'.wav'
print(file_content,audio_path)
score_result=connect(audio_path,file_content)
#处理结果,添加进结果集
result.append(score_result)
returnresult
isebynetease.py
isebynetease.py中是和请求有道智云API直接相关的一些方法,最核心的是connect()方法,整合了API所要求的各个参数,并调用执行请求的方法do_request(),而后根据UI的展示需求,处理API的返回结果并拼接字符串。
xxxxxxxxxx
defconnect(audio_file_path,audio_text):
recordname=audio_file_path.split("/")[-1]
audio_file_path=audio_file_path
lang_type='en'# 当前仅支持英文
extension=audio_file_path[audio_file_path.rindex('.')+1:]
ifextension!='wav':
print('不支持的音频类型')
sys.exit(1)
wav_info=wave.open(audio_file_path,'rb')
sample_rate=wav_info.getframerate()
nchannels=wav_info.getnchannels()
wav_info.close()
withopen(audio_file_path,'rb')asfile_wav:
q=base64.b64encode(file_wav.read()).decode('utf-8')
data= {}
data['text'] =audio_text
curtime=str(int(time.time()))
data['curtime'] =curtime
salt=str(uuid.uuid1())
signStr=APP_KEY+truncate(q)+salt+curtime+APP_SECRET
sign=encrypt(signStr)
data['appKey'] =APP_KEY
data['q'] =q
data['salt'] =salt
data['sign'] =sign
data['signType'] ="v2"
data['langType'] =lang_type
data['rate'] =sample_rate
data['format'] ='wav'
data['channel'] =nchannels
data['type'] =1
# 处理返回值
response=do_request(data)
j=json.loads(str(response.content,encoding="utf-8"))
print(j)
# 句子完整度
contextIntegrity="句子完整度:"+str(round(j["integrity"],2))+" "
pronunciation="发音准确度:"+str(round(j["pronunciation"],2))+" "
fluency="流利度:"+str(round(j["fluency"],2))+" "
speed="语速:"+str(round(j["speed"],2))+" "
recordAndResult=recordname+" "+contextIntegrity+pronunciation+fluency+speed+"\n"
returnrecordAndResult
效果展示
展示一下本人纯正的”chinenglish“ 录音后程序的运行情况(得分多少不重要,重要的是它客观的评价方式 :P )
首先介绍一下操作方法:
1)点击“选择文章”,选择需要评测的文章;
2)点击“录音”,“结束录音”按钮,进行语音录制;
3)如需对多篇文章进行评测,重复1)、2)步骤即可
4)点击“评分“,进行智能语音评测,并展示评分结果,同时将详细评分结果,存储在本代码路径的result目录下。
效果展示
界面部分:展示了 句子完整度、发音准确度的、流利度的得分,以及语速:
文档部分:分别对每个语音进行了测评,并将返回的详细结果以json的形式存在了result文件夹下。
输出结果展示:
xxxxxxxxxx
{
’integrity‘: 100,//句子完整度
'refText’: "Are you ok? ",//待评测语音对应的文本
'pronunciation': 67.108101,//句子发音准确度
'start': 0.030000,//音频开始时间,秒
'words': [{ //单词信息列表
'pronunciation': 50.640327, //单词准确度分数
'start': 0.73, //单词开始时间,秒
'end': 0.76,//单词结束时间,秒
'word': 'Are', //单词文本
'phonemes': [{ //音标信息列表
'stress_ref': False, //元音重音参考(即标准重音),如果为true,说明参考答案认为该元音应该发重音,辅音时无意义
'pronunciation': 50.640331, //音标准确度评分
'stress_detect': False,//在一个单词中,用户该音标发音不为重音
'phoneme': 'ɝ', //音标名称
'start': 0.73, //音标开始时间,秒
'end': 0.76, //音标结束时间,秒
'judge': True, //判断音标是否错误,true为发音正确,false为发音错误,同时calibration给出提示
'calibration': 'ɝ', //判断音标是否错误,true为发音正确,false为发音错误,同时calibration给出提示
'prominence': 1 //重音程度,当前音标越可能是重音,分数区间[0 100]
}]
}, {
'pronunciation': 76.810608,
'start': 0.77,
'end': 1.08,
'word': 'you',
'phonemes': [{
'stress_ref': False,
'pronunciation': 79.084282,
'stress_detect': False,
'phoneme': 'j',
'start': 0.77,
'end': 0.86,
'judge': True,
'calibration': 'j',
'prominence': 0.944885
}, {
'stress_ref': True,
'pronunciation': 74.536934,
'stress_detect': True,
'phoneme': 'u',
'start': 0.87,
'end': 1.08,
'judge': True,
'calibration': 'u',
'prominence': 1
}]
}, {
'pronunciation': 66.129013,
'start': 1.14,
'end': 1.8,
'word': 'ok',
'phonemes': [{
'stress_ref': True,
'pronunciation': 69.046341,
'stress_detect': True,
'phoneme': 'o',
'start': 1.14,
'end': 1.27,
'judge': True,
'calibration': 'o',
'prominence': 1
}, {
'stress_ref': False,
'pronunciation': 65.357841,
'stress_detect': False,
'phoneme': 'k',
'start': 1.28,
'end': 1.42,
'judge': True,
'calibration': 'k',
'prominence': 0.838557
}, {
'stress_ref': True,
'pronunciation': 63.982838,
'stress_detect': True,
'phoneme': 'e',
'start': 1.43,
'end': 1.8,
'judge': True,
'calibration': 'e',
'prominence': 0.956448
}]
}],
'fluency': 83.554047, //句子流利度
'overall': 83.885124,//句子综合评分
'errorCode': '0', //识别结果错误码,一定存在
'end': 1.8,//句子结束时间,秒
'speed': 55.555557 // 句子语速(单词/分钟)
}
总结
有道智云的智能语音评测API文档清晰,调用过程全程无坑,开发体验非常友好,评分结果客观公正,很具有参考价值!
项目地址:https://github.com/LemonQH/BatchISEDemo