156 lines
4.3 KiB
Python
156 lines
4.3 KiB
Python
|
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
|