import threading
import AI_Chatbots
from pyaudio import PyAudio, paInt16
import wave
from TextToSpeech import BaiduVoice
from cozeAPI import chat
import pygame
from datetime import datetime
# 继承AI_Chatbots.Ui_MainWindow类,实现AI聊天机器人的主要功能
class AI_botImpl(AI_Chatbots.Ui_MainWindow):
def __init__(self, window):
super().__init__()
self.setupUi(window)
# 设置推送按钮的样式
self.pushButton.setStyleSheet(u"background-color: rgb(85, 170, 0);\n"
"color: rgb(255, 255, 255);\n"
"font-size:20px;\n"
"border-radius:5px")
# # 初始化录音状态为False
# self.recording_status = False
# 连接按钮的pressed和released信号到相应的槽函数
self.recording_status = False # 录音状态,默认为False
self.pushButton.pressed.connect(self.start_recording)
self.pushButton.released.connect(self.stop_recording)
self.recording = False
# 创建线程锁,用于安全地操作共享数据frames
self.frames_lock = threading.Lock()
# 初始化音频数据列表
self.frames = []
# 设置音频块的大小
self.CHUNK = 1024
# 设置音频格式为16位整数
self.FORMAT = paInt16
# 设置音频通道数为1(单声道)
self.CHANNELS = 1
# 设置音频采样率为16000Hz
self.RATE = 16000
# 创建PyAudio对象
self.audio = PyAudio()
# 显示聊天记录的方法
def display_chat(self, user_input, bot_response):
# 获取当前时间
current_time = self.get_current_time()
# 格式化用户输入和机器人响应的时间戳文本
user_text = f"{current_time} 用户: {user_input}\n"
bot_text = f"{current_time} Bot: {bot_response}\n"
# 将文本添加到文本浏览器中显示
self.textBrowser.append(user_text)
self.textBrowser.append(bot_text)
# 获取当前时间的方法
def get_current_time(self):
# 返回格式化后的时间字符串
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 开始录音的方法
def start_recording(self):
# 如果当前没有录音,则开始录音的方法
if not self.recording:
self.recording = True
# 清空音频数据列表
with self.frames_lock:
self.frames.clear()
# 更新按钮文本和样式,以反映录音中的状态
self.pushButton.setText("录音中...")
self.pushButton.setStyleSheet(u"background-color: rgb(255, 0, 0);\n"
"color: rgb(255, 255, 255);\n"
"font-size:20px;\n"
"border-radius:5px")
print("录音中...")
# 创建录音线程并开始录音
self.record_audio_thread = threading.Thread(target=self.record_audio)
self.record_audio_thread.start()
# 停止录音的方法
def stop_recording(self):
"""
停止录音功能的方法。
本方法通过改变对象的状态来停止录音,同时更新用户界面的按钮文本和样式,
并尝试保存录音文件。确保录音线程安全结束是其核心功能之一。
"""
# 检查是否正在录音,是则停止录音
if self.recording:
self.recording = False
# 更新按钮文本和样式,以反映录音停止的状态
self.pushButton.setText("按住话筒说话")
self.pushButton.setStyleSheet(u"background-color: rgb(85, 170, 0);\n"
"color: rgb(255, 255, 255);\n"
"font-size:20px;\n"
"border-radius:5px")
print("停止录音...")
# 等待录音线程结束
self.record_audio_thread.join()
# 尝试保存录音文件,根据结果执行相应操作
success = self.save_audio()
if success:
print("录音文件保存成功!")
# 调用语音识别方法处理保存的音频
self.speech_recognition()
else:
print("录音文件保存失败!")
# 录音方法
def record_audio(self):
"""
录音方法。尝试打开音频流并开始录音,直到停止录音或发生异常。
"""
try:
# 打开音频流
stream = self.audio.open(format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
frames_per_buffer=self.CHUNK)
# 循环录音,直到停止录音
while self.recording:
# 读取音频数据,并将其添加到音频数据列表中
data = stream.read(self.CHUNK)
with self.frames_lock:
self.frames.append(data)
# 停止并关闭音频流
stream.stop_stream()
stream.close()
except Exception as e:
# 异常处理
print(f"Error during recording: {e}")
# 保存录音为WAV文件的方法
def save_audio(self):
"""
保存录音为WAV文件。
此函数尝试将之前录制的音频数据保存为WAV文件。它负责创建一个新的WAV文件,
设置适当的声道数、采样宽度、帧率,并将音频数据写入文件。如果操作成功,它将
打印确认消息并返回True。如果过程中发生任何错误,它将捕获异常,打印错误消息,
并返回False。
返回:
bool: 如果成功保存音频文件,则为True,否则为False。
"""
try:
# 定义文件名和路径,创建WAV文件并写入音频数据
filename = 'medium/user.wav'
wf = wave.open(filename, 'wb')
wf.setnchannels(self.CHANNELS)
wf.setsampwidth(self.audio.get_sample_size(self.FORMAT))
wf.setframerate(self.RATE)
with self.frames_lock:
wf.writeframes(b''.join(self.frames))
wf.close()
# 打印保存成功消息
print(f"录音文件已保存为 {filename}")
return True
except Exception as e:
# 异常处理
print(f"Error saving audio file: {e}")
return False
def speech_recognition(self):
"""
语音识别功能。
该方法使用百度语音识别服务识别预录制的音频文件。
如果识别成功,将调用coze_api方法处理识别结果。
如果识别失败,将输出失败信息。
"""
voice = BaiduVoice()
recognition_result = voice.recognize_speech('medium/user.wav')
print("已识别的文本:", recognition_result)
if recognition_result:
self.coze_api(recognition_result)
else:
print("识别失败")
def speech_synthesis(self, kword):
"""
语音合成功能。
该方法使用百度语音合成服务将文本转换为语音,并播放合成的语音。
初始化pygame模块以处理音频播放,并在播放完成后进行清理。
"""
voice = BaiduVoice()
voice.synthesize_text(kword, 'medium/bot.mp3')
print("已合成的语音文本:", kword)
pygame.init()
pygame.mixer.music.load('medium/bot.mp3')
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
pygame.quit()
def coze_api(self, kword):
"""
调用cozeapi接口并处理响应。
该方法首先调用cozeapi接口,传入关键词(kword),获取响应内容,
然后调用语音合成功能将响应内容转换为语音输出。
参数:
kword (str): 用户输入的关键词,用于查询或发送请求。
返回:
无
"""
print("调用cozeapi接口")
chat_response = chat(kword)
print(chat_response)
self.speech_synthesis(chat_response)
def on_send_button_clicked(self):
"""
处理发送按钮点击事件。
该方法在用户点击发送按钮时被触发,获取用户输入的文本,
并进行一些基本的验证,如检查输入是否为空。如果验证通过,
则清除输入框,并进行对话处理,显示用户输入和Bot的响应。
"""
user_input = self.textEdit.toPlainText()
if not user_input:
print("输入框不能为空")
return
self.textEdit.clear()
response = self.coze_bot_dialogue(user_input)
self.display_chat(user_input, response)
def coze_bot_dialogue(self, message):
"""
与coze机器人进行对话。
该方法作为与coze机器人交互的中介,将用户的消息传递给chat函数,
并返回机器人的响应。
参数:
message (str): 用户的消息。
返回:
str: 机器人的响应消息。
"""
return chat(message)
def display_chat(self, user_input, bot_response):
"""
在界面中显示聊天内容。
该方法将用户和机器人的对话内容格式化并显示在文本浏览器中,
同时为发送按钮绑定点击事件处理函数。
参数:
user_input (str): 用户的输入。
bot_response (str): 机器人的响应。
返回:
无
"""
user_text = f"用户: {user_input}\n"
bot_text = f"Bot: {bot_response}\n"
self.pushButton_2.clicked.connect(self.on_send_button_clicked)
1. 类定义和初始化
class AI_botImpl(AI_Chatbots.Ui_MainWindow):
def __init__(self, window):
super().__init__()
self.setupUi(window)
self.pushButton.setStyleSheet(u"background-color: rgb(85, 170, 0);\n"...
-
AI_botImpl
类继承自AI_Chatbots.Ui_MainWindow
,这表明它是一个基于Qt Designer的UI类。 -
在初始化方法
__init__
中,首先调用基类的构造函数super().__init__()
,然后调用self.setupUi(window)
来设置UI界面。 -
设置了推送按钮
self.pushButton
的样式,包括背景颜色、文字颜色、字体大小和边框圆角。
2. 录音状态和线程锁
self.recording_status = False # 录音状态,默认为False
self.pushButton.pressed.connect(self.start_recording)
self.pushButton.released.connect(self.stop_recording)
self.recording = False
self.frames_lock = threading.Lock()
self.frames = []
-
self.recording_status
和self.recording
用于控制录音的开始和停止。 -
self.frames_lock
是一个线程锁,用于在多线程环境下安全地操作self.frames
(音频数据列表)。
3. 音频参数设置
self.CHUNK = 1024
self.FORMAT = paInt16
self.CHANNELS = 1
self.RATE = 16000
self.audio = PyAudio()
-
self.CHUNK
设置音频块的大小为1024字节。 -
self.FORMAT
设置音频格式为16位整数。 -
self.CHANNELS
设置音频通道数为1(单声道)。 -
self.RATE
设置音频采样率为16000Hz。 -
self.audio
创建一个PyAudio
对象,用于音频的录制和播放。
4. 显示聊天记录
def display_chat(self, user_input, bot_response):
current_time = self.get_current_time()
user_text = f"{current_time} 用户: {user_input}\n"
bot_text = f"{current_time} Bot: {bot_response}\n"
self.textBrowser.append(user_text)
self.textBrowser.append(bot_text)
-
display_chat
方法用于在文本浏览器中显示用户和机器人的对话。 -
get_current_time
方法获取当前时间并格式化为字符串。
5. 录音方法
def start_recording(self):
if not self.recording:
self.recording = True
with self.frames_lock:
self.frames.clear()
self.pushButton.setText("录音中...")
self.pushButton.setStyleSheet(u"background-color: rgb(255, 0, 0);\n"...
print("录音中...")
self.record_audio_thread = threading.Thread(target=self.record_audio)
self.record_audio_thread.start()
-
start_recording
方法开始录音过程。 -
清空
self.frames
列表,准备新的录音数据。 -
更新按钮文本和样式,表示正在录音。
-
创建并启动一个线程来执行
record_audio
方法。
6. 停止录音
def stop_recording(self):
if self.recording:
self.recording = False
self.pushButton.setText("按住话筒说话")
self.pushButton.setStyleSheet(u"background-color: rgb(85, 170, 0);\n"...
print("停止录音...")
self.record_audio_thread.join()
success = self.save_audio()
if success:
print("录音文件保存成功!")
self.speech_recognition()
else:
print("录音文件保存失败!")
-
stop_recording
方法停止录音。 -
更新按钮文本和样式,表示录音已停止。
-
等待录音线程结束。
-
调用
save_audio
方法保存录音文件,并根据结果进行后续处理。
7. 录音线程
def record_audio(self):
try:
stream = self.audio.open(format=self.FORMAT, channels=self.CHANNELS, rate=self.RATE, input=True, frames_per_buffer=self.CHUNK)
while self.recording:
data = stream.read(self.CHUNK)
with self.frames_lock:
self.frames.append(data)
stream.stop_stream()
stream.close()
except Exception as e:
print(f"Error during recording: {e}")
-
record_audio
方法在单独的线程中运行,负责实际的录音工作。 -
使用
PyAudio
对象打开音频流,循环读取音频数据并存储到self.frames
列表中。 -
读取直到
self.recording
变为False,然后停止并关闭音频流。
8. 保存录音文件
def save_audio(self):
try:
filename = 'medium/user.wav'
wf = wave.open(filename, 'wb')
wf.setnchannels(self.CHANNELS)
wf.setsampwidth(self.audio.get_sample_size(self.FORMAT))
wf.setframerate(self.RATE)
with self.frames_lock:
wf.writeframes(b''.join(self.frames))
wf.close()
print(f"录音文件已保存为 {filename}")
return True
except Exception as e:
print(f"Error saving audio file: {e}")
return False
-
save_audio
方法将录音数据保存为WAV文件。 -
使用
wave
库创建WAV文件,并设置通道数、采样宽度和帧率。 -
将音频数据写入文件,并在成功时返回True,失败时返回False。
9. 语音识别
def speech_recognition(self):
voice = BaiduVoice()
recognition_result = voice.recognize_speech('medium/user.wav')
print("已识别的文本:", recognition_result)
if recognition_result:
self.coze_api(recognition_result)
else:
print("识别失败")
-
speech_recognition
方法使用BaiduVoice
类进行语音识别。 -
识别成功后,调用
coze_api
方法处理识别结果。
10. 语音合成
def speech_synthesis(self, kword):
voice = BaiduVoice()
voice.synthesize_text(kword, 'medium/bot.mp3')
print("已合成的语音文本:", kword)
pygame.init()
pygame.mixer.music.load('medium/bot.mp3')
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
pygame.quit()
-
speech_synthesis
方法使用BaiduVoice
类将文本转换为语音并播放。 -
使用
pygame
库加载和播放合成的语音文件。
11. 处理用户输入和显示聊天内容
def on_send_button_clicked(self):
user_input = self.textEdit.toPlainText()
if not user_input:
print("输入框不能为空")
return
self.textEdit.clear()
response = self.coze_bot_dialogue(user_input)
self.display_chat(user_input, response)
def coze_bot_dialogue(self, message):
return chat(message)
-
on_send_button_clicked
方法处理发送按钮的点击事件,获取用户输入并调用coze_bot_dialogue
方法。 -
coze_bot_dialogue
方法调用chat
函数与聊天机器人进行交互。
总结
这段代码实现了一个完整的AI聊天机器人,包括录音、语音识别、语音合成和聊天功能。它使用了多线程、音频处理和GUI交互,是一个综合性的Python项目。