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.
This commit is contained in:
tsukumi
2024-03-10 03:04:27 +00:00
parent a79b1910fb
commit b7d7c78203
4 changed files with 45 additions and 25 deletions

View File

@@ -151,7 +151,7 @@ def save_last_download(latest_release):
# pyopenjtalk_worker を起動 # pyopenjtalk_worker を起動
## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する ## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する
pyopenjtalk.initialize() pyopenjtalk.initialize_worker()
# pyopenjtalk の辞書を更新 # pyopenjtalk の辞書を更新
update_dict() update_dict()

View File

@@ -43,7 +43,7 @@ ln = config.server_config.language
# pyopenjtalk_worker を起動 # pyopenjtalk_worker を起動
## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する ## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する
pyopenjtalk.initialize() pyopenjtalk.initialize_worker()
# 事前に BERT モデル/トークナイザーをロードしておく # 事前に BERT モデル/トークナイザーをロードしておく
## ここでロードしなくても必要になった際に自動ロードされるが、時間がかかるため事前にロードしておいた方が体験が良い ## ここでロードしなくても必要になった際に自動ロードされるが、時間がかかるため事前にロードしておいた方が体験が良い

View File

@@ -18,38 +18,58 @@ WORKER_CLIENT: Optional[WorkerClient] = None
def run_frontend(text: str) -> list[dict[str, Any]]: def run_frontend(text: str) -> list[dict[str, Any]]:
assert WORKER_CLIENT if WORKER_CLIENT is not None:
ret = WORKER_CLIENT.dispatch_pyopenjtalk("run_frontend", text) ret = WORKER_CLIENT.dispatch_pyopenjtalk("run_frontend", text)
assert isinstance(ret, list) assert isinstance(ret, list)
return ret return ret
else:
# without worker
import pyopenjtalk
return pyopenjtalk.run_frontend(text)
def make_label(njd_features: Any) -> list[str]: def make_label(njd_features: Any) -> list[str]:
assert WORKER_CLIENT if WORKER_CLIENT is not None:
ret = WORKER_CLIENT.dispatch_pyopenjtalk("make_label", njd_features) ret = WORKER_CLIENT.dispatch_pyopenjtalk("make_label", njd_features)
assert isinstance(ret, list) assert isinstance(ret, list)
return ret 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): def mecab_dict_index(path: str, out_path: str, dn_mecab: Optional[str] = None) -> None:
assert WORKER_CLIENT if WORKER_CLIENT is not None:
WORKER_CLIENT.dispatch_pyopenjtalk("mecab_dict_index", path, out_path, dn_mecab) 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): def update_global_jtalk_with_user_dict(path: str) -> None:
assert WORKER_CLIENT if WORKER_CLIENT is not None:
WORKER_CLIENT.dispatch_pyopenjtalk("update_global_jtalk_with_user_dict", path) 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(): def unset_user_dict() -> None:
assert WORKER_CLIENT if WORKER_CLIENT is not None:
WORKER_CLIENT.dispatch_pyopenjtalk("unset_user_dict") WORKER_CLIENT.dispatch_pyopenjtalk("unset_user_dict")
else:
# without worker
import pyopenjtalk
pyopenjtalk.unset_user_dict()
# initialize module when imported # initialize module when imported
def initialize(port: int = WORKER_PORT) -> None: def initialize_worker(port: int = WORKER_PORT) -> None:
import atexit import atexit
import signal import signal
import socket import socket
@@ -99,11 +119,11 @@ def initialize(port: int = WORKER_PORT) -> None:
logger.debug("pyopenjtalk worker server started") logger.debug("pyopenjtalk worker server started")
WORKER_CLIENT = client WORKER_CLIENT = client
atexit.register(terminate) atexit.register(terminate_worker)
# when the process is killed # when the process is killed
def signal_handler(signum: int, frame: Any): def signal_handler(signum: int, frame: Any):
terminate() terminate_worker()
try: try:
signal.signal(signal.SIGTERM, signal_handler) signal.signal(signal.SIGTERM, signal_handler)
@@ -113,13 +133,13 @@ def initialize(port: int = WORKER_PORT) -> None:
# top-level declaration # top-level declaration
def terminate() -> None: def terminate_worker() -> None:
logger.debug("pyopenjtalk worker server terminated") logger.debug("pyopenjtalk worker server terminated")
global WORKER_CLIENT global WORKER_CLIENT
if not WORKER_CLIENT: if not WORKER_CLIENT:
return return
# repare for unexpected errors # prepare for unexpected errors
try: try:
if WORKER_CLIENT.status() == 1: if WORKER_CLIENT.status() == 1:
WORKER_CLIENT.quit_server() WORKER_CLIENT.quit_server()

View File

@@ -28,7 +28,7 @@ from style_bert_vits2.tts_model import ModelHolder
# pyopenjtalk_worker を起動 # pyopenjtalk_worker を起動
## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する ## pyopenjtalk_worker は TCP ソケットサーバーのため、ここで起動する
pyopenjtalk.initialize() pyopenjtalk.initialize_worker()
# 事前に BERT モデル/トークナイザーをロードしておく # 事前に BERT モデル/トークナイザーをロードしておく
## ここでロードしなくても必要になった際に自動ロードされるが、時間がかかるため事前にロードしておいた方が体験が良い ## ここでロードしなくても必要になった際に自動ロードされるが、時間がかかるため事前にロードしておいた方が体験が良い