一、前言说明

  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升级后,修改了写法,毕竟我这个博客写的有两年的时间了,读者朋友可以按评论区的修改试试  

  chatbot = ChatBot('Training demo')
  trainer = ListTrainer(chatbot)
  trainer.train([
    "text1",
    "text.2",
  ])
 
  博主最近更新Python3.6到Python3.8,chatterbot也同步更新,证实上述写法是OK的,需要删掉之前生成的db.sqlite3,否则会报错,改后的文件内容如下
#!/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实现机器人语音聊天的更多相关文章

  1. python 实现简单语音聊天机器人

    '''思路:使用百度的文本转音频API,将结果保存成mp3格式,并用mp3play库播放该文件.''' 1 # -*- coding:utf-8 -*- import sys import reque ...

  2. Python实现机器人聊天

    今天午休的时候,无意之中看了一篇博客,名字叫Python实现机器人,感觉挺有的意思的.于是用其写了一个简单的Python聊天,源码如下所示: # -*- coding: utf- -*- import ...

  3. 手把手教你用Python代码实现微信聊天机器人 -- Python wxpy

    关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号 欢迎大家关注我的微信公众号:「醉翁猫咪」 来学习了,微信聊天机器人. 环境要求: Windows / Li ...

  4. Python微信机器人

    Python微信机器人 本文目录 一 简介 二 登录微信 三 微信好友男女比例 四 微信好友地域分布 五 微信聊天机器人 一 简介 wxpy基于itchat,使用了 Web 微信的通讯协议,,通过大量 ...

  5. Unity3D 实现简单的语音聊天 [iOS版本]

    现在很多手机游戏中的聊天系统都加入语音聊天的功能,相比于传统的文字聊天,语音聊天在MMORPG中显得尤为重要,毕竟直接口头交流总比你码字快得多了,也更直观些. 实现语音聊天的方法很多,U3D中有不少第 ...

  6. Android 即时语音聊天工具 开发

    使用融云SDK 1. 功能需求分析 1.1 核心功能需求: * 即时通讯 * 文字聊天 * 语音聊天 1.2 辅助功能需求: * 注册.登录 * 好友添加功能 * 好友关系管理 2. 融云即时通讯平台 ...

  7. C#实现多人语音聊天

    在上一篇文章 实现一个简单的语音聊天室(多人语音聊天系统)中,我用C#实现了一个简单的语音聊天室,并给出了源代码下载.尽管有源代码,可是非常多朋友反映,理解起来还是有些模糊.不够清楚.如今想来,是由于 ...

  8. python写机器人玩僵尸骰子

    python写机器人玩僵尸骰子由Al Sweigart用python发布注意:我正在为我的僵尸骰子模拟器寻找反馈,以及这一套指令.如果你觉得有什么地方可以改进,请发邮件到al@inventwithpy ...

  9. cordova使用webrtc与网页端及移动端视频、语音聊天

    最近在做一个移动端与移动端.网页端文字.视频.语音聊天的功能.文字聊天使用websocket,在网上很多资料,也没什么难度.但是在视频.语音聊天上遇到了小小的难点.之前一直在找一些SDK想快速开发,例 ...

随机推荐

  1. CF859C Pie Rules 动态规划 逆推_思维题

    题意:有 nnn 个物品,每个物品有不同的价值,物品按顺序分给两个人,有一块令牌,每回合拥有令牌的人拥有物品的分配权,但是该回合未获得物品的那个人会在下回合获得令牌,开始令牌在Bob手里,两个人都采取 ...

  2. Codeforces Round #493 (Div. 2) C. Convert to Ones 乱搞_构造_好题

    题意: 给你一个长度为 nnn 的 010101串 ,你有两种操作: 1.将一个子串翻转,花费 XXX 2.将一个子串中的0变成1,1变成0,花费 YYY 求你将这个01串变成全是1的串的最少花费. ...

  3. PAT 天梯赛练习集 L2-016. 愿天下有情人都是失散多年的兄妹

    题目链接:https://www.patest.cn/contests/gplt/L2-016 呵呵.大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人.父母.祖父母.曾祖父母. ...

  4. HDU 1028 Ignatius and the Princess III(母函数整数拆分)

    链接:传送门 题意:一个数n有多少种拆分方法 思路:典型母函数在整数拆分上的应用 /********************************************************** ...

  5. 移动端优先的flex三栏布局

    默认情况下先显示移动端,通过 @media 属性适配屏幕变化 使用flexbox相关的CSS属性 display: flex; (父元素) flex-wrap: nowrap | wrap | wra ...

  6. NOIP2018提高组金牌训练营——数论专题

    地址 https://www.51nod.com/live/liveDescription.html#!liveId=23 1187 寻找分数 给出 a,b,c,d, 找一个分数p/q,使得a/b & ...

  7. Tomcat样例安全漏洞

    [漏洞描述] Tomcat在使用的时候一般都直接官网下载源代码包直接使用. 默认情况下,Tomcat源码包里面包含了   examples   这个目录,这个目录主要实现一些样例页面的访问. 比如: ...

  8. Java线程:CountDownLatch 与Thread 的 join()

    需求: 主程序中需要等待所有子线程完成后 再继续任务 两种实现方式: 一种使用join() 方法:当在当前线程中调用某个线程 thread 的 join() 方法时,当前线程就会阻塞,直到thread ...

  9. SpringBoot中使用过滤器Filter

    场景:API的参数都是经过加密的,于是在过滤器中,将获取到的请求的参数先解密再去进行处理 一.实现Filter接口 public class TestFilter implements Filter ...

  10. tp框架报错 Namespace declaration statement has to be the very first statement in the script

    Namespace declaration statement has to be the very first statement in the script tp框架报这个错误,错误行数就是nam ...