197 lines
6.5 KiB
Python
197 lines
6.5 KiB
Python
|
import os
|
|||
|
import tkinter as tk
|
|||
|
from tkinter import messagebox, ttk
|
|||
|
import sqlite3
|
|||
|
import pygame
|
|||
|
import subprocess
|
|||
|
import pyaudio
|
|||
|
import sys
|
|||
|
import threading
|
|||
|
import queue
|
|||
|
import main
|
|||
|
import app
|
|||
|
# 在这里调用 main.py 中的函数或类
|
|||
|
|
|||
|
|
|||
|
def get_match_logs(db_name="conversation.db"):
|
|||
|
conn = sqlite3.connect(db_name)
|
|||
|
c = conn.cursor()
|
|||
|
c.execute("SELECT id, question, answer, audio_path FROM conversation")
|
|||
|
logs = c.fetchall()
|
|||
|
conn.close()
|
|||
|
return logs
|
|||
|
|
|||
|
def delete_log(log_id, audio_path, db_name="conversation.db"):
|
|||
|
conn = sqlite3.connect(db_name)
|
|||
|
c = conn.cursor()
|
|||
|
c.execute("DELETE FROM conversation WHERE id = ?", (log_id,))
|
|||
|
conn.commit()
|
|||
|
conn.close()
|
|||
|
|
|||
|
# 删除音频文件
|
|||
|
if audio_path and os.path.isfile(audio_path):
|
|||
|
os.remove(audio_path)
|
|||
|
|
|||
|
def clear_all_logs(db_name="conversation.db"):
|
|||
|
conn = sqlite3.connect(db_name)
|
|||
|
c = conn.cursor()
|
|||
|
c.execute("SELECT audio_path FROM conversation")
|
|||
|
audio_paths = c.fetchall()
|
|||
|
|
|||
|
# 删除所有记录
|
|||
|
c.execute("DELETE FROM conversation")
|
|||
|
conn.commit()
|
|||
|
conn.close()
|
|||
|
|
|||
|
# 删除所有音频文件
|
|||
|
for path in audio_paths:
|
|||
|
if path[0] and os.path.isfile(path[0]):
|
|||
|
os.remove(path[0])
|
|||
|
|
|||
|
class App:
|
|||
|
def __init__(self, root):
|
|||
|
self.root = root
|
|||
|
self.root.title("交流记录")
|
|||
|
|
|||
|
# 初始化pygame
|
|||
|
pygame.mixer.init()
|
|||
|
|
|||
|
# 创建表格
|
|||
|
self.tree = ttk.Treeview(root, columns=("Question", "Answer", "Audio Path"), show='headings')
|
|||
|
self.tree.heading("Question", text="问题")
|
|||
|
self.tree.heading("Answer", text="回答")
|
|||
|
self.tree.heading("Audio Path", text="音频路径")
|
|||
|
self.tree.pack(fill=tk.BOTH, expand=True)
|
|||
|
|
|||
|
# 添加滚动条
|
|||
|
scrollbar = ttk.Scrollbar(root, orient=tk.VERTICAL, command=self.tree.yview)
|
|||
|
self.tree.configure(yscroll=scrollbar.set)
|
|||
|
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
|||
|
|
|||
|
# 加载日志
|
|||
|
self.load_logs()
|
|||
|
|
|||
|
# 创建按钮容器
|
|||
|
button_frame = tk.Frame(root)
|
|||
|
button_frame.pack(pady=10)
|
|||
|
|
|||
|
# 删除按钮
|
|||
|
self.delete_button = tk.Button(button_frame, text="删除选中记录", command=self.delete_selected)
|
|||
|
self.delete_button.pack(side=tk.LEFT, padx=5)
|
|||
|
|
|||
|
# 播放按钮
|
|||
|
self.play_button = tk.Button(button_frame, text="播放音频", command=self.play_audio)
|
|||
|
self.play_button.pack(side=tk.LEFT, padx=5)
|
|||
|
|
|||
|
# 清除所有记录按钮
|
|||
|
self.clear_button = tk.Button(button_frame, text="清除所有记录", command=self.clear_all)
|
|||
|
self.clear_button.pack(side=tk.LEFT, padx=5)
|
|||
|
|
|||
|
# 刷新记录按钮
|
|||
|
self.refresh_button = tk.Button(button_frame, text="刷新记录", command=self.load_logs)
|
|||
|
self.refresh_button.pack(side=tk.LEFT, padx=5)
|
|||
|
|
|||
|
# 添加执行主程序的按钮
|
|||
|
self.start_button = tk.Button(root, text="开始录音和识别", command=self.start_main)
|
|||
|
self.start_button.pack(pady=20)
|
|||
|
|
|||
|
# 创建小屏幕区域
|
|||
|
full_width = self.root.winfo_width()
|
|||
|
self.small_frame = tk.Frame(root, width=full_width, height=200, bg="black")
|
|||
|
self.small_frame.pack(side=tk.RIGHT, padx=10, pady=10)
|
|||
|
|
|||
|
self.output_text = tk.Text(self.small_frame, bg="black", fg="white", wrap="word")
|
|||
|
self.output_text.pack(expand=True, fill=tk.BOTH)
|
|||
|
|
|||
|
self.process = None
|
|||
|
self.output_queue = queue.Queue() # 用于存放输出的队列
|
|||
|
|
|||
|
# 定时器检查队列中的输出
|
|||
|
self.root.after(100, self.check_queue)
|
|||
|
|
|||
|
def start_main(self):
|
|||
|
# 创建并启动线程
|
|||
|
thread = threading.Thread(target=self.run_main)
|
|||
|
thread.start()
|
|||
|
|
|||
|
def run_main(self):
|
|||
|
# 获取当前脚本的路径
|
|||
|
script_path = os.path.join(os.path.dirname(__file__), 'main.py')
|
|||
|
|
|||
|
# 调用 main.py,确保使用当前虚拟环境的 Python 解释器
|
|||
|
self.process = subprocess.Popen(
|
|||
|
[sys.executable, script_path],
|
|||
|
stdout=subprocess.PIPE,
|
|||
|
stderr=subprocess.PIPE,
|
|||
|
text=True,
|
|||
|
encoding='utf-8' # 设置编码为 utf-8
|
|||
|
)
|
|||
|
|
|||
|
self.read_output()
|
|||
|
|
|||
|
def read_output(self):
|
|||
|
if self.process:
|
|||
|
output = self.process.stdout.readline()
|
|||
|
if output:
|
|||
|
self.output_queue.put(output) # 将输出放入队列
|
|||
|
if self.process.poll() is None: # 进程仍在运行
|
|||
|
self.root.after(100, self.read_output)
|
|||
|
|
|||
|
def check_queue(self):
|
|||
|
while not self.output_queue.empty():
|
|||
|
output = self.output_queue.get()
|
|||
|
self.output_text.insert(tk.END, output)
|
|||
|
self.output_text.see(tk.END) # 自动滚动到最新输出
|
|||
|
self.root.after(100, self.check_queue) # 定时检查队列
|
|||
|
|
|||
|
def load_logs(self):
|
|||
|
for row in self.tree.get_children():
|
|||
|
self.tree.delete(row)
|
|||
|
logs = get_match_logs()
|
|||
|
for log in logs:
|
|||
|
self.tree.insert("", tk.END, values=(log[1], log[2], log[3]))
|
|||
|
|
|||
|
def delete_selected(self):
|
|||
|
selected_item = self.tree.selection()
|
|||
|
if selected_item:
|
|||
|
selected_index = self.tree.index(selected_item[0])
|
|||
|
log_id = get_match_logs()[selected_index][0]
|
|||
|
audio_path = get_match_logs()[selected_index][3]
|
|||
|
full_audio_path = os.path.join("static", audio_path)
|
|||
|
delete_log(log_id, full_audio_path)
|
|||
|
self.load_logs()
|
|||
|
else:
|
|||
|
messagebox.showwarning("警告", "请先选择要删除的记录。")
|
|||
|
|
|||
|
def play_audio(self):
|
|||
|
selected_item = self.tree.selection()
|
|||
|
if selected_item:
|
|||
|
selected_index = self.tree.index(selected_item[0])
|
|||
|
audio_path = get_match_logs()[selected_index][3]
|
|||
|
|
|||
|
# 拼接静态文件夹路径
|
|||
|
full_audio_path = os.path.join("static", audio_path)
|
|||
|
|
|||
|
# 打印音频路径用于调试
|
|||
|
print("尝试加载音频文件:", full_audio_path)
|
|||
|
|
|||
|
# 检查文件是否存在
|
|||
|
if os.path.isfile(full_audio_path):
|
|||
|
pygame.mixer.music.load(full_audio_path)
|
|||
|
pygame.mixer.music.play()
|
|||
|
else:
|
|||
|
messagebox.showerror("错误", "音频文件不存在。")
|
|||
|
else:
|
|||
|
messagebox.showwarning("警告", "请先选择要播放的记录。")
|
|||
|
|
|||
|
def clear_all(self):
|
|||
|
confirm = messagebox.askyesno("确认", "您确定要清除所有记录吗?")
|
|||
|
if confirm:
|
|||
|
clear_all_logs()
|
|||
|
self.load_logs()
|
|||
|
|
|||
|
if __name__ == '__main__':
|
|||
|
root = tk.Tk()
|
|||
|
app = App(root)
|
|||
|
root.mainloop()
|