import threading import time import winsound import pyttsx3 try: pyttsx3.speak("..") except: pass def beep(duration=700, freq=640): winsound.Beep(freq, duration) class SpeakServer: thread = None # background thread that reads frames from camera engine = None __flag = threading.Event() # 用于暂停线程的标识 __flag.clear() # 设置为True __running = threading.Event() # 用于停止线程的标识 __running.set() # 将running设置为True __had_data = threading.Event() __had_data.clear() speak_list = [] is_pause = True BASE_SPEED = 200 MAX_SPEED = 320 speed_set = BASE_SPEED speed_now = BASE_SPEED def __new__(cls): if not cls.thread: # start background frame thread cls.thread = threading.Thread(target=cls._thread, daemon=True) cls.thread.start() return super().__new__(cls) def start(self): pass @staticmethod def add_speak(data): SpeakServer.speak_list.append(data) SpeakServer.__had_data.set() @classmethod def check_list(cls): if not cls.speak_list: return True else: return False @classmethod def wait_4_speak(cls): while not cls.check_list(): time.sleep(0.1) @staticmethod def speed_control(rate): while not SpeakServer.engine: time.sleep(0.5) try: SpeakServer.engine.setProperty('rate', rate) SpeakServer.speed_set = rate SpeakServer.speed_now = rate except: return @staticmethod def set_temp_speed(rate): while not SpeakServer.engine: time.sleep(0.5) try: SpeakServer.engine.setProperty('rate', rate) SpeakServer.speed_now = rate except: return @staticmethod def volume_control(volume): while not SpeakServer.engine: time.sleep(0.5) try: SpeakServer.engine.setProperty('volume', volume) except: return @staticmethod def save_to_file(text, output_path): while True: try: SpeakServer.engine = pyttsx3.init() break except: time.sleep(1) SpeakServer.engine.save_to_file(text, output_path) SpeakServer.engine.runAndWait() @classmethod def _thread(cls): while True: try: cls.engine = pyttsx3.init() break except: time.sleep(1) while SpeakServer.__running.is_set(): SpeakServer.__had_data.wait() while cls.speak_list: try: temp_speak = cls.speak_list[0] # 语速控制 if len(cls.speak_list) >= 2: speak_len = len("".join([str(s) for s in cls.speak_list])) if speak_len > 10: speak_speed = cls.BASE_SPEED + min(speak_len, 30) / 30 * (cls.MAX_SPEED - cls.BASE_SPEED) cls.set_temp_speed(speak_speed) else: if cls.speed_now != cls.speed_set: cls.speed_control(cls.speed_set) else: cls.speed_control(cls.speed_set) cls.engine.say("{}".format(temp_speak)) cls.engine.runAndWait() cls.speak_list.pop(0) except Exception as e: print('speak machine error:', e) time.sleep(0.1) SpeakServer.__had_data.clear() SpeakServer.thread = None @classmethod def wait(cls): cls.__flag.wait() @classmethod def pause(cls): if not cls.is_pause: cls.__flag.clear() # 设置为False, 让线程阻塞 cls.is_pause = True @classmethod def resume(cls): if cls.is_pause: cls.__flag.set() # 设置为True, 让线程停止阻塞 cls.is_pause = False @classmethod def stop(cls): return # cls.__flag.set() # 将线程从暂停状态恢复, 如何已经暂停的话 # cls.__running.clear() # 设置为False