依稀记得去年生日,对着 Google 说 "Sing me Happy Birthday" 。
她真的给我唱了英文版的生日歌,满怀深情地(我感觉……)。最后还加了一串调皮的鼓声。
我转头对着公司的前台小姐姐说,看见没有,你的 Siri 不爱我。。。
呃,不瞎扯了。
基于以上的渊源,我用 Python 写了一个还算得上智能的语音助理。
演示视频:用 Python 实现的智能语音机器人(一)
源代码
不要慌,用的现成的框架和公共 API,一百来行代码而已,权当游戏。
一、整体结构
没有做过多的设计(不懂。。。),整体就是一个简单的线性结构,顺序执行。
一次交互完毕后,从头开始重复执行。
SpeechRecognition(录音)--> 百度语音(Speech-to-Text)--> 图灵机器人(语义分析及应答)--> 百度语音(Text-to-Speech)--> PyAudio(音频播放)
二、SpeechRecognition
SpeechRecogintion 是 Python 的一个语音识别框架,已经对接了如谷歌和微软的 STT (语音转文本)服务。
本项目里的语音识别及合成用的是百度的开放服务,所以只是需要 SpeechRecogintion 的录音功能。
它可以检测语音中的停顿自动终止录音并保存,比 PyAudio 更人性化(代码写起来也更简单)。
安装依赖库
Windows
安装 SpeechRecognition 需要提前装好 Python 的 PyAudio 框架。PyAudio 貌似需要编译安装,Windows 系统上估计会有点麻烦。
我用的是 Anaconda 软件,Windows 系统上用它管理 Python 包很方便。
嫌这个软件太大的话,也有简化版的 Miniconda 。
装好以后直接执行下面的命令即可(当然也可以在 conda 的虚拟环境里安装,不赘述):
conda install pyaudio
PyAudio 装好以后,直接使用 Python 的包管理工具 pip
安装 SpeechRecognition 即可:
pip install SpeechRecognition
Linux
Linux 系统下就显得省事一点了。可以直接使用系统自带的包管理器安装 PyAudio (如 Ubuntu 和 Raspbian 系统的 apt-get
)
$ sudo apt-get install python3-pyaudio
当然也可以使用 pip
命令安装,不过需要提前装好编译用的依赖库 portaudio19 :
$ sudo apt-get install portaudio19-dev
$ pip install pyaudio
同样的,PyAudio 装好以后,安装 SpeechRecognition :
pip install SpeechRecognition
录音代码
import speech_recognition as sr
def rec(rate=16000):
r = sr.Recognizer()
with sr.Microphone(sample_rate=rate) as source:
print("please say something")
audio = r.listen(source)
with open("recording.wav", "wb") as f:
f.write(audio.get_wav_data())
rec()
从系统麦克风拾取音频数据,采样率为 16000(貌似百度语音 API 最高就支持到 16k 的采样率)。
之后把采集到的音频数据以 wav 格式保存在当前目录下的 recording.wav
文件中,供后面的程序使用。
录音完成后,可以找到录好的音频文件试听一下效果。
三、百度语音(STT)
创建应用
百度语音是百度云 AI 开放平台提供的支持语音识别和语音合成的服务,注册以后就可以直接访问它的 REST API 了,并且有向普通用户提供免费的调用额度。
注册成功以后,进入语音服务的控制台创建一个新的应用,记下自己的 AppID
、API Key
和 Secret Key
。
语音识别代码
百度 AI 有提供面向 Python 的框架 baidu-aip
,感觉就相当于重新打包以后的 requests 库,用来访问 REST API。这里简单起见,直接使用该框架。
安装:
pip install baidu-aip
语音识别代码如下(代码中的 Key 替换成自己的):
from aip import AipSpeech
APP_ID = 'Your AppID'
API_KEY = 'Your API Key'
SECRET_KEY = 'Your Secret Key'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
def listen():
with open('recording.wav', 'rb') as f:
audio_data = f.read()
result = client.asr(audio_data, 'wav', 16000, {
'dev_pid': 1536,
})
result_text = result["result"][0]
print("you said: " + result_text)
return result_text
listen()
简单来说,将 SpeechRecognition 录制的音频上传至百度语音的服务,返回识别后的文本结果并输出。
四、图灵机器人
图灵机器人是一个提供(一定额度内)免费的智能聊天服务的平台,注册以后就可以创建自己的聊天机器人并接入到项目中。
首先进入图灵机器人的控制台并创建一个新的聊天机器人,记下分配到的 apikey
。
该平台也提供了开放的 REST API ,但是不像百度那样有打包自己的 SDK 。所以需要使用 Python 的 requests 库访问,代码如下:
import requests
import json
TURING_KEY = "Your apikey"
URL = "http://openapi.tuling123.com/openapi/api/v2"
HEADERS = {'Content-Type': 'application/json;charset=UTF-8'}
def robot(text=""):
data = {
"reqType": 0,
"perception": {
"inputText": {
"text": ""
},
"selfInfo": {
"location": {
"city": "杭州",
"street": "网商路"
}
}
},
"userInfo": {
"apiKey": TURING_KEY,
"userId": "starky"
}
}
data["perception"]["inputText"]["text"] = text
response = requests.request("post", URL, json=data, headers=HEADERS)
response_dict = json.loads(response.text)
result = response_dict["results"][0]["values"]["text"]
print("the AI said: " + result)
return result
robot("你好")
简单来说就是上传一个 json 格式的请求(包含聊天内容和个人信息等),获取到回复。再从收到的对象中提取出回复的文本。
五、百度语音(TTS)
其实大部分系统都有内置的 TTS (即文本转语音)引擎,如 MacOS 的 say
命令,只不过其中有很多都显得太“机械”,呃,缺少“人情味儿”。。。
百度的 TTS 引擎语音效果听起来还是很卡哇伊(4 号选手度丫丫)的,比较超出我的预期。
测试代码如下:
from aip import AipSpeech
APP_ID = 'Your AppID'
API_KEY = 'Your API Key'
SECRET_KEY = 'Your Secret Key'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
def speak(text=""):
result = client.synthesis(text, 'zh', 1, {
'spd': 4,
'vol': 5,
'per': 4,
})
if not isinstance(result, dict):
with open('audio.mp3', 'wb') as f:
f.write(result)
speak("你好啊")
就是把需要转换成语音的文本内容上传,再将返回的数据保存在本地。貌似只能生成 mp3 格式。
六、PyAudio 播放
这个我有点方。。。没找到 Python 播放 MP3 的合适的方法,所以用 os.system 调用系统中的 sox
命令将 MP3 转为 wav 格式,再用 PyAudio 播放。
sox 安装
SoX 是一个强大的跨平台的音频处理工具,Linux 系统可以直接使用包管理器安装:
$ sudo apt-get install sox libsox-fmt-mp3
Windows 系统安装的默认的 SoX 是不包含 mp3 格式支持的,所以需要自己编译(手动狗头)或者下载已经编译好的 dll 文件(libmad.dll 和 libmp3lame.dll,放置在 SoX 的安装目录下。
最后将安装目录添加至系统的 PATH 环境变量即可。
代码如下:
import pyaudio
import wave
import os
import time
def play():
os.system('sox audio.mp3 audio.wav')
wf = wave.open('audio.wav', 'rb')
p = pyaudio.PyAudio()
def callback(in_data, frame_count, time_info, status):
data = wf.readframes(frame_count)
return (data, pyaudio.paContinue)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
stream.start_stream()
while stream.is_active():
time.sleep(0.1)
stream.stop_stream()
stream.close()
wf.close()
p.terminate()
play()
七、最终代码及视频演示
整合后的最终代码我就不再贴一遍了,100 行左右,已上传至 Github 。
第二个视频:用 Python 实现的智能语音机器人(二)
对了,这个是支持树莓派的。不过需要额外装一个USB音频驱动作为录音设备。参考树莓派3 音频配置及其应用场景(录音、VoIP 电话等)
参考资料
SpeechRecognition
百度语音
图灵机器人
PyAudio
SoX