Akul-AI / rlvoice-1

An offline TTS engine for AkulAI and more.
Mozilla Public License 2.0
14 stars 3 forks source link

save_to_file still fails to work #7

Open qiulang opened 6 months ago

qiulang commented 6 months ago

Describe the bug I notice your project because of this issue https://github.com/nateshmbhat/pyttsx3/pull/271 (to fix save_to_file on macos) but I find it still fails to work on my mac (m2).

No output file.

engine = rlvoice.init()
engine.save_to_file('Hello World', 'test.mp3')
engine.runAndWait()

Desktop (please complete the following information):

my mac

Additional context BTW, the original pyttsx3 the voice.languages is en_US but you changed to en-US, ie change from underscore to dash, so maybe it worths to mention it in your readme

qiulang commented 6 months ago

OK I just found out that save_to_file can not save my words to mp3 file but wav, but why ?

engine = rlvoice.init()
engine.save_to_file('Hello World', 'test.wav') # can't save as mp3 but wav
engine.runAndWait()
Akul2010 commented 6 months ago

The ability to save to a specific file format like .wav or .mp3 depends on the capabilities of the underlying TTS engine and the libraries it uses for audio encoding.

In many cases, TTS engines rely on external libraries or utilities to handle audio encoding and saving. These libraries may support only a limited set of file formats. I think that NSSS (the default MacOS speech engine) doesn't support exporting to .mp3.

Saving to .wav format is often supported because it is a simple uncompressed audio format that is widely used and supported by many audio libraries. Saving to .mp3 may not be directly supported by some TTS engines due to licensing restrictions or because the necessary encoding libraries are not bundled with the engine.

Try using another engine, like CoquiTTS or Espeak.

qiulang commented 6 months ago

Hi thanks for the reply. I tried to install espeak on my mac and used it (engine = rlvoice.init('espeak')) but I failed.

Then I installed espeak-ng (after removing espeak) but the same error.

Traceback (most recent call last):
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/__init__.py", line 20, in init
    eng = _activeEngines[driverName]
          ~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/Users/langqiu/anaconda3/lib/python3.11/weakref.py", line 136, in __getitem__
    o = self.data[key]()
        ~~~~~~~~~^^^^^
KeyError: 'espeak'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/langqiu/Dev/conda-learn/./ttsxA.py", line 51, in <module>
    engine = rlvoice.init('espeak')
             ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/__init__.py", line 22, in init
    eng = Engine(driverName, debug)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/engine.py", line 30, in __init__
    self.proxy = driver.DriverProxy(weakref.proxy(self), driverName, debug)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/driver.py", line 49, in __init__
    self._module = importlib.import_module(name)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/langqiu/anaconda3/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/drivers/espeak.py", line 7, in <module>
    from . import _espeak, toUtf8, fromUtf8
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/drivers/_espeak.py", line 99, in <module>
    Initialize = cfunc('espeak_Initialize', dll, c_int,
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/langqiu/anaconda3/lib/python3.11/site-packages/rlvoice/drivers/_espeak.py", line 13, in cfunc
    return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute '_handle'

Do you know why ?

Akul2010 commented 5 months ago

Sorry for the late reply, I was sick and then had to catch up with work.

If you see in the _espeak.py file, it doesn't support loading espeak from MacOS, only Windows and Linux.

# Lines 17-59
def load_linux_ep():
   global dll
   try: dll = cdll.LoadLibrary('libespeak.so.1')
   except Exception as e: return False
   else: return True

def load_linux_epng():
   global dll
   try: dll = cdll.LoadLibrary('libespeak-ng.so.1')
   except Exception as e: return False
   else: return True

def load_linux_epng2():
   global dll
   try: dll = cdll.LoadLibrary('/usr/local/lib/libespeak-ng.so.1')
   except Exception as e: return False
   else: return True

def load_windows_epng1():
   global dll
   try: dll = cdll.LoadLibrary('libespeak-ng.dll')
   except Exception as e: return False
   else: return True

def load_windows_epng2():
   global dll
   try: dll = cdll.LoadLibrary('C:\\Program Files\\eSpeak NG\\libespeak-ng.dll')
   except Exception as e: return False
   else: return True

def load_windows_epng3():
   global dll
   try: dll = cdll.LoadLibrary('C:\\Program Files (x86)\\eSpeak NG\\libespeak-ng.dll')
   except Exception as e: return False
   else: return True

try:
   load_linux_ep() or load_linux_epng() or load_linux_epng2() or load_windows_epng1() or load_windows_epng2() or load_windows_epng3()
except Exception as exp:
    print("Exception: " + str(exp) + "\n")
    print("This means you probably do not have eSpeak or eSpeak-ng installed!")
    import sys
    sys.exit()

Implementing the same for MacOS shouldn't be too hard, just have to add the path file to espeak and then put it in the if condition. Do you think you can find the espeak file on your computer?

qiulang commented 5 months ago

Thanks for the reply. Actually I have tried https://github.com/sayak-brm/espeakng-python but I found the sound quality was so bad that I had given it up.

Akul2010 commented 5 months ago

Yes, please let me know the file path of espeak on the MacOS, and I will update the file. Or, if you would like to, you could update the code yourself and create a pull request.

Akul2010 commented 3 months ago

@qiulang If you would like to provide the path file to espeak on your MacOS computer, I could update the code to allow for MacOS to use espeak. I can't do it myself since I don't have a Mac nor do I have an active contributor with one.