Python实现机器人语音聊天
一、前言说明
1.功能简述
登录后进入聊天界面,如果服务器都在同一个地址,则都进入同一个房间
进入/离开/发消息同一房间用户都可以看到,输入“tuling”或“chatbot”可以切换为和Tuling机器人或者ChatBot聊天
按住Say说话,自动录音并转为文本发送
如果是跟机器人聊天,则自动回复文本并播放文本语音
Tuling,是图灵,已经录入大量中文对话,直接调用接口即可实现自动回复,实用于开发聊天软件
ChatBot,可自行训练机器人,让机器人拥有自己的语料库,实用于企业智能聊天个性化
2.需要的核心技术
a. 输入语音,识别后转换为输入文字
b. Tuling或ChatBot两种机器人,回复输出文字
c. 输出文字,转换为输出语音并播放
以上a和c主要调用Baidu提供的API进行转换,如果理解本文,可自行尝试调用Google提供的API实现,Google技术强大但是否对中文支持良好,博主不曾尝试不妄自揣度
3.环境说明
系统环境Win10,运行环境Python3.6,运行工具Pycharm
二、源码设计(贴上完整源码自己去理解)
1.运行顺序
(1)TrainChat.py训练本地chatbot机器人(每次更新训练内容,运行一次即可)
(2) server.py开启服务器
(3)client.py运行n次,每次运行都可登陆一个用户
2.服务器server.py
主要处理用户的登录校验,房间的人员消息处理
此处通过config.py中配置的列表PORT = range(1, 3)生成两个房间,地址分别是127.0.0.1:1和127.0.0.1:2(实用时可以无限个)
启用客户端前,这个服务器要先运行,代码中CommandHandler类拆解client客户端发送的信息中的命令,并绑定函数
import asynchat
import asyncore
from config import PORT # 定义结束异常类
class EndSession(Exception):
pass class ChatServer(asyncore.dispatcher):
"""
聊天服务器
"""
def __init__(self, port):
asyncore.dispatcher.__init__(self)
# 创建socket
self.create_socket()
# 设置 socket 为可重用
self.set_reuse_addr()
# 监听端口
self.bind(('', port))
self.listen(5)
self.users = {}
self.main_room = ChatRoom(self) def handle_accept(self):
conn, addr = self.accept()
ChatSession(self, conn) class ChatSession(asynchat.async_chat):
"""
负责和客户端通信
"""
def __init__(self, server, sock):
asynchat.async_chat.__init__(self, sock)
self.server = server
self.set_terminator(b'\n')
self.data = []
self.name = None
self.enter(LoginRoom(server)) def enter(self, room):
# 从当前房间移除自身,然后添加到指定房间
try:
cur = self.room
except AttributeError:
pass
else:
cur.remove(self)
self.room = room
room.add(self) def collect_incoming_data(self, data):
# 接收客户端的数据
self.data.append(data.decode("utf-8")) def found_terminator(self):
# 当客户端的一条数据结束时的处理
line = ''.join(self.data)
self.data = []
try:
self.room.handle(self, line.encode("utf-8"))
# 退出聊天室的处理
except EndSession:
self.handle_close() def handle_close(self):
# 当 session 关闭时,将进入 LogoutRoom
asynchat.async_chat.handle_close(self)
self.enter(LogoutRoom(self.server)) class CommandHandler:
"""
命令处理类
"""
def unknown(self, session, cmd):
# 响应未知命令
# 通过 aynchat.async_chat.push 方法发送消息
session.push(('Unknown command {} \n'.format(cmd)).encode("utf-8")) def handle(self, session, line):
line = line.decode()
# 命令处理
if not line.strip():
return
parts = line.split(' ', 1)
cmd = parts[0]
try:
line = parts[1].strip()
except IndexError:
line = ''
# 通过协议代码执行相应的方法
method = getattr(self, 'do_' + cmd, None)
try:
method(session, line)
except TypeError:
self.unknown(session, cmd) class Room(CommandHandler):
"""
包含多个用户的环境,负责基本的命令处理和广播
"""
def __init__(self, server):
self.server = server
self.sessions = [] def add(self, session):
# 一个用户进入房间
self.sessions.append(session) def remove(self, session):
# 一个用户离开房间
self.sessions.remove(session) def broadcast(self, line):
# 向所有的用户发送指定消息
# 使用 asynchat.asyn_chat.push 方法发送数据
for session in self.sessions:
session.push(line) def do_logout(self, session, line):
# 退出房间
raise EndSession class LoginRoom(Room):
"""
处理登录用户
"""
def add(self, session):
# 用户连接成功的回应
Room.add(self, session)
# 使用 asynchat.asyn_chat.push 方法发送数据
session.push(b'Connect Success') def do_login(self, session, line):
# 用户登录逻辑
name = line.strip()
# 获取用户名称
if not name:
session.push(b'UserName Empty')
# 检查是否有同名用户
elif name in self.server.users:
session.push(b'UserName Exist')
# 用户名检查成功后,进入主聊天室
else:
session.name = name
session.enter(self.server.main_room) class LogoutRoom(Room):
"""
处理退出用户
"""
def add(self, session):
# 从服务器中移除
try:
del self.server.users[session.name]
except KeyError:
pass class ChatRoom(Room):
"""
聊天用的房间
"""
def add(self, session):
# 广播新用户进入
session.push(b'Login Success')
self.broadcast((session.name + ' has entered the room.\n').encode("utf-8"))
self.server.users[session.name] = session
Room.add(self, session) def remove(self, session):
# 广播用户离开
Room.remove(self, session)
self.broadcast((session.name + ' has left the room.\n').encode("utf-8")) def do_say(self, session, line):
# 客户端发送消息
self.broadcast((session.name + ': ' + line + '\n').encode("utf-8")) def do_noone_say(self, session, line):
# 图灵回复消息
self.broadcast((line + '\n').encode("utf-8")) def do_chatbot_say(self, session, line):
# 图灵回复消息
self.broadcast(('ChatBot: ' + line + '\n').encode("utf-8")) def do_tuling_say(self, session, line):
# 图灵回复消息
self.broadcast(('Tuling: ' + line + '\n').encode("utf-8")) def do_look(self, session, line):
# 查看在线用户
session.push(b'All Online Users Are:\n')
for other in self.sessions:
session.push((other.name + '\n').encode("utf-8")) if __name__ == '__main__':
for i in range(len(PORT)):
ChatServer(PORT[i])
print("Chat server run at '127.0.0.1:{0}'".format(PORT[i]))
try:
asyncore.loop()
except KeyboardInterrupt:
print("Chat server exit")
server.py
3.训练chatbot的TrainChat.py
主要用来训练chatbot机器人,数据保存在本地sqlite数据库(如果没有数据库自动创建)
个人学习此数据足以,作为企业可改为mongodb保存数据,速度会有保障
#!/usr/bin/python
# -*- coding: utf-8 -*-
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer
from chatterbot.trainers import ChatterBotCorpusTrainer my_bot = ChatBot("Training demo",
database="./db.sqlite3") # 直接写语句训练
my_bot.set_trainer(ListTrainer)
my_bot.train(["你叫什么名字?", "我叫小白兔!", ])
my_bot.train([
"Test1",
"Test2",
"Test3",
"Test4",
]) # 使用自定义语句训练它
my_bot.set_trainer(ChatterBotCorpusTrainer)
my_bot.train("chatterbot.corpus.mytrain")
# while True:
# print(my_bot.get_response(input("user:")))
TrainChat.py
4.训练chatbot的语料库
提供了两种语料训练方法
(1)TrainChat.py里面可以直接写训练语句,也可开启通过聊天时候的语句自动训练
(2)自定义语料库训练,自定义语料格式,直接参照chatbot提供的一些写就行
找到安装chatbot后默认提供的中文语料格式D:\Python\Lib\site-packages\chatterbot_corpus\data\chinese
打开后格式就有了,这里我们按照格式新增一个mytrain文件夹,写入自己的语料文件,如我写的phone.yml
categories:
- phone
conversations:
- - iPhoneX
- iPhone X是Apple(苹果公司)于北京时间2017年9月13日凌晨1点,在Apple Park新总部的史蒂夫·乔布斯剧院会上发布的新机型。其中“X”是罗马数字“10”的意思,代表着苹果向iPhone问世十周年致敬。iPhone X属于高端版机型,采用全新设计,搭载色彩锐利的OLED屏幕,配备升级后的相机,使用3D面部识别(Face ID)传感器解锁手机,支持AirPower(空中能量)无线充电。分为64GB、256GB两个版本,中国大陆起售价8388人民币,美国起售价999美元,2017年10月27日预售,11月3号正式开卖。
- - 三星Galaxy S6
- 三星Galaxy S6是三星公司(SAMSUNG)在2015年3月2日推出的一款手机,已于2015年4月11日正式上市。\n三星Galaxy S6采用5.1英寸屏幕,2560×1440像素,像素密度高达573ppi,内置Exynos 7420八核64位处理器,能够提供更强的性能以及更低的功耗;采用前500W像素+后1600W像素的双镜头设计,均支持F1.9大光圈,感光元件是索尼IMX 240,支持OIS光学防抖和自动HDR技术。
- - 华为P8
- P系列是华为手机中的旗舰系列,到2017年1月,共有6款机型:P1、P2、P6、P7、P8、P8 MAX、P9、P9 Plus。从2012年1月11日在美国拉斯维加斯发布全球最薄6.68毫米的P1开始,P系列便创立了以惊艳ID设计融合强大均衡软硬件配置为主的旗舰产品地位。之后,华为于2013年6月18日发布P6,2014年5月7日发布P7,均分别轻松创下了数百万销量的佳绩,一举奠定了华为在国内领先、国际一流的品牌地位
phone.yml
(3)说明:评论区读者朋友【逾行】说这里会报错,原因应该是包chatbot升级后,修改了写法,毕竟我这个博客写的有两年的时间了,读者朋友可以按评论区的修改试试
trainer = ListTrainer(chatbot)
trainer.train([
"text1",
"text.2",
])
#!/usr/bin/python
# -*- coding: utf-8 -*-
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer
my_bot = ChatBot("Training demo", database_uri='sqlite:///db.sqlite3')
trainer = ListTrainer(my_bot)
# 直接写语句训练
trainer.train(["你叫什么名字?", "我叫小白兔!", ])
trainer.train([
"Test1",
"Test2",
"Test3",
"Test4",
])
# 使用自定义语句训练它
trainer.train("chatterbot.corpus.mytrain")
5.录音并保存文件recorder.py
提供录音功能并将录音文件保存在本地
#!/usr/bin/python3
# -*- coding: utf-8 -*- from pyaudio import PyAudio, paInt16
import numpy as np
from datetime import datetime
import wave
import sys
import time class Recoder:
NUM_SAMPLES = 2000 # py audio内置缓冲大小
SAMPLING_RATE = 8000 # 取样频率
LEVEL = 500 # 声音保存的阈值
COUNT_NUM = 20 # NUM_SAMPLES个取样之内出现COUNT_NUM个大于LEVEL的取样则记录声音
SAVE_LENGTH = 8 # 声音记录的最小长度:SAVE_LENGTH * NUM_SAMPLES 个取样
TIME_COUNT = 10 # 录音时间,单位s Voice_String = [] def savewav(self, filename):
wf = wave.open(filename, 'wb')
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(self.SAMPLING_RATE)
wf.writeframes(np.array(self.Voice_String).tostring())
# wf.writeframes(self.Voice_String.decode())
wf.close() def recoder(self):
pa = PyAudio()
stream = pa.open(format=paInt16, channels=1, rate=self.SAMPLING_RATE, input=True,
frames_per_buffer=self.NUM_SAMPLES)
save_count = 0
save_buffer = []
time_count = self.TIME_COUNT while True:
time_count -= 1
# print time_count
# 读入NUM_SAMPLES个取样
string_audio_data = stream.read(self.NUM_SAMPLES)
# 将读入的数据转换为数组
audio_data = np.fromstring(string_audio_data, dtype=np.short)
# 计算大于LEVEL的取样的个数
large_sample_count = np.sum( audio_data > self.LEVEL )
print(np.max(audio_data))
# 如果个数大于COUNT_NUM,则至少保存SAVE_LENGTH个块
if large_sample_count > self.COUNT_NUM:
save_count = self.SAVE_LENGTH
else:
save_count -= 1 if save_count < 0:
save_count = 0 if save_count > 0:
# 将要保存的数据存放到save_buffer中
# print save_count > 0 and time_count >0
save_buffer.append(string_audio_data )
else:
# print save_buffer
# 将save_buffer中的数据写入WAV文件,WAV文件的文件名是保存的时刻
# print "debug"
if len(save_buffer) > 0 :
self.Voice_String = save_buffer
save_buffer = []
print("Recode a piece of voice successfully!")
return True
if time_count == 0:
if len(save_buffer)>0:
self.Voice_String = save_buffer
save_buffer = []
print("Recode a piece of voice successfully!")
return True
else:
return False def recording():
r = Recoder()
r.recoder()
r.savewav(r"E:\Python_Doc\voice_say\say_voice.wav")
recorder.py
6. chatbot.py
提供播放音频文件
调用图灵Tuling接口返回文本信息
调用chatbot返回文本信息
调用百度api语音识别
调用百度api转文本为语音(有两个百度api都可用,第一个不用密匙),其中chatbot的数据库配置要和TrainChat.py中配置的名称一致
import pygame
from chatterbot import ChatBot
import requests
import json
from config import *
import time
import os
import random
import urllib.request
import base64 # 初始化百度返回的音频文件地址,后面会变为全局变量,随需改变
mp3_url = 'E:\Python_Doc\\voice_du\\voice_ss.mp3' # 播放Mp3文件
def play_mp3():
# 接受服务器的消息
pygame.mixer.init()
pygame.mixer.music.load(mp3_url)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
time.sleep(1)
pygame.mixer.music.stop()
pygame.mixer.quit() # 删除声音文件
def remove_voice():
path = r"E:\Python_Doc\voice_du"
for i in os.listdir(path):
path_file = os.path.join(path, i)
try:
os.remove(path_file)
except:
continue # 图灵自动回复
def tuling(info):
url = tuling_url + "?key=%s&info=%s" % (tuling_app_key, info)
content = requests.get(url, headers=headers)
answer = json.loads(content.text)
return answer['text'] # 聊天机器人回复
def chatbot(info):
my_bot = ChatBot("", read_only=True,
database="./db.sqlite3")
res = my_bot.get_response(info)
return str(res) # 百度讲文本转为声音文件保存在本地 tts地址,无需token实时认证
def baidu_api(answer):
api_url = '{11}?idx={0}&tex={1}&cuid={2}&cod={3}&lan={4}&ctp={5}&pdt={6}&spd={7}&per={8}&vol={9}&pit={10}'\
.format(baidu_api_set["idx"], answer, baidu_api_set["cuid"], baidu_api_set["cod"], baidu_api_set["lan"],
baidu_api_set["ctp"], baidu_api_set["pdt"], baidu_api_set["spd"], baidu_api_set["per"],
baidu_api_set["vol"], baidu_api_set["pit"], baidu_api_url)
res = requests.get(api_url, headers=headers2)
# 本地Mp3语音文件保存位置
iname = random.randrange(1, 99999)
global mp3_url
mp3_url = 'E:\Python_Doc\\voices\\voice_tts' + str(iname) + '.mp3'
with open(mp3_url, 'wb') as f:
f.write(res.content) # 百度讲文本转为声音文件保存在本地 方法2 tsn地址
def baidu_api2(answer):
# 获取access_token
token = getToken()
get_url = baidu_api_url2 % (urllib.parse.quote(answer), "test", token)
voice_data = urllib.request.urlopen(get_url).read()
# 本地Mp3语音文件保存位置
name = random.randrange(1, 99999)
global mp3_url
mp3_url = 'E:\Python_Doc\\voice_du\\voice_tsn' + str(name) + '.mp3'
voice_fp = open(mp3_url, 'wb+')
voice_fp.write(voice_data)
voice_fp.close()
return # 百度语音转文本
def getText(filename):
# 获取access_token
token = getToken()
data = {}
data['format'] = 'wav'
data['rate'] = 16000
data['channel'] = 1
data['cuid'] = str(random.randrange(123456, 999999))
data['token'] = token
wav_fp = open(filename, 'rb')
voice_data = wav_fp.read()
data['len'] = len(voice_data)
data['speech'] = base64.b64encode(voice_data).decode('utf-8')
post_data = json.dumps(data)
# 语音识别的api url
upvoice_url = 'http://vop.baidu.com/server_api'
r_data = urllib.request.urlopen(upvoice_url, data=bytes(post_data, encoding="utf-8")).read()
print(json.loads(r_data))
err = json.loads(r_data)['err_no']
if err == 0:
return json.loads(r_data)['result'][0]
else:
return json.loads(r_data)['err_msg'] # 获取百度API调用的认证,实时生成,因为有时间限制
def getToken():
# token认证的url
api_url = "https://openapi.baidu.com/oauth/2.0/token?" \
"grant_type=client_credentials&client_id=%s&client_secret=%s"
token_url = api_url % (BaiDu_API_Key_GetVoi, BaiDu_Secret_Key_GetVoi)
r_str = urllib.request.urlopen(token_url).read()
token_data = json.loads(r_str)
token_str = token_data['access_token']
return token_str
chatbot.py
7.client.py
提供登录窗口,聊天窗口,已及响应事件
say按钮绑定sayDown录音和sayUp获取语音文本并发送两个事件
Users显示当前房间所有用户...
import wx
import telnetlib
from time import sleep
import _thread as thread
import time
import os
from chatbot import baidu_api2, chatbot, tuling, play_mp3, remove_voice, getText
from config import BOTS, BOT, default_server, VOICE_SWITCH
from recorder import recording bot_use = BOT class LoginFrame(wx.Frame):
"""
登录窗口
"""
def __init__(self, parent, id, title, size):
# 初始化,添加控件并绑定事件
wx.Frame.__init__(self, parent, id, title)
self.SetSize(size)
self.Center()
self.serverAddressLabel = wx.StaticText(self, label="Server Address", pos=(15, 40), size=(120, 25))
self.userNameLabel = wx.StaticText(self, label="UserName", pos=(45, 90), size=(120, 25))
self.serverAddress = wx.TextCtrl(self, value=default_server,
pos=(120, 37), size=(150, 25), style=wx.TE_PROCESS_ENTER)
self.userName = wx.TextCtrl(self, pos=(120, 87), size=(150, 25), style=wx.TE_PROCESS_ENTER)
self.loginButton = wx.Button(self, label='Login', pos=(50, 145), size=(90, 30))
self.exitButton = wx.Button(self, label='Exit', pos=(180, 145), size=(90, 30))
# 绑定登录方法
self.loginButton.Bind(wx.EVT_BUTTON, self.login)
# 绑定退出方法
self.exitButton.Bind(wx.EVT_BUTTON, self.exit)
# 服务器输入框Tab事件
self.serverAddress.SetFocus()
self.Bind(wx.EVT_TEXT_ENTER, self.usn_focus, self.serverAddress)
# 用户名回车登录
self.Bind(wx.EVT_TEXT_ENTER, self.login, self.userName)
self.Show() # 回车调到用户名输入栏
def usn_focus(self, event):
self.userName.SetFocus() def login(self, event):
# 登录处理
try:
serverAddress = self.serverAddress.GetLineText(0).split(':')
con.open(serverAddress[0], port=int(serverAddress[1]), timeout=10)
response = con.read_some()
if response != b'Connect Success':
self.showDialog('Error', 'Connect Fail!', (200, 100))
return
con.write(('login ' + str(self.userName.GetLineText(0)) + '\n').encode("utf-8"))
response = con.read_some()
if response == b'UserName Empty':
self.showDialog('Error', 'UserName Empty!', (200, 100))
elif response == b'UserName Exist':
self.showDialog('Error', 'UserName Exist!', (200, 100))
else:
self.Close()
ChatFrame(None, 2, title='当前用户:'+str(self.userName.GetLineText(0)), size=(515, 400))
except Exception:
self.showDialog('Error', 'Connect Fail!', (95, 20)) def exit(self, event):
self.Close() # 显示错误信息对话框
def showDialog(self, title, content, size):
dialog = wx.Dialog(self, title=title, size=size)
dialog.Center()
wx.StaticText(dialog, label=content)
dialog.ShowModal() class ChatFrame(wx.Frame):
"""
聊天窗口
"""
def __init__(self, parent, id, title, size):
# 初始化,添加控件并绑定事件
wx.Frame.__init__(self, parent, id, title, style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX |
wx.DEFAULT_FRAME_STYLE)
self.SetSize(size)
self.Center()
self.chatFrame = wx.TextCtrl(self, pos=(5, 5), size=(490, 310), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.sayButton = wx.Button(self, label="Say", pos=(5, 320), size=(58, 25))
self.message = wx.TextCtrl(self, pos=(65, 320), size=(240, 25), style=wx.TE_PROCESS_ENTER)
self.sendButton = wx.Button(self, label="Send", pos=(310, 320), size=(58, 25))
self.usersButton = wx.Button(self, label="Users", pos=(373, 320), size=(58, 25))
self.closeButton = wx.Button(self, label="Close", pos=(436, 320), size=(58, 25))
# 发送按钮绑定发送消息方法
self.sendButton.Bind(wx.EVT_BUTTON, self.send)
# 输入框回车发送信息
self.message.SetFocus()
# 发送消息
self.sayButton.Bind(wx.EVT_LEFT_DOWN, self.sayDown)
self.sayButton.Bind(wx.EVT_LEFT_UP, self.sayUp)
# 发送消息
self.Bind(wx.EVT_TEXT_ENTER, self.send, self.message)
# Users按钮绑定获取在线用户数量方法
self.usersButton.Bind(wx.EVT_BUTTON, self.lookUsers)
# 关闭按钮绑定关闭方法
self.closeButton.Bind(wx.EVT_BUTTON, self.close)
thread.start_new_thread(self.receive, ())
# self.ShowFullScreen(True)
self.Show() def sayDown(self, event):
thread.start_new_thread(recording, ())
# print("ON") def sayUp(self, event):
sayText = getText(r"E:\Python_Doc\voice_say\say_voice.wav")
self.message.AppendText(str(sayText))
self.send(self) def send(self, event):
# 发送消息
message = str(self.message.GetLineText(0)).strip()
global bot_use
if message != '':
if message == "chatbot":
bot_use = "ChatBot"
self.message.Clear()
con.write(('noone_say You have been changed ChatBot-Chat' + '\n').encode("utf-8"))
return
elif message == "tuling":
bot_use = "TuLing"
self.message.Clear()
con.write(('noone_say You have been changed TuLing-Chat' + '\n').encode("utf-8"))
return
elif message == "user":
bot_use = "User"
self.message.Clear()
con.write(('noone_say You have been changed User-Chat' + '\n').encode("utf-8"))
return
con.write(('say ' + message + '\n').encode("utf-8"))
self.message.Clear()
# 机器人回复
if bot_use == "ChatBot":
answer = chatbot(message)
con.write(('chatbot_say ' + answer + '\n').encode("utf-8"))
elif bot_use == "TuLing":
answer = tuling(message)
con.write(('tuling_say ' + answer + '\n').encode("utf-8"))
elif bot_use == "User":
return if VOICE_SWITCH:
# 写本地音乐文件
baidu_api2(answer)
# 新建线程播放音乐
thread.start_new_thread(play_mp3, ())
return def lookUsers(self, event):
# 查看当前在线用户
con.write(b'look\n') def close(self, event):
# 关闭窗口
thread.start_new_thread(remove_voice, ())
con.write(b'logout\n')
con.close()
self.Close() def receive(self):
# 接受服务器的消息
while True:
sleep(0.6)
result = con.read_very_eager()
if result != '':
self.chatFrame.AppendText(result) if __name__ == '__main__':
app = wx.App()
con = telnetlib.Telnet()
LoginFrame(None, -1, title="Login", size=(320, 250))
app.MainLoop()
client.py
8.config配置文件
百度API的KEY等内容也可自行去对应官网申请,本文提供仅供学习使用
# 默认输入的服务器地址,测试时候使用,避免登录总是输入地址麻烦
default_server = "127.0.0.1:1" # 定义服务器端口,一个端口一个房间
PORT = range(1, 3) # 图灵Tuling机器人还是ChatBot聊天机器人选择
BOTS = ["TuLing", "ChatBot", "User"]
BOT = BOTS[2] # 浏览器请求头文件
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36', }
headers2 = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
'(KHTML, like Gecko)Chrome/62.0.3202.94 Safari/537.36'} # 图灵密匙,自动回复地址,选择的key不同,tuling机器人的回答也各不相同
tuling_app_key = "e5ccc9c7c8834ec3b08940e290ff1559"
tuling_app_key2 = "4bc32d41c10be18627438ae45eb839ac"
tuling_url = "http://www.tuling123.com/openapi/api" # 语音保存播放开关
VOICE_SWITCH = True # 百度文本转语音地址和配置 tts地址
baidu_api_url = "http://tts.baidu.com/text2audio"
baidu_api_set = {"idx": 1, "cuid": "baidu_speech_demo", "cod": 2,
"lan": "zh", "ctp": 1, "pdt": 1, "spd": 4, "per": 4, "vol": 5, "pit": 5} # 百度文字转语音 tsn地址
baidu_api_url2 = "http://tsn.baidu.com/text2audio?tex=%s&lan=zh&cuid=%s&ctp=1&tok=%s"
BaiDu_API_Key_GetVoi = "2NagVAULCYCnOnamrc8MNUPc"
BaiDu_Secret_Key_GetVoi = "af4860b64e77d187643db05ccdb060e4" # 百度语音识别
BaiDu_App_ID = ""
BaiDu_API_Key = "2NagVAULCYCnOnamrc8MNUPc"
BaiDu_Secret_Key = "af4860b64e77d187643db05ccdb060e4"
BaiDu_OpenApi_Url = "https://openapi.baidu.com/oauth/2.0/token" \
"?grant_type=client_credentials&client_id=%&client_secret=%"
config.py
三、总结
此文在本地语音保存解析过程有时间差问题,读者可自行优化。
修改日志:将整个源码整合成一个项目ChatRoom,并传到GitHub:https://github.com/Vrapile/ChatRoom.git
Python实现机器人语音聊天的更多相关文章
- python 实现简单语音聊天机器人
'''思路:使用百度的文本转音频API,将结果保存成mp3格式,并用mp3play库播放该文件.''' 1 # -*- coding:utf-8 -*- import sys import reque ...
- Python实现机器人聊天
今天午休的时候,无意之中看了一篇博客,名字叫Python实现机器人,感觉挺有的意思的.于是用其写了一个简单的Python聊天,源码如下所示: # -*- coding: utf- -*- import ...
- 手把手教你用Python代码实现微信聊天机器人 -- Python wxpy
关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号 欢迎大家关注我的微信公众号:「醉翁猫咪」 来学习了,微信聊天机器人. 环境要求: Windows / Li ...
- Python微信机器人
Python微信机器人 本文目录 一 简介 二 登录微信 三 微信好友男女比例 四 微信好友地域分布 五 微信聊天机器人 一 简介 wxpy基于itchat,使用了 Web 微信的通讯协议,,通过大量 ...
- Unity3D 实现简单的语音聊天 [iOS版本]
现在很多手机游戏中的聊天系统都加入语音聊天的功能,相比于传统的文字聊天,语音聊天在MMORPG中显得尤为重要,毕竟直接口头交流总比你码字快得多了,也更直观些. 实现语音聊天的方法很多,U3D中有不少第 ...
- Android 即时语音聊天工具 开发
使用融云SDK 1. 功能需求分析 1.1 核心功能需求: * 即时通讯 * 文字聊天 * 语音聊天 1.2 辅助功能需求: * 注册.登录 * 好友添加功能 * 好友关系管理 2. 融云即时通讯平台 ...
- C#实现多人语音聊天
在上一篇文章 实现一个简单的语音聊天室(多人语音聊天系统)中,我用C#实现了一个简单的语音聊天室,并给出了源代码下载.尽管有源代码,可是非常多朋友反映,理解起来还是有些模糊.不够清楚.如今想来,是由于 ...
- python写机器人玩僵尸骰子
python写机器人玩僵尸骰子由Al Sweigart用python发布注意:我正在为我的僵尸骰子模拟器寻找反馈,以及这一套指令.如果你觉得有什么地方可以改进,请发邮件到al@inventwithpy ...
- cordova使用webrtc与网页端及移动端视频、语音聊天
最近在做一个移动端与移动端.网页端文字.视频.语音聊天的功能.文字聊天使用websocket,在网上很多资料,也没什么难度.但是在视频.语音聊天上遇到了小小的难点.之前一直在找一些SDK想快速开发,例 ...
随机推荐
- 利用cookie判断文件下载完成
在网页下载文件时,该文件又是通过后台代码生成的,比如报表之类的.当需要生成文件过大时会耗费很多时间,而文件生成好传到页面的时候也没有事件可以监听它,像微软官网,谷歌,百度等下载方式都是通过提示五秒过后 ...
- Win10和子系统Ubuntu简单共享
Win10和子系统Ubuntu简单共享 C:\Users\用户名\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp ...
- [AngularJS]Chapter 1 AnjularJS简介
创建一个完美的Web应用程序是很令人激动的,但是构建这样应用的复杂度也是不可思议的.我们Angular团队的目标就是去减轻构建这样AJAX应用的复杂度.在谷歌我们经历过各种复杂的应用创建工作比如:GM ...
- Xdoclet + Ant自己主动生成Hibernate配置文件
在使用Hibernate的时候,过多的Hibernate配置文件是一个让人头疼的问题. 近期接触了Xdoclet这个工具. 它实际上就是一个自己主动代码生成的工具.Xdoclet不能单独执行,必须搭配 ...
- HDU 4309 Contest 1
最大流建图.开始以为旧桥有1000座,没敢用枚举,后来看看题目发现了只是十二座.枚举桥的状态没问题. 对于隧道的容量W,可以虚拟出第三个结点表示,如u->v.增加一个点p,u->p(INF ...
- NHibernate3剖析:Query篇之NHibernate.Linq增强查询
系列引入 NHibernate3.0剖析系列分别从Configuration篇.Mapping篇.Query篇.Session策略篇.应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种 ...
- Hadoop实战:使用Combiner提高Map/Reduce程序效率
好不easy算法搞定了.小数据測试也得到了非常好的结果,但是扔到进群上.挂上大数据就挂了.无休止的reduce不会结束了. .. .. .... .. ... .. ================= ...
- updatefile.sh - Linux下代码更新脚本
以下写的是一个关于文件上传的代码shell脚本 该篇文章主要有下面几个方面的考虑: 1.文章主要用于在Linux下代码包批量上传: 2.将被覆盖的代码备份做备份,用于兴许做问题查看或者代码的回退(回退 ...
- JAVA设计模式之【状态模式】
状态模式 水.固态.气态.液态 账户.正常状态.透支状态.受限状态 状态模式中,用一个状态类来分散冗长的条件语句,让系统有灵活性和可扩展性 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的 ...
- 文本编辑工具 Vim
Vim是Vi的升级版 vi和Vim的区别在于vi不会显示颜色,Vim会显示颜色 1.如果没有,可以安装 #yum install -y vim-enhanced