From b7d7c7820364c7d17f8bedad04b8aa5441bec6ba Mon Sep 17 00:00:00 2001 From: tsukumi Date: Sun, 10 Mar 2024 03:04:27 +0000 Subject: [PATCH] Refactor: when pyopenjtalk_worker is called without initialization, continue processing without a worker When using style-bert-vits2 as a library, the requirement to be able to launch it in multiple processes may not be necessary. Also, if the library is embedded and exe-ed using PyInstaller or similar, it is difficult to make pyopenjtalk_worker run in a separate process. Therefore, we changed it so that the worker is used only when it is explicitly initialized. --- server_editor.py | 2 +- server_fastapi.py | 2 +- .../japanese/pyopenjtalk_worker/__init__.py | 64 ++++++++++++------- webui/inference.py | 2 +- 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/server_editor.py b/server_editor.py index b12f304..3c0d2c8 100644 --- a/server_editor.py +++ b/server_editor.py @@ -151,7 +151,7 @@ def save_last_download(latest_release): # pyopenjtalk_worker を起動 ## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する -pyopenjtalk.initialize() +pyopenjtalk.initialize_worker() # pyopenjtalk の辞書を更新 update_dict() diff --git a/server_fastapi.py b/server_fastapi.py index e8309da..30f253f 100644 --- a/server_fastapi.py +++ b/server_fastapi.py @@ -43,7 +43,7 @@ ln = config.server_config.language # pyopenjtalk_worker を起動 ## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する -pyopenjtalk.initialize() +pyopenjtalk.initialize_worker() # 事前に BERT モデル/トークナイザーをロードしておく ## ここでロードしなくても必要になった際に自動ロードされるが、時間がかかるため事前にロードしておいた方が体験が良い diff --git a/style_bert_vits2/nlp/japanese/pyopenjtalk_worker/__init__.py b/style_bert_vits2/nlp/japanese/pyopenjtalk_worker/__init__.py index 3593e60..212d21a 100644 --- a/style_bert_vits2/nlp/japanese/pyopenjtalk_worker/__init__.py +++ b/style_bert_vits2/nlp/japanese/pyopenjtalk_worker/__init__.py @@ -18,38 +18,58 @@ WORKER_CLIENT: Optional[WorkerClient] = None def run_frontend(text: str) -> list[dict[str, Any]]: - assert WORKER_CLIENT - ret = WORKER_CLIENT.dispatch_pyopenjtalk("run_frontend", text) - assert isinstance(ret, list) - return ret + if WORKER_CLIENT is not None: + ret = WORKER_CLIENT.dispatch_pyopenjtalk("run_frontend", text) + assert isinstance(ret, list) + return ret + else: + # without worker + import pyopenjtalk + return pyopenjtalk.run_frontend(text) def make_label(njd_features: Any) -> list[str]: - assert WORKER_CLIENT - ret = WORKER_CLIENT.dispatch_pyopenjtalk("make_label", njd_features) - assert isinstance(ret, list) - return ret + if WORKER_CLIENT is not None: + ret = WORKER_CLIENT.dispatch_pyopenjtalk("make_label", njd_features) + assert isinstance(ret, list) + return ret + else: + # without worker + import pyopenjtalk + return pyopenjtalk.make_label(njd_features) -def mecab_dict_index(path: str, out_path: str, dn_mecab: Optional[str] = None): - assert WORKER_CLIENT - WORKER_CLIENT.dispatch_pyopenjtalk("mecab_dict_index", path, out_path, dn_mecab) +def mecab_dict_index(path: str, out_path: str, dn_mecab: Optional[str] = None) -> None: + if WORKER_CLIENT is not None: + WORKER_CLIENT.dispatch_pyopenjtalk("mecab_dict_index", path, out_path, dn_mecab) + else: + # without worker + import pyopenjtalk + pyopenjtalk.mecab_dict_index(path, out_path, dn_mecab) -def update_global_jtalk_with_user_dict(path: str): - assert WORKER_CLIENT - WORKER_CLIENT.dispatch_pyopenjtalk("update_global_jtalk_with_user_dict", path) +def update_global_jtalk_with_user_dict(path: str) -> None: + if WORKER_CLIENT is not None: + WORKER_CLIENT.dispatch_pyopenjtalk("update_global_jtalk_with_user_dict", path) + else: + # without worker + import pyopenjtalk + pyopenjtalk.update_global_jtalk_with_user_dict(path) -def unset_user_dict(): - assert WORKER_CLIENT - WORKER_CLIENT.dispatch_pyopenjtalk("unset_user_dict") +def unset_user_dict() -> None: + if WORKER_CLIENT is not None: + WORKER_CLIENT.dispatch_pyopenjtalk("unset_user_dict") + else: + # without worker + import pyopenjtalk + pyopenjtalk.unset_user_dict() # initialize module when imported -def initialize(port: int = WORKER_PORT) -> None: +def initialize_worker(port: int = WORKER_PORT) -> None: import atexit import signal import socket @@ -99,11 +119,11 @@ def initialize(port: int = WORKER_PORT) -> None: logger.debug("pyopenjtalk worker server started") WORKER_CLIENT = client - atexit.register(terminate) + atexit.register(terminate_worker) # when the process is killed def signal_handler(signum: int, frame: Any): - terminate() + terminate_worker() try: signal.signal(signal.SIGTERM, signal_handler) @@ -113,13 +133,13 @@ def initialize(port: int = WORKER_PORT) -> None: # top-level declaration -def terminate() -> None: +def terminate_worker() -> None: logger.debug("pyopenjtalk worker server terminated") global WORKER_CLIENT if not WORKER_CLIENT: return - # repare for unexpected errors + # prepare for unexpected errors try: if WORKER_CLIENT.status() == 1: WORKER_CLIENT.quit_server() diff --git a/webui/inference.py b/webui/inference.py index 9c2bf63..6d6eae6 100644 --- a/webui/inference.py +++ b/webui/inference.py @@ -28,7 +28,7 @@ from style_bert_vits2.tts_model import ModelHolder # pyopenjtalk_worker を起動 ## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する -pyopenjtalk.initialize() +pyopenjtalk.initialize_worker() # 事前に BERT モデル/トークナイザーをロードしておく ## ここでロードしなくても必要になった際に自動ロードされるが、時間がかかるため事前にロードしておいた方が体験が良い