From b1caf631a0d14dbf89975e349ece39ef4c9bcd2e Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 12:02:47 +0100 Subject: [PATCH 1/7] fix for bug in stop method --- RealtimeTTS/engines/coqui_engine.py | 14 ++++++++------ RealtimeTTS/stream_player.py | 2 ++ RealtimeTTS/text_to_stream.py | 27 ++++++++++++++++++++++----- requirements.txt | 3 ++- setup.py | 2 +- 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/RealtimeTTS/engines/coqui_engine.py b/RealtimeTTS/engines/coqui_engine.py index 3a762f4..346e3e6 100644 --- a/RealtimeTTS/engines/coqui_engine.py +++ b/RealtimeTTS/engines/coqui_engine.py @@ -277,7 +277,7 @@ def postprocess_wave(chunk): if command == 'shutdown': logging.info('Shutdown command received. Exiting worker process.') - conn.send({'status': 'shutdown'}) + conn.send(('shutdown', 'shutdown')) break # This exits the loop, effectively stopping the worker process. elif command == 'synthesize': @@ -333,7 +333,7 @@ def postprocess_wave(chunk): except KeyboardInterrupt: logging.info('Keyboard interrupt received. Exiting worker process.') - conn.send({'shutdown': 'shutdown'}) + conn.send(('shutdown', 'shutdown')) except Exception as e: logging.error(f"General synthesis error: {e} occured trying to synthesize text {text}") @@ -447,6 +447,9 @@ def synthesize(self, while not 'finished' in status: if 'shutdown' in status or 'error' in status: + if 'error' in status: + logging.error(f'Error synthesizing text: {text}') + logging.error(f'Error: {result}') return False self.queue.put(result) status, result = self.parent_synthesize_pipe.recv() @@ -550,8 +553,8 @@ def shutdown(self): # Wait for the worker process to acknowledge the shutdown try: - response = self.parent_synthesize_pipe.recv() - if response.get('status') == 'shutdown': + status, _ = self.parent_synthesize_pipe.recv() + if 'shutdown' in status: logging.info('Worker process acknowledged shutdown') except EOFError: # Pipe was closed, meaning the process is already down @@ -566,5 +569,4 @@ def shutdown(self): # Wait for the process to terminate self.synthesize_process.join() - logging.info('Worker process has been terminated') - + logging.info('Worker process has been terminated') \ No newline at end of file diff --git a/RealtimeTTS/stream_player.py b/RealtimeTTS/stream_player.py index fb77ec9..c54bdd9 100644 --- a/RealtimeTTS/stream_player.py +++ b/RealtimeTTS/stream_player.py @@ -228,6 +228,8 @@ def stop(self, immediate: bool = False): if immediate: self.immediate_stop.set() + while self.playback_active: + time.sleep(0.1) return self.playback_active = False diff --git a/RealtimeTTS/text_to_stream.py b/RealtimeTTS/text_to_stream.py index 3619e18..b388c3f 100644 --- a/RealtimeTTS/text_to_stream.py +++ b/RealtimeTTS/text_to_stream.py @@ -50,6 +50,7 @@ def __init__(self, self.output_wavfile = None self.chunk_callback = None self.wf = None + self.abort_events = [] self._create_iterators() @@ -132,8 +133,10 @@ def play_async(self, Async handling of text to audio synthesis, see play() method. """ self.stream_running = True - self.play_thread = threading.Thread(target=self.play, args=(fast_sentence_fragment, buffer_threshold_seconds, minimum_sentence_length, minimum_first_fragment_length, log_synthesized_text, reset_generated_text, output_wavfile, on_sentence_synthesized, on_audio_chunk, tokenizer, language, context_size)) - self.play_thread.start() + + play_thread = threading.Thread(target=self.play, args=(fast_sentence_fragment, buffer_threshold_seconds, minimum_sentence_length, minimum_first_fragment_length, log_synthesized_text, reset_generated_text, output_wavfile, on_sentence_synthesized, on_audio_chunk, tokenizer, language, context_size)) + play_thread.daemon = True + play_thread.start() def _on_audio_chunk(self, chunk): format, _, _ = self.engine.get_stream_info() @@ -193,6 +196,8 @@ def play(self, # Set the stream_running flag to indicate the stream is active self.stream_running = True + abort_event = threading.Event() + self.abort_events.append(abort_event) self.output_wavfile = output_wavfile self.chunk_callback = on_audio_chunk @@ -251,7 +256,7 @@ def play(self, sentence_queue = queue.Queue() def synthesize_worker(): - while True: + while not abort_event.is_set(): sentence = sentence_queue.get() if sentence is None: # Sentinel value to stop the worker break @@ -262,6 +267,8 @@ def synthesize_worker(): while not synthesis_successful: try: + if abort_event.is_set(): + break success = self.engine.synthesize(sentence) if success: if on_sentence_synthesized: @@ -295,6 +302,8 @@ def synthesize_worker(): # Iterate through the synthesized chunks and feed them to the engine for audio synthesis for sentence in chunk_generator: + if abort_event.is_set(): + break sentence = sentence.strip() sentence_queue.put(sentence) if not self.stream_running: @@ -302,9 +311,13 @@ def synthesize_worker(): # Signal to the worker to stop sentence_queue.put(None) - worker_thread.join() + worker_thread.join() + + except Exception as e: + logging.warning(f"error in play() with engine {self.engine.engine_name}: {e}") finally: + self.abort_events.remove(abort_event) self.player.stop() if self.stream_running and len(self.char_iter.items) > 0 and self.char_iter.iterated_text == "": @@ -354,6 +367,10 @@ def stop(self): """ Stops the playback of the synthesized audio stream immediately. """ + + for abort_event in self.abort_events: + abort_event.set() + if self.is_playing(): self.char_iter.stop() if self.engine.can_consume_generators: @@ -362,7 +379,7 @@ def stop(self): else: self.player.stop(immediate=True) self.stream_running = False - + self._create_iterators() def text(self): """ diff --git a/requirements.txt b/requirements.txt index 9fac729..12dc8cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ pyttsx3==2.90 stream2sentence==0.2.0 azure-cognitiveservices-speech==1.33.0 elevenlabs==0.2.26 -TTS==0.21.1 \ No newline at end of file +TTS==0.21.1 +tqdm==4.66.1 \ No newline at end of file diff --git a/setup.py b/setup.py index fff1b02..6b6fd97 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setuptools.setup( name="RealTimeTTS", - version="0.3.0 ", + version="0.3.1", author="Kolja Beigel", author_email="kolja.beigel@web.de", description="*Stream text into audio with an easy-to-use, highly configurable library delivering voice output with minimal latency.", From 46fe08bc81f326a29b069dca5ec6a1c6bb45f269 Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 13:31:06 +0100 Subject: [PATCH 2/7] readme --- README.md | 208 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 121 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 9c73a0b..52c756f 100644 --- a/README.md +++ b/README.md @@ -52,13 +52,26 @@ This library uses: ## Installation +Simple installation: + ```bash pip install RealtimeTTS ``` -This will install all the necessary dependencies, including a **CPU support only** version of PyTorch (needed for Coqui engine) +This will install all the necessary dependencies, including a **CPU support only** version of PyTorch (needed for Coqui engine) + +Installation into virtual environment with GPU support: -To use Coqui engine it is recommended to upgrade torch to GPU usage (see installation steps under [Coqui Engine](#coquiengine) further below). +```bash +python -m venv env_realtimetts +env_realtimetts\Scripts\activate.bat +python.exe -m pip install --upgrade pip +pip install RealtimeTTS +pip install torch==2.1.1+cu118 torchaudio==2.1.1+cu118 --index-url https://download.pytorch.org/whl/cu118 +``` + +Also see [CUDA installation](#cuda_installation) further below +Also see [CUDA installation](#cuda-installation) further below ## Engine Requirements @@ -96,72 +109,7 @@ Downloads a neural TTS model first. In most cases it be fast enought for Realtim - to clone a voice submit the filename of a wave file containing the source voice as cloning_reference_wav to the CoquiEngine constructor - in my experience voice cloning works best with a 24000 Hz mono 16bit WAV file containing a short (~10 sec) sample -#### GPU-Support (CUDA) for Coqui - -Additional steps are needed for a **GPU-optimized** installation. These steps are recommended for those who require **better performance** and have a compatible NVIDIA GPU. - -> **Note**: *To check if your NVIDIA GPU supports CUDA, visit the [official CUDA GPUs list](https://developer.nvidia.com/cuda-gpus).* - -To use local Coqui Engine with GPU support via CUDA please follow these steps: - -1. **Install NVIDIA CUDA Toolkit 11.8**: - - Visit [NVIDIA CUDA Toolkit Archive](https://developer.nvidia.com/cuda-11-8-0-download-archive). - - Select version 11. - - Download and install the software. - -2. **Install NVIDIA cuDNN 8.7.0 for CUDA 11.x**: - - Visit [NVIDIA cuDNN Archive](https://developer.nvidia.com/rdp/cudnn-archive). - - Click on "Download cuDNN v8.7.0 (November 28th, 2022), for CUDA 11.x". - - Download and install the software. - -3. **Install ffmpeg**: - - You can download an installer for your OS from the [ffmpeg Website](https://ffmpeg.org/download.html). - - Or use a package manager: - - - **On Ubuntu or Debian**: - ```bash - sudo apt update && sudo apt install ffmpeg - ``` - - - **On Arch Linux**: - ```bash - sudo pacman -S ffmpeg - ``` - - - **On MacOS using Homebrew** ([https://brew.sh/](https://brew.sh/)): - ```bash - brew install ffmpeg - ``` - - - **On Windows using Chocolatey** ([https://chocolatey.org/](https://chocolatey.org/)): - ```bash - choco install ffmpeg - ``` - - - **On Windows using Scoop** ([https://scoop.sh/](https://scoop.sh/)): - ```bash - scoop install ffmpeg - ``` - -4. **Install PyTorch with CUDA support**: - ```bash - pip install torch==2.1.0+cu118 torchaudio==2.1.0+cu118 --index-url https://download.pytorch.org/whl/cu118 - ``` - -5. **Fix for to resolve compatility issues**: - If you run into library compatility issues, please set these libraries to fixed versions: - - ```bash - pip install networkx==2.8.8 - pip install typing_extensions==4.8.0 - pip install fsspec==2023.6.0 - pip install imageio==2.31.6 - pip install networkx==2.8.8 - pip install numpy==1.24.3 - pip install requests==2.31.0 - ``` +On most systems GPU support will be needed to run fast enough for realtime, otherwise you will experience stuttering. ## Quick Start @@ -388,29 +336,115 @@ These methods are responsible for executing the text-to-audio synthesis and play By understanding and setting these parameters and methods appropriately, you can tailor the `TextToAudioStream` to meet the specific needs of your application. + +### CUDA installation + +These steps are recommended for those who require **better performance** and have a compatible NVIDIA GPU. + +> **Note**: *To check if your NVIDIA GPU supports CUDA, visit the [official CUDA GPUs list](https://developer.nvidia.com/cuda-gpus).* + +To use torch with support via CUDA please follow these steps: + +> **Note**: *newer pytorch installations [may](https://stackoverflow.com/a/77069523)(unverified) not need Toolkit (and possibly cuDNN) installation anymore.* + +1. **Install NVIDIA CUDA Toolkit**: + For example, to install Toolkit 11.8 please + - Visit [NVIDIA CUDA Toolkit Archive](https://developer.nvidia.com/cuda-11-8-0-download-archive). + - Select version 11. + - Download and install the software. + +2. **Install NVIDIA cuDNN**: + For example, to install cuDNN 8.7.0 for CUDA 11.x please + - Visit [NVIDIA cuDNN Archive](https://developer.nvidia.com/rdp/cudnn-archive). + - Click on "Download cuDNN v8.7.0 (November 28th, 2022), for CUDA 11.x". + - Download and install the software. + +3. **Install ffmpeg**: + + You can download an installer for your OS from the [ffmpeg Website](https://ffmpeg.org/download.html). + + Or use a package manager: + + - **On Ubuntu or Debian**: + ```bash + sudo apt update && sudo apt install ffmpeg + ``` + + - **On Arch Linux**: + ```bash + sudo pacman -S ffmpeg + ``` + + - **On MacOS using Homebrew** ([https://brew.sh/](https://brew.sh/)): + ```bash + brew install ffmpeg + ``` + + - **On Windows using Chocolatey** ([https://chocolatey.org/](https://chocolatey.org/)): + ```bash + choco install ffmpeg + ``` + + - **On Windows using Scoop** ([https://scoop.sh/](https://scoop.sh/)): + ```bash + scoop install ffmpeg + ``` + +4. **Install PyTorch with CUDA support**: + ```bash + pip install torch==2.1.1+cu118 torchaudio==2.1.1+cu118 --index-url https://download.pytorch.org/whl/cu118 + ``` + +5. **Fix for to resolve compatility issues**: + If you run into library compatility issues, try setting these libraries to fixed versions: + + ```bash + pip install networkx==2.8.8 + pip install typing_extensions==4.8.0 + pip install fsspec==2023.6.0 + pip install imageio==2.31.6 + pip install networkx==2.8.8 + pip install numpy==1.24.3 + pip install requests==2.31.0 + ``` + +## 💖 Acknowledgements + +Huge shoutout to: +- The team behind [coqui](ttps://coqui.ai/) being the first giving us local high quality inference fast enough for realtime, even with a clonable voice + ## Contribution Contributions are always welcome (e.g. PR to add a new engine). -## License - -❗ -While the source of this library is under MIT, some libraries it depends on are not. -A lot of external engine providers currently DO NOT ALLOW commercial use together with their free plans. -Please read and respect the licenses of the different engine providers. - -[CoquiEngine](https://coqui.ai/cpml) -- non-commercial for free plan, commercial paid plans available - -[ElevenlabsEngine](https://help.elevenlabs.io/hc/en-us/articles/13313564601361-Can-I-publish-the-content-I-generate-on-the-platform-) -- non-commercial for free plan, commercial for every paid plan - -[AzureEngine](https://learn.microsoft.com/en-us/answers/questions/1192398/can-i-use-azure-text-to-speech-for-commercial-usag) -- non-commercial for free tier, commercial for standard tier upwards - -SystemEngine: -- GNU Lesser General Public License (LGPL) version 3.0 -- commercial use allowed +## License Information + +### ❗ Important Note: +While the source of this library is under the MIT License, many of the engines it depends on are not. External engine providers often restrict commercial use in their free plans. This means the engines can be used for noncommercial projects, but commercial usage requires a paid plan. + +### Engine Licenses Summary: + +#### CoquiEngine +- **License**: Open-source only for noncommercial projects. +- **Commercial Use**: Requires a paid plan. +- **Details**: [CoquiEngine License](https://coqui.ai/cpml) + +#### ElevenlabsEngine +- **License**: Open-source only for noncommercial projects. +- **Commercial Use**: Available with every paid plan. +- **Details**: [ElevenlabsEngine License](https://help.elevenlabs.io/hc/en-us/articles/13313564601361-Can-I-publish-the-content-I-generate-on-the-platform-) + +#### AzureEngine +- **License**: Open-source only for noncommercial projects. +- **Commercial Use**: Available from the standard tier upwards. +- **Details**: [AzureEngine License](https://learn.microsoft.com/en-us/answers/questions/1192398/can-i-use-azure-text-to-speech-for-commercial-usag) + +#### SystemEngine +- **License**: Mozilla Public License 2.0 and GNU Lesser General Public License (LGPL) version 3.0. +- **Commercial Use**: Allowed under this license. +- **Details**: [SystemEngine License](https://github.com/nateshmbhat/pyttsx3/blob/master/LICENSE) + +**Disclaimer**: This is a summarization of the licenses as understood at the time of writing. It is not legal advice. Please read and respect the licenses of the different engine providers yourself if you plan to use them in a project. ## Author From 6c37c959ef87f4200f6b98d1349fe023f7acadb0 Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 13:31:26 +0100 Subject: [PATCH 3/7] readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 52c756f..c7b0618 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,6 @@ pip install RealtimeTTS pip install torch==2.1.1+cu118 torchaudio==2.1.1+cu118 --index-url https://download.pytorch.org/whl/cu118 ``` -Also see [CUDA installation](#cuda_installation) further below Also see [CUDA installation](#cuda-installation) further below ## Engine Requirements From f4630ab3904ab58964b91f9079828f1620b1188c Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 13:32:42 +0100 Subject: [PATCH 4/7] readme --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c7b0618..301328a 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ RealtimeTTS is a state-of-the-art text-to-speech (TTS) library designed for real https://github.com/KoljaB/RealtimeTTS/assets/7604638/87dcd9a5-3a4e-4f57-be45-837fc63237e7 - -### Key Features +## Key Features - **Low Latency** - almost instantaneous text-to-speech conversion @@ -24,7 +23,7 @@ https://github.com/KoljaB/RealtimeTTS/assets/7604638/87dcd9a5-3a4e-4f57-be45-837 > **Hint**: *Check out [RealtimeSTT](https://github.com/KoljaB/RealtimeSTT), the input counterpart of this library, for speech-to-text capabilities. Together, they form a powerful realtime audio wrapper around large language models.* -### Updates +## Updates Latest Version: v0.3.0 From bafd67c9304e19459c4e8280bec09f84190f36aa Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 13:34:14 +0100 Subject: [PATCH 5/7] readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 301328a..e90675b 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,12 @@ https://github.com/KoljaB/RealtimeTTS/assets/7604638/87dcd9a5-3a4e-4f57-be45-837 ## Updates -Latest Version: v0.3.0 +Latest Version: v0.3.1 #### New Features: -1. Expanded language support, including Chinese (details in [tests](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/chinese_test.py) and [speed test](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/pyqt6_speed_test_chinese.py)). -2. Fallback engines in TextToAudioStream, enhancing reliability for real-time scenarios by switching to alternate engines if one fails. -3. Audio file saving feature with `output_wavfile` parameter. This allows for the simultaneous saving of real-time synthesized audio, enabling later playback of the live synthesis. +- Expanded language support, including Chinese (details in [tests](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/chinese_test.py) and [speed test](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/pyqt6_speed_test_chinese.py)). +- Fallback engines in TextToAudioStream, enhancing reliability for real-time scenarios by switching to alternate engines if one fails. +- Audio file saving feature with `output_wavfile` parameter. This allows for the simultaneous saving of real-time synthesized audio, enabling later playback of the live synthesis. For more details, see the [release history](https://github.com/KoljaB/RealtimeTTS/releases). From b27239419edab91b74c6f0547722a524e1a165ce Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 13:37:16 +0100 Subject: [PATCH 6/7] readme --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e90675b..e9d4bb5 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,16 @@ https://github.com/KoljaB/RealtimeTTS/assets/7604638/87dcd9a5-3a4e-4f57-be45-837 - ensures continuous operation with a fallback mechanism - switches to alternative engines in case of disruptions guaranteeing consistent performance and reliability, which is vital for critical and professional use cases -> **Hint**: *Check out [RealtimeSTT](https://github.com/KoljaB/RealtimeSTT), the input counterpart of this library, for speech-to-text capabilities. Together, they form a powerful realtime audio wrapper around large language models.* +> **Hint**: *check out [RealtimeSTT](https://github.com/KoljaB/RealtimeSTT), the input counterpart of this library, for speech-to-text capabilities. Together, they form a powerful realtime audio wrapper around large language models.* ## Updates Latest Version: v0.3.1 #### New Features: -- Expanded language support, including Chinese (details in [tests](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/chinese_test.py) and [speed test](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/pyqt6_speed_test_chinese.py)). -- Fallback engines in TextToAudioStream, enhancing reliability for real-time scenarios by switching to alternate engines if one fails. -- Audio file saving feature with `output_wavfile` parameter. This allows for the simultaneous saving of real-time synthesized audio, enabling later playback of the live synthesis. +- expanded language support, including Chinese (details in [tests](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/chinese_test.py) and [speed test](https://github.com/KoljaB/RealtimeTTS/blob/master/tests/pyqt6_speed_test_chinese.py)). +- fallback engines in TextToAudioStream, enhancing reliability for real-time scenarios by switching to alternate engines if one fails. +- audio file saving feature with `output_wavfile` parameter. This allows for the simultaneous saving of real-time synthesized audio, enabling later playback of the live synthesis. For more details, see the [release history](https://github.com/KoljaB/RealtimeTTS/releases). @@ -69,7 +69,7 @@ pip install RealtimeTTS pip install torch==2.1.1+cu118 torchaudio==2.1.1+cu118 --index-url https://download.pytorch.org/whl/cu118 ``` -Also see [CUDA installation](#cuda-installation) further below +More information about [CUDA installation](#cuda-installation). ## Engine Requirements @@ -339,11 +339,11 @@ By understanding and setting these parameters and methods appropriately, you can These steps are recommended for those who require **better performance** and have a compatible NVIDIA GPU. -> **Note**: *To check if your NVIDIA GPU supports CUDA, visit the [official CUDA GPUs list](https://developer.nvidia.com/cuda-gpus).* +> **Note**: *to check if your NVIDIA GPU supports CUDA, visit the [official CUDA GPUs list](https://developer.nvidia.com/cuda-gpus).* To use torch with support via CUDA please follow these steps: -> **Note**: *newer pytorch installations [may](https://stackoverflow.com/a/77069523)(unverified) not need Toolkit (and possibly cuDNN) installation anymore.* +> **Note**: *newer pytorch installations [may](https://stackoverflow.com/a/77069523) (unverified) not need Toolkit (and possibly cuDNN) installation anymore.* 1. **Install NVIDIA CUDA Toolkit**: For example, to install Toolkit 11.8 please @@ -409,7 +409,7 @@ To use torch with support via CUDA please follow these steps: ## 💖 Acknowledgements Huge shoutout to: -- The team behind [coqui](ttps://coqui.ai/) being the first giving us local high quality inference fast enough for realtime, even with a clonable voice +- The team behind [coqui](https://coqui.ai/) being the first giving us local high quality inference fast enough for realtime, even with a clonable voice ## Contribution From 556cff3c60778cc0aaff868b2f97852cb26b2d7b Mon Sep 17 00:00:00 2001 From: Kolja Beigel Date: Thu, 30 Nov 2023 13:38:09 +0100 Subject: [PATCH 7/7] readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index e9d4bb5..9d68e06 100644 --- a/README.md +++ b/README.md @@ -408,8 +408,7 @@ To use torch with support via CUDA please follow these steps: ## 💖 Acknowledgements -Huge shoutout to: -- The team behind [coqui](https://coqui.ai/) being the first giving us local high quality inference fast enough for realtime, even with a clonable voice +Huge shoutout to the team behind [Coqui AI](https://coqui.ai/) being the first giving us local high quality synthesis with realtime speed and even a clonable voice! ## Contribution