Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The script throws a "Class not registered" error when using PyInstaller (pyttsx3 + IVONA voices), although it works stably in PyCharm #403

Open
PokoLokoW opened this issue Apr 5, 2022 · 7 comments
Labels

Comments

@PokoLokoW
Copy link

PokoLokoW commented Apr 5, 2022

import pyttsx3
tts_engine = pyttsx3.init(debug=True)
tts_engine.setProperty("rate", 140)
tts_voices = tts_engine.getProperty('voices')
for voice in tts_voices:
    if voice.name == "IVONA 2 Tatyana OEM":
        tts_engine.setProperty('voice', voice.id)
        print("Голос озвучки установлен на: " + voice.name)

tts_engine.say("Test message 1")
tts_engine.runAndWait()

tts_engine.say("Test message 2")
tts_engine.runAndWait()

tts_engine.say("Test message 3")
tts_engine.runAndWait()

A simple script works well in pyCharm, but if compiled with the command (removing -F doesn't help)

pyinstaller -F main.py --icon=icon.ico --name FileName

then during the processing of "runAndWait ()" it first shows 3 identical system windows with the error "load lib failed", and after closing these windows it shows an error in the log:

Traceback (most recent call last):

    File "pyttsx3\driver.py", line 92, in _pump

    File "pyttsx3\drivers\sapi5.py", line 56, in say

_ctypes.COMError: (-2147221164, 'Class not registered', (None, None, None, 0, None))

At the same time, if you use the standard system voice, there is no problem.

  • pyinstaller: 4.10 (and latest development version)
  • Python: 3.10 (3.7)
  • Platform: Windows 10 Pro Rus
  • How you installed Python: python.org/downloads
  • I have no way to test the functionality on another platform
  • pyttsx3: 2.90 (2.71)

If the problem is not directly related to PyInstaller, then, if possible, please tell me at least what exactly could be the reason. I've been trying to figure out the problem for the third day and have not yet been able to find a solution.

@bwoodsend bwoodsend transferred this issue from pyinstaller/pyinstaller Apr 5, 2022
@bwoodsend
Copy link
Member

pyttsx3 has apparently been fixed before and I see they haven't released anything new since then. Either you just need to pip install -U pyinstaller-hooks-contrib or our test for pyttsx3 is woefully inadequate.

@PokoLokoW
Copy link
Author

I have the latest version of pyinstaller-hooks-contrib installed. And even uninstalling + reinstalling also did not help fix the situation.

This problem is reproduced on another computer that has Windows 10 installed. And, as I wrote earlier, it is associated with specific voice options. Can you at least suggest how you can determine what data the script lacks for normal operation? I would try to fix the problem myself, but I was never able to get a sufficiently informative log that would help me specify the problem.

@bwoodsend
Copy link
Member

Hmm, does --collect-submodules=pyttsx3 make any difference?

@rokm
Copy link
Member

rokm commented Apr 5, 2022

I doubt it does - the error message looks like a COM class is not registered, and that sapi5 driver/backend seems to do some runtime generation/compiling when imported. So it sounds like these are not set up correctly for whatever reason...

How does one install that "IVONA 2 Tatyana OEM" voice? Does it need to be installed externally on the system, outside the python/pyttsx3?

@PokoLokoW
Copy link
Author

No, --collect-submodules=pyttsx3 did not help

Yes, the voice is installed from outside. I took from the Internet and use this file
https://drive.google.com/file/d/1XTIkKdSO42bFOWcoL8K-PUiIzB3fA4N8/view?usp=sharing
After installing the voice, it offers to install MiniSpeech. It doesn't need to be installed.

@rokm
Copy link
Member

rokm commented Apr 5, 2022

There are DLLs in C:\Program Files (x86)\Speech2Go Voice Package\x64 that need to be discoverable. And since PyInstaller clears the search path, they are not found, resulting in those "load lib failed" messages.

One way to work around this is to collect those DLLs into frozen application, for example via --add-binary "C:\Program Files (x86)\Speech2Go Voice Package\x64\*.dll;.".

I'm not sure if that's enough to make a portable application, though; i.e., does the engine require other stuff from Speech2Go Voice Package? If the user needs to install it on their system anyway, there's not much point in bundling those DLLs. In that case, you can add the system-installed DLL directory to the DLL search path in your python code, before you import pyttsx3. For example:

import os
speech2go_libs_dir = r'C:\Program Files (x86)\Speech2Go Voice Package\x64'
if os.path.isdir(speech2go_libs_dir):
    print(f"Adding {speech2go_libs_dir} to DLL paths...")
    os.add_dll_directory(speech2go_libs_dir)
    if "PATH" in os.environ:
        os.environ["PATH"] = speech2go_libs_dir + os.pathsep + os.environ["PATH"]
    else:
        os.environ["PATH"] = speech2go_libs_dir

import pyttsx3
tts_engine = pyttsx3.init(debug=True)
# [...]

@PokoLokoW
Copy link
Author

Yes, it works. Thanks!

Is it possible to take this into account in PyInstaller so that in the future no one will have such problems? I mean clearing the search path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants