title: 單片機學(xué)習(xí):第一篇 基于Python的樹莓派語音助手
tags: 樹莓派,python,語音助手,百度AIP
目錄
一、pyaudio錄音
二、語音識別
三、與圖靈機器人對話
四、語音合成
五、封裝
樹莓派功能十分強大,作為一個微型電腦,獨特的陣腳設(shè)計使得樹莓派開發(fā)的自定義程度非常高。本篇博客通過使用python語言,封裝一個簡單的語音助手程序。制作一個語音助手你需要如下物品:
```
1:一個樹莓派(3代、4代皆可)
2:免驅(qū)的usb聲卡(聲卡需接在樹莓派usb接口)
3:麥克風(fēng)(接在聲卡上)
4:有線音響(音響可連在聲卡上,也可連在樹莓派的3.5mm接口上)
(樹莓派播放設(shè)備默認使用3.5mm接口,具體過程需要自定義播放設(shè)備)
```
如果要設(shè)置usb聲卡輸出,參考配置聲卡教程:https://www.jianshu.com/p/f414b85b9e71,如果使用默認3.5mm接口輸出可以忽略。
設(shè)計語音助手有如下過程:錄音、語音識別、圖靈機器人對話、語音合成,以下對各個過程進行介紹。
使用python語言進行錄音,主要是將說話者聲音輸出成一段音頻文件。對于python來說,這很容易。通過引用pyaudio庫,可以進行錄音、播放、生成wav文件等。
首先,我們在樹莓派上需要下載pyaudio庫: ```pip3 install pyaudio```
在pyaudio的官網(wǎng)http://people.csail.mit.edu/hubert/pyaudio/介紹上有對pyaudio的詳細介紹,以官網(wǎng)示例:
創(chuàng)建一名為rec的python文件 ```sudo nano rec.py```
import RPi.GPIO as GPIO import pyaudio import wave import os import sys def rec_fun(): # 隱藏錯誤消息,因為會有一堆ALSA和JACK錯誤消息,但其實能正常錄音 # os.close(sys.stderr.fileno()) BUTT = 26 # 開始錄音的按鈕:一邊接GPIO26,一邊接地 GPIO.setmode(GPIO.BCM) # 設(shè)GPIO26腳為輸入腳,電平拉高,也就是說26腳一旦讀到低電平,說明按了按鈕 GPIO.setup(BUTT, GPIO.IN, pull_up_down = GPIO.PUD_UP) # wav文件是由若干個CHUNK組成的,CHUNK我們就理解成數(shù)據(jù)包或者數(shù)據(jù)片段。 CHUNK = 512 FORMAT = pyaudio.paInt16 # pyaudio.paInt16表示我們使用量化位數(shù) 16位來進行錄音 RATE = 16000 # 采樣率1.6k。 WAVE_OUTPUT_FILENAME = 'command.wav' print('請按住按鈕開始錄音...') GPIO.wait_for_edge(BUTT, GPIO.FALLING) # To use PyAudio, first instantiate PyAudio using pyaudio.PyAudio(), which sets up the portaudio system. p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = 1, # cloud speecAPI只支持單聲道 rate = RATE, input = True, frames_per_buffer = CHUNK) print('錄音中...') frames = [] # 按住按鈕錄音,放開時結(jié)束 while GPIO.input(BUTT) == 0: data = stream.read(CHUNK) frames.append(data) print('錄音完成,輸出文件:' + WAVE_OUTPUT_FILENAME + '\n') stream.stop_stream() stream.close() p.terminate() wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') wf.setnchannels(1) wf.setsampwidth(p.get_sample_size(FORMAT)) # Returns the size (in bytes) for the specified sample format. wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close() return # 可以直接運行rec.py進行測試,同時保證該文件import時不會自動運行 if __name__ == '__main__': rec_fun()
通過樹莓派一 點亮LED燈:https://www.luodeb.top/2020/06/21/raspberry/?from=timeline,我們對樹莓派的陣腳已經(jīng)有了大概了解。
按鈕錄音,是通過按鈕控制陣腳高低電平。在上述代碼里引用```import RPi.GPIO as GPIO```,選擇26號輸出腳和GND。
執(zhí)行后按住按鈕開始錄音,會在rec.py同目錄下生成command.wav文件。
我選擇了百度AIP平臺,使用其語音識別技術(shù)。(當(dāng)然也可使用Google、科大訊飛等平臺)
1. 申請百度AIP賬號與應(yīng)用
在百度AI開發(fā)平臺:https://ai.baidu.com/?track=cp:aipinzhuan|pf:pc|pp:AIpingtai|pu:title|ci:|kw:10005792注冊賬號,再在控制臺創(chuàng)建一個新應(yīng)用
2. python調(diào)用百度AIP
官網(wǎng)文檔中有詳細使用語音識別技術(shù),包括python的示例。首先導(dǎo)入AipSpeech, 即百度AI語音識別的Python SDK客戶端(```pip3 install baidu-aip```)。附上代碼如下:
from aip import AipSpeech import os APP_ID = '你的IDID' API_KEY = '你的KEYKEY' SECRET_KEY = '你的secret_key' # 新建一個 AipSpeech client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 def get_file_content(filePath): #filePath待讀取文件名 with open(filePath, 'rb') as fp: return fp.read() # 語音識別 def stt(filename): # 識別本地文件 result = client.asr(get_file_content(filename), 'wav', 16000, {'dev_pid': 1537,} # dev_pid 參數(shù)表示識別的語 言類型 1537表示普通話 ) print (result) return result['result'] # 解析返回值,打印語音識別的結(jié)果 if result['err_msg']=='success.': word = result['result'][0].encode('utf-8') # utf-8 編碼 if word!='': if word[len(word)-3:len(word)]==',': print (word[0:len(word)-3]) with open('demo.txt','wb') as f: f.write(word[0:len(word)-3]) else: print (word.decode('utf-8').encode('gbk')) with open('demo.txt','wb') as f: f.write(word) f.close() else: print ('音頻文件不存在或格式錯誤') else: print ('錯誤') # main 函數(shù) 識別本地錄音文件 yahboom.wav if __name__ == '__main__': stt('command.wav') # command.wav為待讀取文件,請?zhí)鎿Q
使用圖靈機器人基本原理就是使用urllib.request模塊,向接口地址發(fā)送HTTP POST請求,請求中加入了聊天內(nèi)容。(返回內(nèi)容是一個字典)
首先我們需要申請一個機器人:官網(wǎng)入口:http://www.turingapi.com/
python代碼參考:
import json import urllib.request def chat(question): api_url = 'http://openapi.tuling123.com/openapi/api/v2' text_input = question req = { 'perception': { 'inputText': { 'text': text_input }, 'selfInfo': { 'location': { 'city': 'xxx', 'province': 'xxx', 'street': 'xxx' } } }, 'userInfo': { 'apiKey': 'xxxxxxxxxxxxx', #你的key 'userId': '123' #唯一的標(biāo)識,自選即可 } } # 將字典格式的req轉(zhuǎn)為utf8編碼的字符串 req = json.dumps(req).encode('utf8') print('\n' + '正在調(diào)用圖靈機器人API...') http_post = urllib.request.Request(api_url, data=req, headers={'content-type': 'application/json'}) response = urllib.request.urlopen(http_post) print('得到回答,輸出為字典格式:') response_str = response.read().decode('utf8') response_dic = json.loads(response_str) intent_code = response_dic['intent']['code'] # 返回網(wǎng)頁類的輸出方式 if(intent_code == 10023): results_url = response_dic['results'][0]['values']['url'] results_text = response_dic['results'][1]['values']['text'] with open('result.txt','w') as f: f.write(results_text) # 自帶文件關(guān)閉功能,不需要再寫f.close() answer = {'code': intent_code, 'text': results_text, 'url':results_url} print(answer) return(answer) # 一般的輸出方式 else: results_text = response_dic['results'][0]['values']['text'] answer = {'code': intent_code, 'text': results_text} with open('result.txt','w') as f: f.write(results_text) # 自帶文件關(guān)閉功能,不需要再寫f.close() print(answer) return(answer) if __name__ == '__main__': with open('demo.txt', 'r',encoding='UTF-8') as f: text = f.read() # 讀取文件 eg_question = text chat(eg_question)
我同樣選擇了百度的語音合成(注意,AI平臺新建應(yīng)用后,語音合成技術(shù)需要自行領(lǐng)用。語音識別的key與合成的key不一樣,使用請注意)。示例文檔自行參考,提供參考代碼:
#encoding:utf8 from aip import AipSpeech import os ''' 你的 APPID AK SK ''' APP_ID = 'xxxxx' API_KEY = 'xxxxxxxxxxxxxxxx' SECRET_KEY = 'chMdMAS0acD7sPS6FhP3a3iOijU7wMVl' def speak(text_content): client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) texts = text_content result = client.synthesis(texts , options={'vol':5}) print('\n' + '正在調(diào)用語音合成API...') if not isinstance(result,dict): with open('answer.mp3','wb') as f: f.write(result) else:print(result) print('播放音頻中...') print('以下均為mplayer的輸出內(nèi)容\n') os.system('mplayer answer.mp3') return if __name__ == '__main__': with open('result.txt', 'rb') as f: # 打開文件 text = f.read() # 讀取文件 eg_text_content = text speak(eg_text_content)
至此,我們的錄音、識別、對話、合成已經(jīng)完成了,開始對這四個py文件進行封裝。
在封裝時,增加一個獲取獲取歌曲直鏈url1.py文件。
一個簡單的if else 完成了圖靈機器人對話到在線放歌的切換。
當(dāng)然,讀者還可以進一步完善,例如實現(xiàn)與圖靈機器人的多次對話直到退出。
需要參考我的全部代碼,可以去我的資源下載