美文网首页
Python实现机器人语音聊天

Python实现机器人语音聊天

作者: 嗨学编程 | 来源:发表于2018-12-24 16:25 被阅读0次

    一、前言说明

    1.功能简述

    Python学习资料或者需要代码、视频加Python学习群:960410445

    登录后进入聊天界面,如果服务器都在同一个地址,则都进入同一个房间

    进入/离开/发消息同一房间用户都可以看到,输入“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

    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 = "10623076"

    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

    三、总结

      此文在本地语音保存解析过程有时间差问题,读者可自行优化。

    相关文章

      网友评论

        本文标题:Python实现机器人语音聊天

        本文链接:https://www.haomeiwen.com/subject/eepzkqtx.html