1 前言
最近比较闲,简单了解了一下微信小程序开发,想着空闲时自己动手也写一个可以陪人聊天的小程序,后来发现类似的小程序已经有好几款了,而且做的都还不错。聊天机器人的好几年前就有了,但最近貌似又开始火热起来了,上次在车库咖啡听百度UNIT分享时,分享嘉宾说目前语音需求远大于图像处理,当时还有点不敢相信,但下面的常见场景大家都不陌生,可见语音到底有多火:
- 百度AI发布了DuerOS,”小度小度”的唤醒语火遍了朋友圈
- 微信和输入法中语音输入真是方便,再也不用担心妈妈不会打字了
- 龙泉寺的贤二机器人居然会跟大师探讨佛法、诵读经文,惊!
- 好友群中多了一个聊天机器人,比如QQ小冰(2854196306),@她后可以陪聊,天知道未来哪天我是在跟谁聊天
- DevOps方兴未艾,ChatOps产品却开始崭露头角,运维人员真是越来越懒了,命令都懒得敲了
- ……
大牛们总是敢为人先,好几年前都已经DIY出来一个能够红外识别人的聊天机器人,电梯直达。汗~,原来自己已经早早落伍啦,现在也利用Python玩玩大神的山寨版聊天机器人。
拼装一个聊天机器人竟然如次简单,你只需要:
语音交互的典型流程:用户说话–>录音–>百度语音识别为文字–>发送文字给图灵机器人–>处理图灵机器人回复文字结果–>将结果文字合成语音–>播放语音给用户。
2 服务调用
(1) 百度语音
百度语音可以调用REST服务,也可以本地安装一个客户端,具体参考开发文档。
https://ai.baidu.com/docs#/ASR-API/top
https://ai.baidu.com/docs#/TTS-API/top
这里选择安装Python SDK的方式进行:
1 |
# pip install baidu-aip |
语音合成及语音识别baidu_asr.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 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import json from aip import AipSpeech APP_ID = '10244407' API_KEY = 'eRbQtT8ACHxDWzePjrpLfh71' SECRET_KEY = 'XXXXXXXXXXXXXXXXXXXXXXX' aipSpeech = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 读取文件 def get_file_content(filePath): with open(filePath, 'rb') as fp: return fp.read() # 识别本地文件 def to_word(sound): result_str = aipSpeech.asr(get_file_content(sound), 'pcm', 16000, { 'lan': 'zh', }) if result_str.has_key('result'): out_txt = result_str['result'][0] else: out_txt = "Null" return out_txt # 转为语音 def to_sound(word,sound_path,per): result = aipSpeech.synthesis(word, 'zh', 1, { 'vol': 5, 'per': per, }) # 识别正确返回语音二进制 错误则返回dict 参照下面错误码 if not isinstance(result, dict): with open(sound_path, 'wb') as f: f.write(result) #print dict if __name__ == '__main__': to_sound('你好吗?','hello.mp3',3) print to_word('16k.pcm') |
注:语音合成中,per参数为发音人选择,0为女声,1为男声,3为情感合成-度逍遥,4为情感合成-度丫丫。
(2)图灵机器人
图灵机器人使用还是挺多的,试用版仅支持文字机器人,可以快速接入微信公众号/微信号/QQ,贤二机器僧公众号估计也是这样做的,接入微信公众号,可以自动文字回复呦,见下图:
服务调用也非常简单,具体查看官方文档:
http://www.tuling123.com/help/h_cent_webapi.jhtml?nav=doc
curl调用示例:
1 |
#curl -i -H 'Content-Type: application/json' -X POST -d '{"key":XXXXXXXXXXXXXXX,"info":"北京天气"}' http://www.tuling123.com/openapi/api |
Python客户端示例bot_1.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import requests, json github_url = 'http://www.tuling123.com/openapi/api' def do_chat(word): data = json.dumps({'key':'XXXXXXXXXXXXXXXXXXXXXXX', 'info':word}) r = requests.post(github_url, data, headers={'Accept': 'application/json'}) return r.json()['text'] if __name__ == '__main__': print do_chat('今天星期几?') |
3 机器人对聊
起两个图灵机器人客户端(bot_1.py&bot_2.py),让两个机器人对聊,哈哈,好无聊
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import time import bot_1, bot_2 if __name__ == '__main__': count = 0 ss = raw_input('启动!输入第一句话:') for i in range(1,20): ss1 = bot_1.do_chat(ss) print '机器人A:',ss1 ss = bot_2.do_chat(ss1) print '机器人B:',ss if ss1 == ss: count = count + 1 if count == 3: print '俩二货已经聊死了~' break |
加上语音合成,语音播放,这播放声音使用了pygame模块,需要提前安装:
1 |
# pip install pygame |
语音对聊模式:
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 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import time import pygame import baidu_asr import bot_1, bot_2 if __name__ == '__main__': count = 0 pygame.mixer.init() print int(time.time()) ss = raw_input('启动!输入第一句话:') for i in range(1, 20): ss1 = bot_1.do_chat(ss) now = (time.time()) print '机器人A:', ss1 sound1 = 'D:/' + str(now) + 'A.mp3' baidu_asr.to_sound(ss1, sound1, 1) track1 = pygame.mixer.music.load(sound1) pygame.mixer.music.play() while pygame.mixer.music.get_busy() == 1: time.sleep(0.5) ss = bot_2.do_chat(ss1) now = (time.time()) print '机器人B:', ss sound2 = 'D:/' + str(now) + 'B.mp3' baidu_asr.to_sound(ss, sound2, 0) track2 = pygame.mixer.music.load(sound2) pygame.mixer.music.play() while pygame.mixer.music.get_busy() == 1: time.sleep(0.5) if ss1 == ss: count = count + 1 if count == 3: print '俩二货已经聊死了~' break |
看看俩二货的聊天记录,也是醉了~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
启动!输入第一句话:我来啦 机器人A: 欢迎啊! 机器人B: 有种终极大boss的感觉。 机器人A: 我老爱你了 机器人B: 知道啦,我也爱你。 机器人A: 么么哒 机器人B: 我要两个,外加一个抱抱。 机器人A: 明天会发生更吃惊的~一切还在掌控范围之内 机器人B: 我非常的喜欢和你聊天 机器人A: 哎哟,不错哟,我也喜欢哟。 机器人B: 虚心使人进步,进步使人骄傲,骄傲使人落后。 机器人A: 感觉这句话你改的还行,就是不切实际。 机器人B: 你若不离不弃我必生死相依 机器人A: 你若生死相依,我立马跳崖自尽。 机器人B: 越来越喜欢你了 机器人A: 没道理不喜欢你。 机器人B: 什么道理,跟我说道说道。 机器人A: 你是我最喜欢的人 机器人B: 哈哈,好开心 机器人A: 为什么问我这个问题 机器人B: 没有为什么 机器人A: 又骗我,你的眼神出卖了你。 …… |
结果生成一堆语音片段,现在将这些片段合成一个mp3文件,这里利用pydub库进行合并,首先安装该库:
1 |
# pip install pydub |
然后下载ffmpeg.exe到指定目录,合成脚本sound_composition.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 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import os from pydub import AudioSegment AudioSegment.converter = "D:/ffmpeg.exe" def get_files(rootDir): files = [] for lists in os.listdir(rootDir): path = os.path.join(rootDir, lists) files.append(path) if os.path.isdir(path): (path) return files def do_composite(files,target_file): temp = files[0] print temp result = AudioSegment.from_mp3(temp) result.export(target_file, format="mp3") del files[0] for s in files: curr = AudioSegment.from_mp3(s) result = result + curr result.export('D:/all.mp3', format="mp3") print s if __name__ == '__main__': sounds = get_files('D:/sound/') do_composite(sounds,'D:/all.mp3') |
语音结果文件如下(语速略慢,太傻了):
4 朗读机器人
利用百度语音合成,进行网页中文本的朗读,这里选择左岸读书的文章《你还没有成功?是不是太努力了?》,
提前网页内容,语音合成代码及朗读代码如下:
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 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import time from selenium import webdriver from bs4 import BeautifulSoup import baidu_asr import sound_composition import pygame def get_content(): page_url = 'http://www.zreading.cn/archives/6086.html' driver = webdriver.PhantomJS() driver.get(page_url) dom = driver.page_source soup = BeautifulSoup(dom, 'lxml') content = [] # 提取标题 content.append(soup.h2.text) # 提取文章内容 p_list = soup.find_all('p') for p in p_list: content.append(p.text) if p.text.startswith(u'左岸记'): break return content if __name__ == '__main__': content = get_content() # 文字转语音 for p in content: now = time.time() baidu_asr.to_sound(p,'D:/sound/'+ str(now) +'.mp3',1) # 合并声音片段 sounds = sound_composition.get_files('D:/sound/') sound_composition.do_composite(sounds,'D:/all.mp3') # 朗读 pygame.mixer.init() track = pygame.mixer.music.load('D:/all.mp3') pygame.mixer.music.play() while pygame.mixer.music.get_busy() == 1: time.sleep(0.5) |
本例机器人朗读:
对比一下Talking Web机器人朗读:
再对比下人工朗读:
不难发现,机器人虽然很厉害,但与人的差距还很远,播音主持专业暂时是安全的,哈哈!
5 参考文档
http://www.codexiu.cn/python/blog/15810/
http://www.tuling123.com/help/h_cent_webapi.jhtml?nav=doc
https://gist.github.com/yangshaoshun/982722287ee2ee57ecec5372eeb7fc32
http://www.debugrun.com/a/e24n1ug.html
6 源码
https://github.com/zjmeixinyanzhi/python-chat-bot
code
more code
~~~~