From 154d07b8626a16f461a0567841c4c9738b1f2684 Mon Sep 17 00:00:00 2001 From: will wade Date: Fri, 25 Oct 2024 12:52:25 +0100 Subject: [PATCH 1/7] Remove FFMPEG, rework onSynth in espeak to finish correctly - #334 #324 - Replace #345 --- README.md | 6 +- README.rst | 6 +- docs/install.rst | 1 - example/main.py | 37 ++++--- pyttsx3/drivers/espeak.py | 202 ++++++++++++++++++++++---------------- requirements.txt | 2 +- setup.py | 62 +++++++----- 7 files changed, 185 insertions(+), 131 deletions(-) diff --git a/README.md b/README.md index dabf772..5dbb2c1 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,10 @@ + If you are on a linux system and if the voice output is not working , then : - Install espeak , ffmpeg and libespeak1 as shown below: + Install espeak and libespeak1 as shown below: ``` - sudo apt update && sudo apt install espeak ffmpeg libespeak1 + sudo apt update && sudo apt install espeak libespeak1 ``` ## Usage : @@ -90,7 +90,7 @@ engine.stop() """Saving Voice to a file""" -# On linux make sure that 'espeak' and 'ffmpeg' are installed +# On linux make sure that 'espeak' is installed engine.save_to_file('Hello World', 'test.mp3') engine.runAndWait() diff --git a/README.rst b/README.rst index d38da06..0a7f47b 100644 --- a/README.rst +++ b/README.rst @@ -19,11 +19,11 @@ Installation + If you are on a linux system and if the voice output is not working , then : -Install espeak , ffmpeg and libespeak1 as shown below: +Install espeak and libespeak1 as shown below: :: - sudo apt update && sudo apt install espeak ffmpeg libespeak1 + sudo apt update && sudo apt install espeak libespeak1 Usage : @@ -65,7 +65,7 @@ Usage : engine.stop() """Saving Voice to a file""" - # On linux make sure that 'espeak' and 'ffmpeg' are installed + # On linux make sure that 'espeak' are installed engine.save_to_file('Hello World', 'test.mp3') engine.runAndWait() diff --git a/docs/install.rst b/docs/install.rst index 26e5187..c4290b4 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -90,4 +90,3 @@ code-block:: bash .. _espeak: http://espeak.sourceforge.net/ .. _virtualenv: https://pypi.python.org/pypi/virtualenv/1.10.1 .. _pip: https://pypi.python.org/pypi/pip -.. _ffmpeg: https://www.ffmpeg.org/ diff --git a/example/main.py b/example/main.py index b7329bb..2a5fafe 100644 --- a/example/main.py +++ b/example/main.py @@ -1,34 +1,39 @@ import pyttsx3 -engine = pyttsx3.init() # object creation + +engine = pyttsx3.init() # object creation """ RATE""" -rate = engine.getProperty('rate') # getting details of current speaking rate -print(rate) #printing current voice rate -engine.setProperty('rate', 125) # setting up new voice rate +rate = engine.getProperty("rate") # getting details of current speaking rate +print(rate) # printing current voice rate +engine.setProperty("rate", 125) # setting up new voice rate """VOLUME""" -volume = engine.getProperty('volume') #getting to know current volume level (min=0 and max=1) -print(volume) #printing current volume level -engine.setProperty('volume',1.0) # setting up volume level between 0 and 1 +volume = engine.getProperty( + "volume" +) # getting to know current volume level (min=0 and max=1) +print(volume) # printing current volume level +engine.setProperty("volume", 1.0) # setting up volume level between 0 and 1 """VOICE""" -voices = engine.getProperty('voices') #getting details of current voice -#engine.setProperty('voice', voices[0].id) #changing index, changes voices. 0 for male -engine.setProperty('voice', voices[1].id) #changing index, changes voices. 1 for female +voices = engine.getProperty("voices") # getting details of current voice +# engine.setProperty('voice', voices[0].id) #changing index, changes voices. 0 for male +engine.setProperty( + "voice", voices[1].id +) # changing index, changes voices. 1 for female """PITCH""" -pitch = engine.getProperty('pitch') #Get current pitch value -print(pitch) #Print current pitch value -engine.setProperty('pitch', 75) #Set the pitch (default 50) to 75 out of 100 +pitch = engine.getProperty("pitch") # Get current pitch value +print(pitch) # Print current pitch value +engine.setProperty("pitch", 75) # Set the pitch (default 50) to 75 out of 100 engine.say("Hello World!") -engine.say('My current speaking rate is ' + str(rate)) +engine.say("My current speaking rate is " + str(rate)) engine.runAndWait() engine.stop() """Saving Voice to a file""" -# On linux make sure that 'espeak' and 'ffmpeg' are installed -engine.save_to_file('Hello World', 'test.mp3') +# On linux make sure that 'espeak' is installed +engine.save_to_file("Hello World", "test.mp3") engine.runAndWait() diff --git a/pyttsx3/drivers/espeak.py b/pyttsx3/drivers/espeak.py index ad961dd..256479c 100644 --- a/pyttsx3/drivers/espeak.py +++ b/pyttsx3/drivers/espeak.py @@ -5,7 +5,8 @@ import time import subprocess from tempfile import NamedTemporaryFile -if platform.system() == 'Windows': + +if platform.system() == "Windows": import winsound from ..voice import Voice @@ -20,30 +21,31 @@ def buildDriver(proxy): # noinspection PyPep8Naming class EspeakDriver(object): _moduleInitialized = False - _defaultVoice = '' + _defaultVoice = "" def __init__(self, proxy): if not EspeakDriver._moduleInitialized: # espeak cannot initialize more than once per process and has # issues when terminating from python (assert error on close) - # so just keep it alive and init once + # so just keep it alive and init once rate = _espeak.Initialize(_espeak.AUDIO_OUTPUT_RETRIEVAL, 1000) if rate == -1: - raise RuntimeError('could not initialize espeak') - EspeakDriver._defaultVoice = 'default' + raise RuntimeError("could not initialize espeak") + EspeakDriver._defaultVoice = "default" EspeakDriver._moduleInitialized = True self._proxy = proxy self._looping = False self._stopping = False self._speaking = False self._text_to_say = None - self._data_buffer = b'' + self._data_buffer = b"" self._numerise_buffer = [] + self._save_file = None _espeak.SetSynthCallback(self._onSynth) - self.setProperty('voice', EspeakDriver._defaultVoice) - self.setProperty('rate', 200) - self.setProperty('volume', 1.0) + self.setProperty("voice", EspeakDriver._defaultVoice) + self.setProperty("rate", 200) + self.setProperty("volume", 1.0) def numerise(self, data): self._numerise_buffer.append(data) @@ -63,37 +65,42 @@ def stop(self): @staticmethod def getProperty(name: str): - if name == 'voices': + if name == "voices": voices = [] for v in _espeak.ListVoices(None): - kwargs = {'id': fromUtf8(v.name), 'name': fromUtf8(v.name)} + print(v) + if v.gender == 0: + print("found one") + kwargs = {"id": fromUtf8(v.name), "name": fromUtf8(v.name)} if v.languages: try: language_code_bytes = v.languages[1:] - language_code = language_code_bytes.decode('utf-8', errors='ignore') - kwargs['languages'] = [language_code] + language_code = language_code_bytes.decode( + "utf-8", errors="ignore" + ) + kwargs["languages"] = [language_code] except UnicodeDecodeError as e: - kwargs['languages'] = ["Unknown"] - genders = [None, 'male', 'female'] - kwargs['gender'] = genders[v.gender] - kwargs['age'] = v.age or None + kwargs["languages"] = ["Unknown"] + genders = [None, "male", "female"] + kwargs["gender"] = genders[v.gender] + kwargs["age"] = v.age or None voices.append(Voice(**kwargs)) return voices - elif name == 'voice': + elif name == "voice": voice = _espeak.GetCurrentVoice() return fromUtf8(voice.contents.name) - elif name == 'rate': + elif name == "rate": return _espeak.GetParameter(_espeak.RATE) - elif name == 'volume': + elif name == "volume": return _espeak.GetParameter(_espeak.VOLUME) / 100.0 - elif name == 'pitch': + elif name == "pitch": return _espeak.GetParameter(_espeak.PITCH) else: - raise KeyError('unknown property %s' % name) + raise KeyError("unknown property %s" % name) @staticmethod def setProperty(name: str, value): - if name == 'voice': + if name == "voice": if value is None: return try: @@ -101,110 +108,139 @@ def setProperty(name: str, value): _espeak.SetVoiceByName(utf8Value) except ctypes.ArgumentError as e: raise ValueError(str(e)) - elif name == 'rate': + elif name == "rate": try: _espeak.SetParameter(_espeak.RATE, value, 0) except ctypes.ArgumentError as e: raise ValueError(str(e)) - elif name == 'volume': + elif name == "volume": try: - _espeak.SetParameter( - _espeak.VOLUME, int(round(value * 100, 2)), 0) + _espeak.SetParameter(_espeak.VOLUME, int(round(value * 100, 2)), 0) except TypeError as e: raise ValueError(str(e)) - elif name == 'pitch': + elif name == "pitch": try: - _espeak.SetParameter( - _espeak.PITCH, int(value), 0 - ) + _espeak.SetParameter(_espeak.PITCH, int(value), 0) except TypeError as e: raise ValueError(str(e)) else: - raise KeyError('unknown property %s' % name) + raise KeyError("unknown property %s" % name) def save_to_file(self, text, filename): + """ + Save the synthesized speech to the specified filename. + """ + self._save_file = filename + self._text_to_say = text code = self.numerise(filename) - _espeak.Synth(toUtf8(text), flags=_espeak.ENDPAUSE | _espeak.CHARS_UTF8, user_data=code) + _espeak.Synth( + toUtf8(text), flags=_espeak.ENDPAUSE | _espeak.CHARS_UTF8, user_data=code + ) def _start_synthesis(self, text): self._proxy.setBusy(True) - self._proxy.notify('started-utterance') + self._proxy.notify("started-utterance") self._speaking = True - self._data_buffer = b'' # Ensure buffer is cleared before starting + self._data_buffer = b"" # Ensure buffer is cleared before starting try: _espeak.Synth(toUtf8(text), flags=_espeak.ENDPAUSE | _espeak.CHARS_UTF8) except Exception as e: self._proxy.setBusy(False) - self._proxy.notify('error', exception=e) + self._proxy.notify("error", exception=e) raise - def _onSynth(self, wav, numsamples, events): + if not self._speaking: + return 0 + i = 0 while True: event = events[i] if event.type == _espeak.EVENT_LIST_TERMINATED: break if event.type == _espeak.EVENT_WORD: - if self._text_to_say: - start_index = event.text_position-1 + start_index = event.text_position - 1 end_index = start_index + event.length word = self._text_to_say[start_index:end_index] else: word = "Unknown" - - self._proxy.notify('started-word', name=word, location=event.text_position, length=event.length) + self._proxy.notify( + "started-word", + name=word, + location=event.text_position, + length=event.length, + ) elif event.type == _espeak.EVENT_END: - stream = NamedTemporaryFile(delete=False, suffix='.wav') - - try: - with wave.open(stream, 'wb') as f: - f.setnchannels(1) - f.setsampwidth(2) - f.setframerate(22050.0) - f.writeframes(self._data_buffer) - self._data_buffer = b'' - - if event.user_data: - os.system(f'ffmpeg -y -i {stream.name} {self.decode_numeric(event.user_data)} -loglevel quiet') - else: - if platform.system() == 'Darwin': # macOS - try: - result = subprocess.run(['afplay', stream.name], check=True, capture_output=True, text=True) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"[EspeakDriver._onSynth] Mac afplay failed with error: {e}") - elif platform.system() == 'Linux': - os.system(f'aplay {stream.name} -q') - elif platform.system() == 'Windows': - winsound.PlaySound(stream.name, winsound.SND_FILENAME) # Blocking playback - - except Exception as e: - raise RuntimeError(f"Error during playback: {e}") - - finally: + if numsamples > 0: + self._data_buffer += ctypes.string_at( + wav, numsamples * ctypes.sizeof(ctypes.c_short) + ) + self._speaking = False + + if self._save_file: try: - stream.close() # Ensure the file is closed - os.remove(stream.name) + with wave.open(self._save_file, "wb") as f: + f.setnchannels(1) # Mono + f.setsampwidth(2) # 16-bit samples + f.setframerate(22050) # 22,050 Hz sample rate + f.writeframes(self._data_buffer) + print(f"Audio saved to {self._save_file}") except Exception as e: - raise RuntimeError(f"Error deleting temporary WAV file: {e}") - - self._proxy.notify('finished-utterance', completed=True) + raise RuntimeError(f"Error saving WAV file: {e}") + else: + try: + with NamedTemporaryFile( + suffix=".wav", delete=False + ) as temp_wav: + with wave.open(temp_wav, "wb") as f: + f.setnchannels(1) # Mono + f.setsampwidth(2) # 16-bit samples + f.setframerate(22050) # 22,050 Hz sample rate + f.writeframes(self._data_buffer) + + temp_wav_name = temp_wav.name + temp_wav.flush() + + # Playback functionality (for say method) + if platform.system() == "Darwin": # macOS + result = subprocess.run( + ["afplay", temp_wav_name], check=True + ) + print(f"afplay result: {result}") + + elif platform.system() == "Linux": + os.system(f"aplay {temp_wav_name} -q") + + elif platform.system() == "Windows": + winsound.PlaySound(temp_wav_name, winsound.SND_FILENAME) + + # Remove the file after playback + os.remove(temp_wav_name) + + except Exception as e: + print(f"Playback error: {e}") + + self._data_buffer = b"" + self._speaking = False # Prevent double processing + self._proxy.notify("finished-utterance", completed=True) self._proxy.setBusy(False) - self.endLoop() # End the loop here - break # Exit the loop after handling the termination event - + self.endLoop() + break + i += 1 - + if numsamples > 0: - self._data_buffer += ctypes.string_at(wav, numsamples * ctypes.sizeof(ctypes.c_short)) + self._data_buffer += ctypes.string_at( + wav, numsamples * ctypes.sizeof(ctypes.c_short) + ) + return 0 - def endLoop(self): self._looping = False - + def startLoop(self): first = True self._looping = True @@ -218,16 +254,16 @@ def startLoop(self): self._start_synthesis(self._text_to_say) self.iterate() time.sleep(0.01) - + def iterate(self): if not self._looping: return if self._stopping: _espeak.Cancel() self._stopping = False - self._proxy.notify('finished-utterance', completed=False) + self._proxy.notify("finished-utterance", completed=False) self._proxy.setBusy(False) self.endLoop() def say(self, text): - self._text_to_say = text \ No newline at end of file + self._text_to_say = text diff --git a/requirements.txt b/requirements.txt index aedc347..76a7260 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # pyttsx3 only requires `espeak` driver/library which is system-dependent ### Ubuntu -#$ sudo apt install espeak ffmpeg +#$ sudo apt install espeak ### Mac OS X (os.platform == 'Darwin') # pyobjc>=2.4 diff --git a/setup.py b/setup.py index 601ac64..59b3332 100644 --- a/setup.py +++ b/setup.py @@ -2,43 +2,57 @@ from setuptools import setup -# Ubuntu: sudo apt install espeak ffmpeg +# Ubuntu: sudo apt install espeak install_requires = [ 'comtypes; platform_system == "Windows"', 'pypiwin32; platform_system == "Windows"', 'pywin32; platform_system == "Windows"', - 'pyobjc>=2.4; platform_system == "Darwin"' + 'pyobjc>=2.4; platform_system == "Darwin"', ] -with open('README.rst', 'r') as f: +with open("README.rst", "r") as f: long_description = f.read() setup( - name='pyttsx3', - packages=['pyttsx3', 'pyttsx3.drivers'], - version='2.98', - description='Text to Speech (TTS) library for Python 3. Works without internet connection or delay. Supports multiple TTS engines, including Sapi5, nsss, and espeak.', + name="pyttsx3", + packages=["pyttsx3", "pyttsx3.drivers"], + version="2.98", + description="Text to Speech (TTS) library for Python 3. Works without internet connection or delay. Supports multiple TTS engines, including Sapi5, nsss, and espeak.", long_description=long_description, - summary='Offline Text to Speech library with multi-engine support', - author='Natesh M Bhat', - url='https://github.com/nateshmbhat/pyttsx3', - author_email='nateshmbhatofficial@gmail.com', + summary="Offline Text to Speech library with multi-engine support", + author="Natesh M Bhat", + url="https://github.com/nateshmbhat/pyttsx3", + author_email="nateshmbhatofficial@gmail.com", install_requires=install_requires, - keywords=['pyttsx', 'ivona', 'pyttsx for python3', 'TTS for python3', 'pyttsx3', 'text to speech for python', 'tts', 'text to speech', 'speech', 'speech synthesis', 'offline text to speech', 'offline tts', 'gtts'], + keywords=[ + "pyttsx", + "ivona", + "pyttsx for python3", + "TTS for python3", + "pyttsx3", + "text to speech for python", + "tts", + "text to speech", + "speech", + "speech synthesis", + "offline text to speech", + "offline tts", + "gtts", + ], classifiers=[ - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'Intended Audience :: System Administrators', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7' + "Intended Audience :: End Users/Desktop", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "Intended Audience :: System Administrators", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", ], ) From b54924a2dc3946aa6ccd42994d4d71b895c6135a Mon Sep 17 00:00:00 2001 From: will wade Date: Fri, 25 Oct 2024 23:03:33 +0100 Subject: [PATCH 2/7] fixing commas and puctuation breaking reading --- pyttsx3/drivers/espeak.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyttsx3/drivers/espeak.py b/pyttsx3/drivers/espeak.py index 256479c..5700284 100644 --- a/pyttsx3/drivers/espeak.py +++ b/pyttsx3/drivers/espeak.py @@ -28,7 +28,7 @@ def __init__(self, proxy): # espeak cannot initialize more than once per process and has # issues when terminating from python (assert error on close) # so just keep it alive and init once - rate = _espeak.Initialize(_espeak.AUDIO_OUTPUT_RETRIEVAL, 1000) + rate = _espeak.Initialize(_espeak.AUDIO_OUTPUT_SYNCH_PLAYBACK, 1000) if rate == -1: raise RuntimeError("could not initialize espeak") EspeakDriver._defaultVoice = "default" @@ -134,7 +134,7 @@ def save_to_file(self, text, filename): self._text_to_say = text code = self.numerise(filename) _espeak.Synth( - toUtf8(text), flags=_espeak.ENDPAUSE | _espeak.CHARS_UTF8, user_data=code + toUtf8(text), flags=_espeak.ENDPAUSE | _espeak.CHARS_AUTO, user_data=code ) def _start_synthesis(self, text): From bcc58abcd5996cfce9a0381bee12d65795f49918 Mon Sep 17 00:00:00 2001 From: will wade Date: Sat, 26 Oct 2024 17:16:24 +0100 Subject: [PATCH 3/7] think this fixes the not speaking after commas. been "fun" this. Never again --- pyttsx3/drivers/espeak.py | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/pyttsx3/drivers/espeak.py b/pyttsx3/drivers/espeak.py index 5700284..d02b711 100644 --- a/pyttsx3/drivers/espeak.py +++ b/pyttsx3/drivers/espeak.py @@ -28,7 +28,7 @@ def __init__(self, proxy): # espeak cannot initialize more than once per process and has # issues when terminating from python (assert error on close) # so just keep it alive and init once - rate = _espeak.Initialize(_espeak.AUDIO_OUTPUT_SYNCH_PLAYBACK, 1000) + rate = _espeak.Initialize(_espeak.AUDIO_OUTPUT_RETRIEVAL, 1000) if rate == -1: raise RuntimeError("could not initialize espeak") EspeakDriver._defaultVoice = "default" @@ -132,10 +132,6 @@ def save_to_file(self, text, filename): """ self._save_file = filename self._text_to_say = text - code = self.numerise(filename) - _espeak.Synth( - toUtf8(text), flags=_espeak.ENDPAUSE | _espeak.CHARS_AUTO, user_data=code - ) def _start_synthesis(self, text): self._proxy.setBusy(True) @@ -153,12 +149,13 @@ def _onSynth(self, wav, numsamples, events): if not self._speaking: return 0 + # Process each event in the current callback i = 0 while True: event = events[i] if event.type == _espeak.EVENT_LIST_TERMINATED: break - if event.type == _espeak.EVENT_WORD: + elif event.type == _espeak.EVENT_WORD: if self._text_to_say: start_index = event.text_position - 1 end_index = start_index + event.length @@ -172,13 +169,8 @@ def _onSynth(self, wav, numsamples, events): length=event.length, ) - elif event.type == _espeak.EVENT_END: - if numsamples > 0: - self._data_buffer += ctypes.string_at( - wav, numsamples * ctypes.sizeof(ctypes.c_short) - ) - self._speaking = False - + elif event.type == _espeak.EVENT_MSG_TERMINATED: + # Final event indicating synthesis completion if self._save_file: try: with wave.open(self._save_file, "wb") as f: @@ -205,25 +197,20 @@ def _onSynth(self, wav, numsamples, events): # Playback functionality (for say method) if platform.system() == "Darwin": # macOS - result = subprocess.run( - ["afplay", temp_wav_name], check=True - ) - print(f"afplay result: {result}") - + subprocess.run(["afplay", temp_wav_name], check=True) elif platform.system() == "Linux": os.system(f"aplay {temp_wav_name} -q") - elif platform.system() == "Windows": winsound.PlaySound(temp_wav_name, winsound.SND_FILENAME) # Remove the file after playback os.remove(temp_wav_name) - except Exception as e: print(f"Playback error: {e}") + # Clear the buffer and mark as finished self._data_buffer = b"" - self._speaking = False # Prevent double processing + self._speaking = False self._proxy.notify("finished-utterance", completed=True) self._proxy.setBusy(False) self.endLoop() @@ -231,6 +218,7 @@ def _onSynth(self, wav, numsamples, events): i += 1 + # Accumulate audio data if available if numsamples > 0: self._data_buffer += ctypes.string_at( wav, numsamples * ctypes.sizeof(ctypes.c_short) From 44d239c905d9e836faa982087948284cf06379f9 Mon Sep 17 00:00:00 2001 From: will wade Date: Sun, 27 Oct 2024 22:44:31 +0000 Subject: [PATCH 4/7] updates to fix six deprecation --- pyttsx3/drivers/espeak.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyttsx3/drivers/espeak.py b/pyttsx3/drivers/espeak.py index d02b711..5784d3e 100644 --- a/pyttsx3/drivers/espeak.py +++ b/pyttsx3/drivers/espeak.py @@ -10,7 +10,7 @@ import winsound from ..voice import Voice -from . import _espeak, fromUtf8, toUtf8 +from . import _espeak # noinspection PyPep8Naming @@ -70,8 +70,7 @@ def getProperty(name: str): for v in _espeak.ListVoices(None): print(v) if v.gender == 0: - print("found one") - kwargs = {"id": fromUtf8(v.name), "name": fromUtf8(v.name)} + kwargs = {"id": v.name.decode('utf-8'), "name": v.name.decode('utf-8')} if v.languages: try: language_code_bytes = v.languages[1:] @@ -88,7 +87,7 @@ def getProperty(name: str): return voices elif name == "voice": voice = _espeak.GetCurrentVoice() - return fromUtf8(voice.contents.name) + return voice.contents.name.decode('utf-8') elif name == "rate": return _espeak.GetParameter(_espeak.RATE) elif name == "volume": From d07a52f9592de7353c512f0dcaa1eb954acf6122 Mon Sep 17 00:00:00 2001 From: will wade Date: Mon, 28 Oct 2024 00:13:01 +0000 Subject: [PATCH 5/7] switch to espeak-ng and remove ffmpeg may break things lets see --- .github/workflows/python_publish.yml | 2 +- README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python_publish.yml b/.github/workflows/python_publish.yml index 41a0231..1132cd4 100644 --- a/.github/workflows/python_publish.yml +++ b/.github/workflows/python_publish.yml @@ -24,7 +24,7 @@ jobs: - if: runner.os == 'Linux' run: | sudo apt-get update -q -q - sudo apt-get install --yes espeak espeak-ng ffmpeg libespeak1 + sudo apt-get install --yes espeak-ng libespeak1 espeak --version espeak-ng --version ffmpeg --version || true diff --git a/README.rst b/README.rst index 0a7f47b..0d7aa2f 100644 --- a/README.rst +++ b/README.rst @@ -23,7 +23,7 @@ Install espeak and libespeak1 as shown below: :: - sudo apt update && sudo apt install espeak libespeak1 + sudo apt update && sudo apt install espeak-ng libespeak1 Usage : From 655d24c81a9bc7588179f83861af3c24e57532c7 Mon Sep 17 00:00:00 2001 From: will wade Date: Mon, 28 Oct 2024 00:15:08 +0000 Subject: [PATCH 6/7] looks like we need both espeak and espeak-ng for test --- .github/workflows/python_publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python_publish.yml b/.github/workflows/python_publish.yml index 1132cd4..96b1b8c 100644 --- a/.github/workflows/python_publish.yml +++ b/.github/workflows/python_publish.yml @@ -24,7 +24,7 @@ jobs: - if: runner.os == 'Linux' run: | sudo apt-get update -q -q - sudo apt-get install --yes espeak-ng libespeak1 + sudo apt-get install --yes espeak espeak-ng libespeak1 espeak --version espeak-ng --version ffmpeg --version || true From 151d2923cdc54d9f079e3d3959e6e0b44e4d0428 Mon Sep 17 00:00:00 2001 From: will wade Date: Mon, 28 Oct 2024 00:16:08 +0000 Subject: [PATCH 7/7] revert. took 2seconds to read actual file.. --- .github/workflows/python_publish.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/python_publish.yml b/.github/workflows/python_publish.yml index 96b1b8c..0889baa 100644 --- a/.github/workflows/python_publish.yml +++ b/.github/workflows/python_publish.yml @@ -24,10 +24,8 @@ jobs: - if: runner.os == 'Linux' run: | sudo apt-get update -q -q - sudo apt-get install --yes espeak espeak-ng libespeak1 - espeak --version + sudo apt-get install --yes espeak-ng libespeak1 espeak-ng --version - ffmpeg --version || true - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5