用 Python 实现自己的智能语音助理(百度语音 + 图灵机器人)

依稀记得去年生日,对着 Google 说 “Sing me Happy Birthday” 。
她真的给我唱了英文版的生日歌,满怀深情地(我感觉……)。最后还加了一串调皮的鼓声。
我转头对着公司的前台小姐姐说,看见没有,你的 Siri 不爱我。。。

呃,不瞎扯了。
基于以上的渊源,我用 Python 写了一个还算得上智能的语音助理。

截图如下:AI1

演示视频:用 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

1
2
$ sudo apt-get install portaudio19-dev
$ pip install pyaudio

同样的,PyAudio 装好以后,安装 SpeechRecognition :
pip install SpeechRecognition

录音代码
1
2
3
4
5
6
7
8
9
10
11
12
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 了,并且有向普通用户提供免费的调用额度。

注册成功以后,进入语音服务的控制台创建一个新的应用,记下自己的 AppIDAPI KeySecret Key
key

语音识别代码

百度 AI 有提供面向 Python 的框架 baidu-aip ,感觉就相当于重新打包以后的 requests 库,用来访问 REST API。这里简单起见,直接使用该框架。
安装:
pip install baidu-aip

语音识别代码如下(代码中的 Key 替换成自己的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
apikey

该平台也提供了开放的 REST API ,但是不像百度那样有打包自己的 SDK 。所以需要使用 Python 的 requests 库访问,代码如下:

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
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 号选手度丫丫)的,比较超出我的预期。

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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.dlllibmp3lame.dll,放置在 SoX 的安装目录下。
最后将安装目录添加至系统的 PATH 环境变量即可。

代码如下:

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
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 实现的智能语音机器人(二)

聊天截图:ai2

对了,这个是支持树莓派的。不过需要额外装一个USB音频驱动作为录音设备。参考树莓派3 音频配置及其应用场景(录音、VoIP 电话等)

参考资料

SpeechRecognition
百度语音
图灵机器人
PyAudio
SoX