Skip to content

Commit

Permalink
fastapi client bugfix for static noise and load balancing for coqui e…
Browse files Browse the repository at this point in the history
…ngine
  • Loading branch information
KoljaB committed Nov 7, 2024
1 parent 8b1bc6d commit 54d1e1e
Show file tree
Hide file tree
Showing 4 changed files with 360 additions and 73 deletions.
174 changes: 174 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,175 @@
.gitignore
_open_cmd.bat
docs/
examples/
batch/
test_env/
tests_private/
docs/
docs_private/
env_realtimetts/
example_rvc/assets/
server/
RealtimeTTS.code-workspace

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
myenv/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
48 changes: 38 additions & 10 deletions RealtimeTTS/engines/coqui_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ def __init__(
sentence_silence_duration=0.6,
default_silence_duration=0.3,
print_realtime_factor=False,
load_balancing=False,
load_balancing_buffer_length=0,
load_balancing_cut_off=0,
):
"""
Initializes a coqui voice realtime text to speech engine object.
Expand Down Expand Up @@ -140,6 +143,16 @@ def __init__(
Duration of the silence after a comma.
sentence_silence_duration (float):
Duration of the silence after a sentence.
default_silence_duration (float):
Default duration of the silence.
print_realtime_factor (bool):
Print the realtime factor for the coqui model.
load_balancing (bool):
Enable load balancing for the coqui model.
load_balancing_buffer_length (int):
Buffer length for the load balancing.
load_balancing_cut_off (int):
Cut off for the load balancing.
"""

self._synthesize_lock = Lock()
Expand All @@ -164,6 +177,9 @@ def __init__(
self.sentence_silence_duration = sentence_silence_duration
self.default_silence_duration = default_silence_duration
self.print_realtime_factor = print_realtime_factor
self.load_balancing = load_balancing
self.load_balancing_buffer_length = load_balancing_buffer_length
self.load_balancing_cut_off = load_balancing_cut_off

self.cloning_reference_wav = voice
self.speed = speed
Expand Down Expand Up @@ -261,6 +277,9 @@ def output_worker(queue):
self.sentence_silence_duration,
self.default_silence_duration,
self.print_realtime_factor,
self.load_balancing,
self.load_balancing_buffer_length,
self.load_balancing_cut_off,
),
)
self.synthesize_process.start()
Expand Down Expand Up @@ -302,6 +321,9 @@ def _synthesize_worker(
sentence_silence_duration,
default_silence_duration,
print_realtime_factor,
load_balancing,
load_balancing_buffer_length,
load_balancing_cut_off,
):
"""
Worker process for the coqui text to speech synthesis model.
Expand Down Expand Up @@ -612,17 +634,8 @@ def get_user_data_dir(appname):
continue
else:
# Poll timed out, continue without blocking
time.sleep(0.01) # You can adjust this sleep to fit your needs
time.sleep(0.01)
continue
# try:
# message = conn.recv()
# except Exception as e:
# logging.error(
# f"conn.recv() error: {e} occured in "
# "synthesize worker thread of coqui engine."
# )
# time.sleep(1)
# continue

command = message["command"]
data = message["data"]
Expand Down Expand Up @@ -715,6 +728,18 @@ def get_user_data_dir(appname):
seconds_to_first_chunk = (
raw_inference_start - time_start
)
else:
chunk_production_seconds = time.time() - time_start
generated_audio_seconds = full_generated_seconds

# wait only if we are faster than realtime, meaning
# that chunk_production_seconds is smaller than generated_audio_seconds
if load_balancing:
if chunk_production_seconds < (generated_audio_seconds + load_balancing_buffer_length):
waiting_time = generated_audio_seconds - chunk_production_seconds - load_balancing_cut_off
if waiting_time > 0:
print(f"Waiting for {waiting_time} seconds")
time.sleep(waiting_time)

time_end = time.time()
seconds = time_end - time_start
Expand All @@ -732,6 +757,7 @@ def get_user_data_dir(appname):
print(f"Realtime Factor: {realtime_factor}")
print(f"Raw Inference Factor: {raw_inference_factor}")


# Send silent audio
sample_rate = config.audio.sample_rate

Expand All @@ -751,6 +777,8 @@ def get_user_data_dir(appname):

conn.send(("finished", ""))

end_time = time.time()

except KeyboardInterrupt:
logging.info("Keyboard interrupt received. " "Exiting worker process.")
conn.send(("shutdown", "shutdown"))
Expand Down
Loading

0 comments on commit 54d1e1e

Please sign in to comment.