树莓派功能十分强大,作为一个微型电脑,独特的阵脚设计使得树莓派开发的自定义程度非常高。本篇博客通过使用python语言,封装一个简单的语音助手程序。
零、物品清单
1 2 3 4 5
| 1:一个树莓派(3代、4代皆可) 2:免驱的usb声卡(声卡需接在树莓派usb接口) 3:麦克风(接在声卡上) 4:有线音响(音响可连在声卡上,也可连在树莓派的3.5mm接口上) (树莓派播放设备默认使用3.5mm接口,具体过程需要自定义播放设备)
|
如果要设置usb声卡输出,参考教程配置声卡教程,如果使用默认3.5mm接口输出可以忽略。
设计语音助手有如下过程:录音、语音识别、图灵机器人对话、语音合成,以下对各个过程进行介绍。
一、pyaudio录音
使用python语言进行录音,主要是将说话者声音输出成一段音频文件。对于python来说,这很容易。通过引用pyaudio库,可以进行录音、播放、生成wav文件等。
首先,我们在树莓派上需要下载pyaudio库: pip3 install pyaudio
在pyaudio的官网介绍上有对pyaudio的详细介绍pyaudio官网,以官网示例:
创建一名为rec的python文件 sudo nano rec.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import RPi.GPIO as GPIO import pyaudio import wave import os import sys def rec_fun(): BUTT = 26 GPIO.setmode(GPIO.BCM) GPIO.setup(BUTT, GPIO.IN, pull_up_down = GPIO.PUD_UP) CHUNK = 512 FORMAT = pyaudio.paInt16 RATE = 16000 WAVE_OUTPUT_FILENAME = "command.wav" print('请按住按钮开始录音...') GPIO.wait_for_edge(BUTT, GPIO.FALLING) p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = 1, rate = RATE, input = True, frames_per_buffer = CHUNK) print("录音中...") frames = [] 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)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close() return
if __name__ == '__main__': rec_fun()
|
通过树莓派一 点亮LED灯,我们对树莓派的阵脚已经有了大概了解。
按钮录音,是通过按钮控制阵脚高低电平。在上述代码里引用import RPi.GPIO as GPIO
,选择26号输出脚和GND。
执行后按住按钮开始录音,会在rec.py同目录下生成command.wav文件。
二、语音识别
我选择了百度AIP平台,使用其语音识别技术。(当然也可使用Google、科大讯飞等平台)
1. 申请百度AIP账号与应用
在百度AI开发平台注册账号:官网链接
再在控制台创建一个新应用,如下图
2. python调用百度AIP
官网文档中有详细使用语音识别技术,包括python的示例。首先导入AipSpeech, 即百度AI语音识别的Python SDK客户端(pip3 install baidu-aip
)。附上代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| from aip import AipSpeech import os
APP_ID = '你的IDID' API_KEY = '你的KEYKEY' SECRET_KEY = '你的secret_key'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
def get_file_content(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,} ) print (result) return result['result']
if result['err_msg']=='success.': word = result['result'][0].encode('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 ("错误")
if __name__ == '__main__': stt('command.wav')
|
三、与图灵机器人对话
使用图灵机器人基本原理就是使用urllib.request模块,向接口地址发送HTTP POST请求,请求中加入了聊天内容。(返回内容是一个字典)
首先我们需要申请一个机器人:官网入口
python代码参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| 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", "userId": "123" } } req = json.dumps(req).encode('utf8') print('\n' + '正在调用图灵机器人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'] 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) 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) 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平台新建应用后,语音合成技术需要自行领用。语音识别的key与合成的key不一样,使用请注意)。示例文档自行参考,提供参考代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 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' + "正在调用语音合成API...")
if not isinstance(result,dict): with open('answer.mp3','wb') as f: f.write(result) else:print(result)
print("播放音频中...") print("以下均为mplayer的输出内容\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)
|
五、封装
至此,我们的录音、识别、对话、合成已经完成了,开始对这四个py文件进行封装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import rec import speech_api import turing import tts import os rec.rec_fun() recognize = speech_api.stt('command.wav') print("111") print(recognize) if recognize[0] == "音乐。": rec.rec_fun() recognize1 = speech_api.stt('command.wav') os.system("python3 url1.py " +recognize1[0]) else: turing_answer = turing.chat(recognize)
tts.speak(turing_answer['text'])
|
下面,就开始与傻瓜机器人的快乐对话吧。
当然在封装时,引用了一个url1文件,是获取获取歌曲直链。
一个简单的if else 完成了图灵机器人对话到在线放歌的切换。
当然,读者还可以进一步完善,例如实现与图灵机器人的多次对话直到退出。