記一次智能語音軟件的開發-終於為孩子找到了個靠譜的口語老師
“再窮不能窮教育,再苦不能苦孩子”,作為娃的爸媽,不僅僅要努力工作保證物質支持,更要關注娃的學習狀況,而且時刻都怕娃“輸在了起跑線上”,可是,現在孩子們的起跑線也太多了點,英語、各種藝術特長,甚至跳繩,忙的不亦樂乎。然而家長也不是全才啊,這不,我的姐姐最近就開始發愁女兒的英語口語問題了,自己發音不准確,報班又不知道哪家靠譜,眼看着孩子就要落后於小伙伴了,了解到這個情況后,我拿出英語課本,想到自己每次都是60飄過的英語成績,又放了回去,拿起了我的武器——代碼。
近些年自然語言處理已經成熟地應用在很多領域,智能語音測評的使用成本早已是大眾所能承受。根據給娃糾正讀音的需求,我最終選擇調用靠譜的大廠,有道智雲的API來開發個簡易語音評測程序,或者稱之為——智能口語老師!
調用API接口的准備工作
首先,是需要在有道智雲的個人頁面上創建實例、創建應用、綁定應用和實例,獲取到應用的id和密鑰。具體個人注冊的過程和應用創建過程詳見文章分享一次批量文件翻譯的開發過程

開發過程詳細介紹
下面介紹具體的代碼開發過程。
首先研究官方文檔給出的API輸入輸出規范。該API采用https方式通信,簡單來說,就是將預先錄制好的聲音文件編碼處理,簽名后提交給API,解析API返回的json即可得到評分結果。
接口地址:
https接口: https://openapi.youdao.com/iseap
API輸入所需參數如下表:
字段名 | 類型 | 含義 | 必填 | 備注 |
---|---|---|---|---|
q | text | 要評測的音頻文件的Base64編碼字符串 | True | 必須是Base64編碼 |
text | text | 要評測的音頻文件對應的文本 | True | have a good day |
langType | text | 源語言 | True | 支持語言 |
appKey | text | 應用ID | True | 可在 應用管理 查看 |
salt | text | UUID | True | UUID |
curtime | text | 時間戳(秒) | True | TimeStamp |
sign | text | 簽名,通過sha256(應用ID+input+salt+curtime+應用密鑰)生成;input的生成規則見表下的備注 | True | sha256(應用ID+input+salt+curtime+應用密鑰) |
signType | text | 簽名類型 | True | v2 |
format | text | 語音文件的格式,wav | true | wav |
rate | text | 采樣率,推薦 16000 采用率 | true | 16000 |
channel | text | 聲道數, 僅支持單聲道,請填寫固定值1 | true | 1 |
type | text | 上傳類型, 僅支持base64上傳,請填寫固定值1 | true | 1 |
其中簽名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 部分大體分為三部分,文章處理區域、錄音區域和評分展示區域。
其布局代碼如下:
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()來收集帶所有的文本文件,啟動合成,並打印運行結果:
def start_score(): result=au_model.get_score(file_dict) for r in result: text3.insert(tk.END,r)
-
audioandprocess.py
這里主要實現了文件處理、錄音和處理接口返回的功能。首先定義一個Audio_model
class Audio_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路徑中,錄音文件名與原文的文件名相同,便於對應。
def record_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中封裝的工具並解析返回值的功能:
def get_score(self,dict): result=[] #self.is_recording=False for path in dict: 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) return result
-
isebynetease.py
isebynetease.py中是和請求有道智雲API直接相關的一些方法,最核心的是connect()方法,整合了API所要求的各個參數,並調用執行請求的方法do_request(),而后根據UI的展示需求,處理API的返回結果並拼接字符串。
def connect(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:] if extension != '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() with open(audio_file_path, 'rb') as file_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" return recordAndResult
效果展示
展示一下本人純正的”chinenglish“ 錄音后程序的運行情況(得分多少不重要,重要的是它客觀的評價方式 :P )
首先介紹一下操作方法:
1)點擊“選擇文章”,選擇需要評測的文章;
2)點擊“錄音”,“結束錄音”按鈕,進行語音錄制;
3)如需對多篇文章進行評測,重復1)、2)步驟即可
4)點擊“評分“,進行智能語音評測,並展示評分結果,同時將詳細評分結果,存儲在本代碼路徑的result目錄下。
效果展示
界面部分:展示了 句子完整度、發音准確度的、流利度的得分,以及語速:
文檔部分:分別對每個語音進行了測評,並將返回的詳細結果以json的形式存在了result文件夾下。
輸出結果展示:
{
’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文檔清晰,調用過程全程無坑,開發體驗非常友好,評分結果客觀公正,很具有參考價值,以至於我都想和小侄女一起學習進步去了!