提示
今年注冊(cè)的賬號(hào)可能百度敞葛,改變了下發(fā)的數(shù)據(jù)格式惹谐,不再是文本格式驼卖,是以鏈接的形式。具體的我還沒有研究怎囚。大家可以看返回的數(shù)據(jù)恳守,payload里面是text還是url,是text 的可以用我這個(gè)方法催烘,url的暫時(shí)還不行颗圣,等我有時(shí)間看一看如何提取在岂,會(huì)再更新的
本文是基于百度的DuerOS Python SDK進(jìn)行的蛮寂,具體安裝以及實(shí)現(xiàn)過(guò)程,可以看我的這篇教程:人工智能-樹莓派小車(1)——DuerOS語(yǔ)音喚醒及老,要實(shí)現(xiàn)的功能有:
- 語(yǔ)音聊天:可以跟智能小車進(jìn)行對(duì)話骄恶,詢問(wèn)現(xiàn)在的天氣匕垫,播放想聽的歌曲等等基本對(duì)話;
- 語(yǔ)音控制:可以通過(guò)語(yǔ)音的操作方式控制智能小車的前進(jìn)后退斟叼、避障轉(zhuǎn)彎等功能朗涩,進(jìn)一步可以擴(kuò)展到家里的臺(tái)燈绑改、空調(diào)绢淀、窗簾等等家具;
- 語(yǔ)音反饋:在你發(fā)出命令后覆履,小車還會(huì)給出回應(yīng)硝全,與你互動(dòng)楞抡,實(shí)現(xiàn)一個(gè)良好的反饋召廷。
視頻演示
實(shí)現(xiàn)了以上幾個(gè)功能竞慢,做了一個(gè)演示,視頻鏈接:通過(guò)語(yǔ)音玩轉(zhuǎn)智能小車
核心代碼
1. 命令讀取
content = u'云端下發(fā)directive:%s' % (directive_content)
content里即為我們要讀取的命令數(shù)據(jù)遮精,是一種類JSON格式本冲,所以有兩種辦法將數(shù)據(jù)讀取出來(lái)劫扒。
- 采用JSON的字典格式
import json
with open('out.json','a') as f:
f.write(json.loads(content).decode('unicode-escape').encode('utf-8'))
f.close()
- 直接將數(shù)據(jù)保存為.txt格式
f = open("ord.txt",'a')
f.write(content)
logging.info(content)
2. 命令判斷
讀取到命令之后要對(duì)其進(jìn)行檢測(cè)沟饥,如果命令中包含一些特定的關(guān)鍵詞,則做出相應(yīng)的動(dòng)作澎灸。
def recognize():
file = '/home/pi/Rascar-DuerOS-Python-Client/ord.txt' # 讀取文件
f = open(file,'r')
out = f.read()
command = out.decode('unicode-escape').encode('utf-8')
print command
GPIO.output(LED_CTR, GPIO.LOW)
############################################
###############命令識(shí)別######################
############################################
if command.find(u"開") !=-1 and command.find(u"大") !=-1 and command.find(u"燈") !=-1:
print "打開前大燈"
robot.Open_Flight()
GPIO.output(LED_CTR, GPIO.HIGH)
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_on_light.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
elif command.find(u"關(guān)") !=-1 and command.find(u"大") !=-1 and command.find(u"燈") !=-1:
print "關(guān)閉前大燈"
robot.Close_Flight()
GPIO.output(LED_CTR, GPIO.HIGH)
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_off_light.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
elif command.find(u"前") !=-1 and command.find(u"進(jìn)") !=-1:
print "前進(jìn)"
robot.Motor_Forward()
time.sleep(2)
robot.Motor_Stop()
GPIO.output(LED_CTR, GPIO.HIGH)
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/forward.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
elif command.find(u"后") !=-1 and command.find(u"退") !=-1:
print "后退"
robot.Motor_Backward()
time.sleep(2)
robot.Motor_Stop()
GPIO.output(LED_CTR, GPIO.HIGH)
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/backward.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
elif command.find(u"左") !=-1 and command.find(u"轉(zhuǎn)") !=-1:
print "左轉(zhuǎn)"
robot.Motor_TurnLeft()
p = GPIO.PWM(11, 3)
p.start(20)
time.sleep(0.5)
p.stop()
robot.Motor_Stop()
GPIO.output(11, GPIO.LOW)
GPIO.output(LED_CTR, GPIO.HIGH)
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_left.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
elif command.find(u"右") !=-1 and command.find(u"轉(zhuǎn)") !=-1:
print "右轉(zhuǎn)"
robot.Motor_TurnRight()
p = GPIO.PWM(8, 3)
p.start(20)
time.sleep(0.5)
p.stop()
robot.Motor_Stop()
GPIO.output(8, GPIO.LOW)
GPIO.output(LED_CTR, GPIO.HIGH)
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_right.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
elif command.find(u"黑") !=-1 and command.find(u"線") !=-1:
print "黑線"
robot.TrackLine()
return
其中GPIO接口的設(shè)置以及初始化县遣,見人工智能-樹莓派小車-GPIO控制小車
最后要養(yǎng)成良好習(xí)慣,用完GPIO接口記得清理GPIO口
GPIO.cleanup()
3. 命令文件清空
為避免命令文件堆積其兴,每次識(shí)別命令結(jié)束后元旬,進(jìn)行命令文件的清理守问,代碼很簡(jiǎn)單耗帕。
f = open("ord.txt",'w')
f.truncate()
f.close()
4. 命令反饋
這部分集成到了第二部分命令判斷中仿便,判斷完立即進(jìn)行反饋。
要注意的是荒勇,在第二部分每一條命令都有一條這樣的代碼
GPIO.output(LED_CTR, GPIO.HIGH)
這一步正是屏蔽掉DuerOS原有的語(yǔ)音反饋的關(guān)鍵
- 首先錄制好自己想要的話語(yǔ)枕屉,然后仿照我的代碼放到對(duì)應(yīng)的位置
shutil.copy("/home/pi/Rascar-DuerOS-Python-Client/app/resources/turn_right.mp3","/home/pi/Rascar-DuerOS-Python-Client/temp.mp3")
- 接下來(lái)是最關(guān)鍵的一步
在sdk/interface里面有一個(gè)speech_synthesizer.py文件搀擂,這個(gè)文件就是控制TTS語(yǔ)音輸出的卷玉,在這對(duì)代碼進(jìn)行一定修改相种,就可以實(shí)現(xiàn)播放我們自定義的音頻。
2.1
import RPi.GPIO as GPIO
LED_CTR = 5 #與上面端口一致腹备,用于檢測(cè)是否有控制指令發(fā)送
然后在speak函數(shù)加入一條檢測(cè)指令
def speak(self, directive):
'''
播放TTS(云端directive name方法)
:param directive: 云端下發(fā)directive
:return:
'''
# directive from dueros may not have the dialogRequestId
if 'dialogRequestId' in directive['header']:
dialog_request_id = directive['header']['dialogRequestId']
if self.dueros.speech_recognizer.dialog_request_id != dialog_request_id:
return
self.token = directive['payload']['token']
url = directive['payload']['url']
if url.startswith('cid:'):
mp3_file = os.path.join(tempfile.gettempdir(), url[4:] + '.mp3')
if os.path.isfile(mp3_file):
self.finished.clear()
# os.system('mpv "{}"'.format(mp3_file))
if GPIO.input(LED_CTR) == 1 :
self.player.play('file://{}'.format('/home/pi/DuerOS-Python-Client/temp.mp3'))
os.remove("temp.mp3")
else :
self.player.play('file://{}'.format(mp3_file))
self.__speech_started()
self.dueros.state_listener.on_speaking()
# will be set at SpeechFinished() if the player reaches the End Of Stream or gets a error
self.finished.wait()
os.system('rm -rf "{}"'.format(mp3_file))
就可以啦
完整代碼
所有的代碼都上傳到了我的GitHub上
Rascar-DuerOS — a Raspberry intelligent car based on the DuerOS
系列教程
人工智能-樹莓派小車(1)——DuerOS語(yǔ)音喚醒
人工智能-樹莓派小車(2)——GPIO接口介紹
人工智能-樹莓派小車(3)——GPIO控制小車
人工智能-樹莓派小車(4)——通過(guò)語(yǔ)音玩轉(zhuǎn)智能小車
人工智能-樹莓派小車(5)——用微信控制智能小車