基礎篇連結:03【pinpong庫控制硬體】之 Latte Panda一代-1
銜接上一篇的學習基礎上,我們這節課進行比較熱門的語音控制硬體。大家想一下語音對於語音控制有什麼了解,我們需要怎麼實現呢?
在今年看的熱播劇「嚮往的生活」中,有一個機器人名叫小度,他能通過何炅老師說的話,然後能自動播放音樂、自動搜索相關信息(菜譜的做法、人物信息)、家電的控制以及簡單的問答功能。
那麼這一篇教程就教大家利用LattePanda一代,結合百度ai和我們的pinpong庫,通過python編程來實現簡單的語音控制開燈的效果。
視頻演示
一、實現原理
要達到語音控制硬體,那麼我們比不可以少的就是語音識別技術了。語音識別技術,也被稱為自動語音識別Automatic Speech Recognition,(ASR),其目標是將人類的語音中的詞彙內容轉換為計算機可讀的輸入,例如按鍵、二進位編碼或者字符序列。
這裡我們調用了百度ai的語音識別技術,通過錄音中的特徵提取,調用已有的識別引擎,識別所輸入的語音,最終轉化成字符序列讓主板能夠識別,當識別到正確的指令時,就可以實現相應功能的控制了。
1、pinpong庫(如一學習過上篇文章的內容則證明已經安裝了pinpong庫,無需再次安裝)
2、Lp必須要聯網
3、安裝百度ai庫
● 可以直接「win+r」,搜索框中輸入cmd按回車,之後輸入「pip install baidu-aip」按回車鍵即可自行進行安裝,此時如果安裝提示安裝超時,那麼可能是網絡問題,因為此命令默認調用國外的下載地址進行下載,為了較快下載安裝百度ai,我們直接用「pip install baidu-aip -i https://pypi.doubanio.com/simple」即可調用國內的網址進行下載。
4、安裝實現錄音需要的PyAudio庫
● 如果是python3.6版本及以下版本,可以直接「win+r」,搜索框中輸入cmd按回車,之後輸入「pip install PyAudio」按回車鍵即可自行進行安裝
● 如果是3.7及以上版本,則需要下載相應的文件到本地,再進行指令安裝。
注意:對於64位作業系統,Python 3.8下載PyAudio‑0.2.11‑cp38‑cp38‑win_amd64.whl,
Python 3.7下載PyAudio‑0.2.11‑cp37‑cp37m‑win_amd64.whl。
下載地址為;
https://sn9.us/dir/13403389-37201167-ba08a5
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudi
● 安裝:
安裝時記得指定一下whl文件所在的路徑,另外還要有權限,最好以管理員身份運行cmd:
5、wav轉化為pcm的工具
wav是我們錄音是自動生成的一個可以直接用播放器播放的音頻。而pcm是利用百度雲進行識別時,識識別效果最為準確的一種格式,所以當我們錄音成功時,需要轉換成pcm格式再進行識別。
這種音頻轉換的工具有很多,這裡我使用的是FFmpeg 這個工具,下載地址為:
https://pan.baidu.com/s/1xhCb8YuO9Q7YfHulxrsP7Q 提取碼為:6s1w
FFmpeg 環境變量配置:
首先你要解壓縮,然後找到bin目錄,我解壓在桌面文件ai中
7、選擇之前解壓時bin的位置進行添加,之後點擊ok確定添加。
8、至此我們添加系統環境變量已經完成,然後通過cmd指令進行驗證,輸入ffmpeg,按回車鍵,出現以下內容說明我們設置成功。
2、LattePanda(拿鐵熊貓)一代自帶的天線*1
注意:天線需要一直連接並處於聯網狀態,led燈接在數字引腳D9,按鈕模塊接在數字引腳D10,另外需要插上耳機在音頻播放接口上。
5.1百度雲上的設置操作
1、註冊百度雲帳號,百度搜索百度雲,點擊進入第一詞條,點擊免費註冊進行註冊
3、登錄成功後,在產品服務中找到我們需要的語音技術,並點擊進入。
5、可以簡單的編輯自己新建的應用,然後點擊立即創建即可創建成功
9、這裡我有一個小技巧,如果後面你需要用百度ai做其他好玩的功能時,這裡我們可以把所以可以免費領取的功能都領取,方便後面使用。甚至可以點擊語音合成的進行領取。
10、都添加成功後,我們可以點擊管理應用,回到我們的應用列表,找到我們需要的應用和對應的APPID、API Key、Secret Key,這三個中的關鍵參數都是我們代碼中所需要的。
5.2測試wav格式是否能成功轉換成pcm格式
1、首先要打開windows的錄音機,錄製一段音頻(說普通話),錄音時需要用到我的的耳機,這時自動生成的是wav格式的音頻。
找到錄音,並點擊打開
錄音成功後(可以自行發揮錄製一段話),後面修改名稱為audio,這裡我另存到了桌面的ceshi文件夾中。
2、我們通過cmd指令進行轉換
輸入命令 : ffmpeg -y -i audio.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 audio.pcm,按回車鍵,即可進行轉換。
成功之後,可以看到同一個文件夾內多了一個audio.pcm文件。
5.3利用百度語音識別的SDK應用
利用百度語音識別的功能,通過python代碼實現語音識別。注意python代碼文件和之前生成的audio.pcm一定要在同一個文件下才能進行識別。
5.3.1 代碼編寫
打開python的IDLE編譯器
點擊File-New File,即可新建python程序文檔
from aip import AipSpeech #導入百度語音識別庫
APP_ID = '22240549' #和我們百度雲中創建的應用的三個參數一致,按照自己所創建的應用參數對應進行替換
API_KEY = 'Px5NXYraIe9wIkCnvsba6y3c'
SECRET_KEY = 'dyFXnDy9RHmhgyoq20Y8W58xKKNpd2d4'
client=AipSpeech(APP_ID,API_KEY,SECRET_KEY)
#讀取文件
filePath="audio.pcm"
with open(filePath,'rb')as fp:
file_context=fp.read()
#識別本地文件
res=client.asr(file_context,'pcm',16000,{
'dev_pid':1537,
})
#列印初識別結果
print(res)
5.3.2 代碼運行
點擊Run運行程序,這是會提示保存文件到相應的位置,我們選擇和audio.pcm在同以文件夾下
得到的結果讓我們很開心,剛好是我們之前錄製的聲音。
5.3.4 asr函數解析
asr函數需要四個參數,第四個參數可以忽略,自有默認值,參照一下這些參數是做什麼的
1、第一個參數: speech 音頻文件流建立包含語音內容的Buffer對象, 語音文件的格式pcm 或者 wav 或者 amr。(雖說支持這麼多格式,但是只有pcm的支持是最好的)
2、第二個參數: format 文件的格式,包括pcm(不壓縮)、wav、amr(雖說支持這麼多格式,但是只有pcm的支持是最好的)
3、第三個參數: rate 音頻文件採樣率 如果使用剛剛的FFmpeg的命令轉換的,你的pcm文件就是16000
4、第四個參數: dev_pid 音頻文件語言id 默認1537(普通話 輸入法模型)
5.4利用PyAudio實現語音錄製功能
5.4.1編寫代碼
新建新的python文件,然後進行代碼的編寫
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 16000
RECORD_SECONDS = 2
WAVE_OUTPUT_FILENAME = "1.wav"#自動生成文件的名稱
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("開始錄音,請說話.")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("錄音結束,請閉嘴!")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
雙擊打開播放錄音,發現就是剛剛我們所錄的音,說明我們成功了。
5.5把錄音代碼寫到一個函數當中,方便我們後面的調用
接下來,我們將這段錄音代碼,寫在一個函數裡面,如果要錄音的話就調用
代碼編寫
建立一個文件 pyrec.py 並將錄音代碼和函數寫在內
# pyrec.py 文件內容
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 16000
RECORD_SECONDS = 2
def rec(file_name):
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("開始錄音,請說話.")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("錄音結束,請閉嘴!")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(file_name, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
代碼中的rec 函數就是我們調用的錄音函數,並且給他一個文件名,他就會自動將聲音寫入到文件中了
5.6通過代碼實現把wav的音頻文件轉換為pcm的文件
新建一個文件 wav2pcm.py,這個文件裡面的函數是專門為我們轉換wav文件的。
使用 os 模塊中的 os.system()方法,這個方法是執行系統命令用的, 在windows系統中的命令就是 cmd 裡面寫的東西,如dir , cd 這類的命令。
代碼編寫
# wav2pcm.py 文件內容
import os
def wav_to_pcm(wav_file):
# 假設 wav_file = "音頻文件.wav"
# wav_file.split(".") 得到["音頻文件","wav"] 拿出第一個結果"音頻文件" 與 ".pcm" 拼接 得到結果 "音頻文件.pcm"
pcm_file = "%s.pcm" %(wav_file.split(".")[0])
# 就是此前我們在cmd窗口中輸入命令,這裡面就是在讓Python幫我們在cmd中執行命令
os.system("ffmpeg -y -i %s -acodec pcm_s16le -f s16le -ac 1 -ar 16000 %s"%(wav_file,pcm_file))
return pcm_file
5.7錄音+語音識別
5.7.1代碼編寫
新建新的python文件,然後進行代碼的編寫
import pyrec #錄音函數文件
import wav2pcm #wav轉換成pcm函數文件
from aip import AipSpeech #百度語音識別庫文件
APP_ID = '22240549' #三個參數要與自己創建的應用對應的三個參數要一致
API_KEY = 'Px5NXYraIe9wIkCnvsba6y3c'
SECRET_KEY = 'dyFXnDy9RHmhgyoq20Y8W58xKKNpd2d4'
client=AipSpeech(APP_ID,API_KEY,SECRET_KEY)
pyrec.rec("1.wav") #錄音並自動生成文件,文件名為1.wav
pcm_file=wav2pcm.wav_to_pcm("1.wav") #自動轉換成pcm文件
#讀取得到的pcm文件
with open(pcm_file,'rb')as fp:
file_context=fp.read()
#通過百度的語音識別進行識別
res=client.asr(file_context,'pcm',16000,{
'dev_pid':1537,
})
#列印出識別到的結果
print(res)
5.7.2運行結果
按照列印的提示進行錄音,最終可以看到我們識別到了正確的結果。此時也可以看到我們的文件夾中多了兩個名為Oldboy.wav和Oldboy.pcm的音頻文件。
5.8加入pinpong庫實現語音控制
前面我們已經實現語音識別了,這裡我們只需要通過識別到的結果進行判斷,是否是我們所需要的指令,這樣我們就可以控制我們的硬體了。還有我們的錄音都是程序運行的瞬間就會啟動錄音功能,但是當我們用來控制硬體時語音一個觸發條件,這樣才更加方便我們實現語音控制。否則你想像一下我們每次實現語音控制,都要重新運行一下程序是不是很麻煩。這裡我選用的按鈕來替代觸發的條件開關(當然你也可以選擇其他的觸發條件)。
大家是不是已經摩拳擦掌了,那麼接下來我們就來進行程序的設計吧!
5.8.1代碼編寫
import pyrec #錄音函數文件
import wav2pcm #wav轉換成pcm函數文件
import time #導入時間庫
from aip import AipSpeech #調用百度的語音識別庫
from pinpong.board import Board,Pin #導入pinpong庫的相關內容
Board("leonardo").begin() # lp一代自帶leonardo主板,所以這裡選擇leonardo
led=Pin(Pin.D9,Pin.OUT) #初始化led燈引腳為D9
btn=Pin(Pin.D10,Pin.IN) #初始化按鈕的引腳為D10
APP_ID = '22240549' #三個參數要與自己創建的應用對應的三個參數要一致
API_KEY = 'Px5NXYraIe9wIkCnvsba6y3c'
SECRET_KEY = 'dyFXnDy9RHmhgyoq20Y8W58xKKNpd2d4'
client=AipSpeech(APP_ID,API_KEY,SECRET_KEY)
while True: #循環執行
b=btn.read_digital() #讀取D10號引腳的電平
print(b) #列印出D10引腳的電平狀態
time.sleep(1) #等待1s
if b==1: #判斷按鈕狀態是否等於1,如果等於則執行下面的代碼
pyrec.rec("Oldboy.wav") #錄音並自動生成文件,文件名為Oldboy.wav
pcm_file=wav2pcm.wav_to_pcm("Oldboy.wav") #自動轉換成pcm文件
#讀取得到的pcm文件
with open(pcm_file,'rb')as fp:
file_context=fp.read()
#通過百度的語音識別進行識別
res=client.asr(file_context,'pcm',16000,{
'dev_pid':1537,
})
#列印出識別到的結果
print(res)
#獲得識別結果中的中文
res_str=res.get("result")[0]
#列印出識別的中文
print(res_str)
#判斷識別結果中是否是開燈,如果是則執行開燈(給數字引腳D9高電平)
if '開燈' in res_str:
led.write_digital(1)
#判斷識別結果中是否是關燈,如果是則執行關燈(給數字引腳D9低電平)
if '關燈' in res_str:
led.write_digital(0)
time.sleep(0.5) #消除抖動
按下按鈕即可進行錄音,當錄音內容為「開燈」時,我們可以看到D9號引腳的led燈被點亮。再次按下按鈕進行錄音,當錄音內容為「關燈」時,我們可以看到D9號引腳的led燈熄滅了。
1、嘗試利用不同指令去控制不同的硬體
2、本文中我們利用觸發錄音方式是按鈕,可以選擇其他的觸發方式,有能力的人還可以嘗試通過語音喚醒去製作,那樣的話就和前文提到的「小度」功能一樣了!