1

我正在创建一个可以说和听的语音助手(使用 Python)。当我添加口语功能时,我将其编程为在程序启动时打招呼。我正在对程序进行多线程处理,因为说话功能需要很长时间,它会挂起程序并且看起来它已经停止了。当我使用 python 的 pyttsx3 库对 speak 函数进行多线程处理时,出现了这个错误:“运行时错误:运行循环已经开始”。我的代码:

from threading import Thread
from tkinter import *

from ctypes import windll, byref, create_unicode_buffer, create_string_buffer

import pyttsx3
import datetime

FR_PRIVATE = 0x10
FR_NOT_ENUM = 0x20


def load_font(font_path, private=True, enumerable=True):
    path_buf = None
    add_font_resource_ex = None

    if isinstance(font_path, bytes):
        path_buf = create_string_buffer(font_path)
        add_font_resource_ex = windll.gdi32.AddFontResourceExA

    elif isinstance(font_path, str):
        path_buf = create_unicode_buffer(font_path)
        add_font_resource_ex = windll.gdi32.AddFontResourceExW

    flags = (FR_PRIVATE if private else 0) | (FR_NOT_ENUM if not enumerable else 0)
    num_fonts_added = add_font_resource_ex(byref(path_buf), flags, 0)

    return bool(num_fonts_added)


class MainWindow(Tk):
    def __init__(self):
        super().__init__()

        self.title("Voice Assistant")
        self.geometry("550x505")
        self.resizable(False, False)

        self.engine = pyttsx3.init()

        self.output_area = Text(self, bd=2, relief=SOLID, font=("Poppins", 16), width=40, height=12, state=DISABLED)
        self.output_area.place(x=10, y=10)

        self.command_en = Entry(self, font=("Poppins", 11), width=48)
        self.command_en.place(x=10, y=465)

        self.hear_btn = Button(self, text="Hear", font=("Arial", 10), width=9, height=1)
        self.hear_btn.place(x=455, y=465)

        self.wish_me()

        self.mainloop()

    def speak(self, audio):
        self.engine.say(audio)
        self.engine.runAndWait()

    def say(self, audio):
        speak_thread = Thread(target=self.speak, args=[audio])
        speak_thread.start()

    def wish_me(self):
        hour = int(datetime.datetime.now().hour)

        if 0 <= hour < 12:
            self.say("Good morning")
        elif 12 <= hour <= 18:
            self.say("Good afternoon")
        else:
            self.say("Good evening")

        self.say("I am Jarvis, How can I help you?")


if __name__ == "__main__":
    loaded = load_font("Poppins-Regular.otf")
    root = MainWindow()

错误:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Users\Manbir Singh Judge\Python 3.8.6\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\Manbir Singh Judge\Python 3.8.6\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:/Users/Manbir Singh Judge/PycharmProjects/Voice Assistant/main.py", line 56, in speak
    self.engine.runAndWait()
  File "C:\Users\Manbir Singh Judge\Python 3.8.6\lib\site-packages\pyttsx3\engine.py", line 177, in runAndWait
    raise RuntimeError('run loop already started')
RuntimeError: run loop already started

4

1 回答 1

0

我刚刚找到了这个解决方法,只需使用子进程库从主 python 调用另一个 python,它将在另一个文件的不同线程中运行

  1. 这是您的主文件:添加此代码

from subprocess import call
phrase = "Hi everyone"
call(["python3", "speak.py", phrase])

  1. 这是您speak.py调用它后将运行的文件
import sys
import pyttsx3

def init_engine():
    engine = pyttsx3.init()
    return engine

def say(s):
    engine.say(s)
    engine.runAndWait() # In here the program will wait as if is in main file

engine = init_engine()
say(str(sys.argv[1])) # Here it will get the text through sys from main file

就是这样,只需编辑此代码以满足您的要求。

于 2021-04-22T14:02:06.357 回答