From 0e1896f5c410947e8a686f545bec56d53042dd05 Mon Sep 17 00:00:00 2001 From: tarepan Date: Sat, 27 Apr 2024 08:54:36 +0000 Subject: [PATCH 01/12] =?UTF-8?q?refactor:=20=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E7=94=9F=E6=88=90=E6=89=8B=E9=A0=86=E3=82=92=E6=98=8E=E7=A2=BA?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/run.py b/run.py index 182e66061..292272bf6 100644 --- a/run.py +++ b/run.py @@ -756,23 +756,23 @@ def main() -> None: "VV_DISABLE_MUTABLE_API" ) - uvicorn.run( - generate_app( - tts_engines, - cores, - latest_core_version, - setting_loader, - preset_manager=preset_manager, - cancellable_engine=cancellable_engine, - root_dir=root_dir, - cors_policy_mode=cors_policy_mode, - allow_origin=allow_origin, - disable_mutable_api=disable_mutable_api, - ), - host=args.host, - port=args.port, + # ASGI に準拠したアプリケーションを生成する + app = generate_app( + tts_engines, + cores, + latest_core_version, + setting_loader, + preset_manager, + cancellable_engine, + root_dir, + cors_policy_mode, + allow_origin, + disable_mutable_api=disable_mutable_api, ) + # ASGI に準拠したサーバを立ち上げる + uvicorn.run(app, host=args.host, port=args.port) + if __name__ == "__main__": main() From 75ec436053aff6821b86f531baa0380691c49c18 Mon Sep 17 00:00:00 2001 From: tarepan Date: Sat, 27 Apr 2024 13:30:35 +0000 Subject: [PATCH 02/12] =?UTF-8?q?refactor:=20=E5=9E=8B=E8=A1=A8=E8=A8=98?= =?UTF-8?q?=E3=81=A8=E8=A8=AD=E5=AE=9A=E5=80=A4=E5=84=AA=E5=85=88=E5=BA=A6?= =?UTF-8?q?=E3=82=92=E5=8D=98=E7=B4=94=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 68 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/run.py b/run.py index 292272bf6..4bf91566f 100644 --- a/run.py +++ b/run.py @@ -11,7 +11,7 @@ from io import BytesIO, TextIOWrapper from pathlib import Path from tempfile import NamedTemporaryFile -from typing import Annotated, Any, Optional +from typing import Annotated, Any import soundfile import uvicorn @@ -116,11 +116,12 @@ def generate_app( setting_loader: SettingHandler, preset_manager: PresetManager, cancellable_engine: CancellableEngine | None = None, - root_dir: Optional[Path] = None, + root_dir: Path | None = None, cors_policy_mode: CorsPolicyMode = CorsPolicyMode.localapps, - allow_origin: Optional[list[str]] = None, + allow_origin: list[str] | None = None, disable_mutable_api: bool = False, ) -> FastAPI: + """ASGI に準拠した VOICEVOX ENGINE アプリケーションを生成する。""" if root_dir is None: root_dir = engine_root() @@ -227,14 +228,14 @@ async def block_origin_middleware( # loop = asyncio.get_event_loop() # _ = loop.create_task(cancellable_engine.catch_disconnection()) - def get_engine(core_version: Optional[str]) -> TTSEngine: + def get_engine(core_version: str | None) -> TTSEngine: if core_version is None: return tts_engines[latest_core_version] if core_version in tts_engines: return tts_engines[core_version] raise HTTPException(status_code=422, detail="不明なバージョンです") - def get_core(core_version: Optional[str]) -> CoreAdapter: + def get_core(core_version: str | None) -> CoreAdapter: """指定したバージョンのコアを取得する""" if core_version is None: return cores[latest_core_version] @@ -716,47 +717,38 @@ def main() -> None: enable_mock=enable_mock, ) - root_dir: Path | None = voicevox_dir - if root_dir is None: - root_dir = engine_root() + # ルートディレクトリのパス。優先度は「引数 > デフォルト」 + root_dir = voicevox_dir or engine_root() setting_loader = SettingHandler(args.setting_file) settings = setting_loader.load() - cors_policy_mode: CorsPolicyMode | None = args.cors_policy_mode - if cors_policy_mode is None: - cors_policy_mode = settings.cors_policy_mode + # CORSの許可モード。優先度は「引数 > 設定ファイル」 + cors_policy_mode = args.cors_policy_mode or settings.cors_policy_mode - allow_origin = None - if args.allow_origin is not None: - allow_origin = args.allow_origin - elif settings.allow_origin is not None: - allow_origin = settings.allow_origin.split(" ") + # 許可するオリジン。優先度は「引数 > 設定ファイル > デフォルト」 + setting_allow_origin = None + if settings.allow_origin: + setting_allow_origin = settings.allow_origin.split(" ") + allow_origin = args.allow_origin or setting_allow_origin or None - # Preset Manager - # preset_pathの優先順: 引数、環境変数、voicevox_dir、実行ファイルのディレクトリ + # プリセットマネージャー。設定ファイルパスの優先度は「引数 > 環境変数 > ルート」 # ファイルの存在に関わらず、優先順で最初に指定されたパスをプリセットファイルとして使用する - preset_path: Path | None = args.preset_file - if preset_path is None: - # 引数 --preset_file の指定がない場合 - env_preset_path = os.getenv("VV_PRESET_FILE") - if env_preset_path is not None and len(env_preset_path) != 0: - # 環境変数 VV_PRESET_FILE の指定がある場合 - preset_path = Path(env_preset_path) - else: - # 環境変数 VV_PRESET_FILE の指定がない場合 - preset_path = root_dir / "presets.yaml" - - preset_manager = PresetManager( - preset_path=preset_path, - ) - - disable_mutable_api: bool = args.disable_mutable_api | decide_boolean_from_env( - "VV_DISABLE_MUTABLE_API" - ) - - # ASGI に準拠したアプリケーションを生成する + env_preset_path_str = os.getenv("VV_PRESET_FILE") + if env_preset_path_str and len(env_preset_path_str) != 0: + env_preset_path = Path(env_preset_path_str) + else: + env_preset_path = None + root_preset_path = root_dir / "presets.yaml" + preset_path = args.preset_file or env_preset_path or root_preset_path + preset_manager = PresetManager(preset_path) + + # ミュータブル API の無効化。優先度は「引数 > 環境変数 > デフォルト(False)」 + env_disable_mutable_api = decide_boolean_from_env("VV_DISABLE_MUTABLE_API") + disable_mutable_api = args.disable_mutable_api or env_disable_mutable_api + + # ASGI に準拠した VOICEVOX ENGINE アプリケーションを生成する app = generate_app( tts_engines, cores, From 1056fb27f966da14b50cf61b929c5611e16ce0b8 Mon Sep 17 00:00:00 2001 From: tarepan Date: Sun, 28 Apr 2024 11:38:13 +0000 Subject: [PATCH 03/12] =?UTF-8?q?refactor:=20ASGI=20=E6=BA=96=E6=8B=A0?= =?UTF-8?q?=E3=81=AE=E6=98=8E=E7=A2=BA=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index 4bf91566f..4837621a7 100644 --- a/run.py +++ b/run.py @@ -121,7 +121,7 @@ def generate_app( allow_origin: list[str] | None = None, disable_mutable_api: bool = False, ) -> FastAPI: - """ASGI に準拠した VOICEVOX ENGINE アプリケーションを生成する。""" + """ASGI 'application' 仕様に準拠した VOICEVOX ENGINE アプリケーションインスタンスを生成する。""" if root_dir is None: root_dir = engine_root() @@ -762,7 +762,7 @@ def main() -> None: disable_mutable_api=disable_mutable_api, ) - # ASGI に準拠したサーバを立ち上げる + # ASGI に準拠した VOICEVOX ENGINE HTTP/1.1 サーバを立ち上げる uvicorn.run(app, host=args.host, port=args.port) From 33cd1f20a7af33ac02fa68e14977600a4ac8ff1e Mon Sep 17 00:00:00 2001 From: tarepan Date: Wed, 1 May 2024 12:48:11 +0000 Subject: [PATCH 04/12] =?UTF-8?q?refactor:=20not=20None=20=E5=80=A4?= =?UTF-8?q?=E4=BB=A3=E5=85=A5=E3=82=92=20util=20=E9=96=A2=E6=95=B0?= =?UTF-8?q?=E3=81=A7=E7=B5=B1=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/run.py b/run.py index 4837621a7..f24434c6c 100644 --- a/run.py +++ b/run.py @@ -11,7 +11,7 @@ from io import BytesIO, TextIOWrapper from pathlib import Path from tempfile import NamedTemporaryFile -from typing import Annotated, Any +from typing import Annotated, Any, TypeVar import soundfile import uvicorn @@ -537,6 +537,24 @@ def custom_openapi() -> Any: return app +T = TypeVar("T") +def select_first_not_none(candidates: list[T | None]) -> T: + """None でない最初の値を取り出す。全ての None の場合はエラーを上げる。""" + for candidate in candidates: + if candidate is not None: + return candidate + raise RuntimeError("すべての候補値が None です") + + +S = TypeVar("S") +def select_first_not_none_or_none(candidates: list[S | None]) -> S | None: + """None でない最初の値を取り出そうとし、全ての None の場合は None を返す。""" + for candidate in candidates: + if candidate is not None: + return candidate + return None + + def main() -> None: multiprocessing.freeze_support() @@ -676,6 +694,12 @@ def main() -> None: args = parser.parse_args() + # NOTE: 型検査のため Any 値に対して明示的に型を付ける + arg_cors_policy_mode: CorsPolicyMode | None = args.cors_policy_mode + arg_allow_origin: list[str] | None = args.allow_origin + arg_preset_path: Path | None = args.preset_file + arg_disable_mutable_api: bool = args.disable_mutable_api + if args.output_log_utf8: set_output_log_utf8() @@ -725,13 +749,13 @@ def main() -> None: settings = setting_loader.load() # CORSの許可モード。優先度は「引数 > 設定ファイル」 - cors_policy_mode = args.cors_policy_mode or settings.cors_policy_mode + cors_policy_mode = select_first_not_none([arg_cors_policy_mode, settings.cors_policy_mode]) # 許可するオリジン。優先度は「引数 > 設定ファイル > デフォルト」 setting_allow_origin = None if settings.allow_origin: setting_allow_origin = settings.allow_origin.split(" ") - allow_origin = args.allow_origin or setting_allow_origin or None + allow_origin = select_first_not_none_or_none([arg_allow_origin, setting_allow_origin]) # プリセットマネージャー。設定ファイルパスの優先度は「引数 > 環境変数 > ルート」 # ファイルの存在に関わらず、優先順で最初に指定されたパスをプリセットファイルとして使用する @@ -741,12 +765,14 @@ def main() -> None: else: env_preset_path = None root_preset_path = root_dir / "presets.yaml" - preset_path = args.preset_file or env_preset_path or root_preset_path + preset_path = select_first_not_none([arg_preset_path, env_preset_path, root_preset_path]) preset_manager = PresetManager(preset_path) # ミュータブル API の無効化。優先度は「引数 > 環境変数 > デフォルト(False)」 - env_disable_mutable_api = decide_boolean_from_env("VV_DISABLE_MUTABLE_API") - disable_mutable_api = args.disable_mutable_api or env_disable_mutable_api + if arg_disable_mutable_api: + disable_mutable_api = True + else: + disable_mutable_api = decide_boolean_from_env("VV_DISABLE_MUTABLE_API") # ASGI に準拠した VOICEVOX ENGINE アプリケーションを生成する app = generate_app( From 8b7206df80c72a65cb65577be291bf1d8f9cb385 Mon Sep 17 00:00:00 2001 From: tarepan Date: Wed, 1 May 2024 12:56:26 +0000 Subject: [PATCH 05/12] =?UTF-8?q?refactor:=20None=20=E5=88=A4=E5=AE=9A?= =?UTF-8?q?=E3=82=92=E5=AE=89=E5=85=A8=E5=81=B4=E3=81=AB=E7=B5=B1=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index f24434c6c..57d2b7ec9 100644 --- a/run.py +++ b/run.py @@ -742,7 +742,9 @@ def main() -> None: ) # ルートディレクトリのパス。優先度は「引数 > デフォルト」 - root_dir = voicevox_dir or engine_root() + root_dir = voicevox_dir + if root_dir is None: + root_dir = engine_root() setting_loader = SettingHandler(args.setting_file) @@ -753,14 +755,14 @@ def main() -> None: # 許可するオリジン。優先度は「引数 > 設定ファイル > デフォルト」 setting_allow_origin = None - if settings.allow_origin: + if settings.allow_origin is not None: setting_allow_origin = settings.allow_origin.split(" ") allow_origin = select_first_not_none_or_none([arg_allow_origin, setting_allow_origin]) # プリセットマネージャー。設定ファイルパスの優先度は「引数 > 環境変数 > ルート」 # ファイルの存在に関わらず、優先順で最初に指定されたパスをプリセットファイルとして使用する env_preset_path_str = os.getenv("VV_PRESET_FILE") - if env_preset_path_str and len(env_preset_path_str) != 0: + if env_preset_path_str is not None and len(env_preset_path_str) != 0: env_preset_path = Path(env_preset_path_str) else: env_preset_path = None From 4ef70960d0c530ab188eba72db3e75294345d268 Mon Sep 17 00:00:00 2001 From: tarepan Date: Wed, 1 May 2024 12:56:45 +0000 Subject: [PATCH 06/12] fix: lint --- run.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index 57d2b7ec9..d648ddc89 100644 --- a/run.py +++ b/run.py @@ -538,6 +538,8 @@ def custom_openapi() -> Any: T = TypeVar("T") + + def select_first_not_none(candidates: list[T | None]) -> T: """None でない最初の値を取り出す。全ての None の場合はエラーを上げる。""" for candidate in candidates: @@ -547,6 +549,8 @@ def select_first_not_none(candidates: list[T | None]) -> T: S = TypeVar("S") + + def select_first_not_none_or_none(candidates: list[S | None]) -> S | None: """None でない最初の値を取り出そうとし、全ての None の場合は None を返す。""" for candidate in candidates: @@ -751,13 +755,17 @@ def main() -> None: settings = setting_loader.load() # CORSの許可モード。優先度は「引数 > 設定ファイル」 - cors_policy_mode = select_first_not_none([arg_cors_policy_mode, settings.cors_policy_mode]) + cors_policy_mode = select_first_not_none( + [arg_cors_policy_mode, settings.cors_policy_mode] + ) # 許可するオリジン。優先度は「引数 > 設定ファイル > デフォルト」 setting_allow_origin = None if settings.allow_origin is not None: setting_allow_origin = settings.allow_origin.split(" ") - allow_origin = select_first_not_none_or_none([arg_allow_origin, setting_allow_origin]) + allow_origin = select_first_not_none_or_none( + [arg_allow_origin, setting_allow_origin] + ) # プリセットマネージャー。設定ファイルパスの優先度は「引数 > 環境変数 > ルート」 # ファイルの存在に関わらず、優先順で最初に指定されたパスをプリセットファイルとして使用する @@ -767,7 +775,9 @@ def main() -> None: else: env_preset_path = None root_preset_path = root_dir / "presets.yaml" - preset_path = select_first_not_none([arg_preset_path, env_preset_path, root_preset_path]) + preset_path = select_first_not_none( + [arg_preset_path, env_preset_path, root_preset_path] + ) preset_manager = PresetManager(preset_path) # ミュータブル API の無効化。優先度は「引数 > 環境変数 > デフォルト(False)」 From 90aa29e296f97d7e41f7d285b3d59ca476f604a3 Mon Sep 17 00:00:00 2001 From: tarepan Date: Wed, 1 May 2024 13:16:39 +0000 Subject: [PATCH 07/12] =?UTF-8?q?refactor:=20=E5=84=AA=E5=85=88=E5=BA=A6?= =?UTF-8?q?=E8=A7=A3=E8=AA=AC=E3=82=92=E9=9B=86=E7=B4=84=E3=80=81=E3=83=AB?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=83=91=E3=82=B9=E6=8C=87=E5=AE=9A=E3=82=92?= =?UTF-8?q?=E5=85=B1=E9=80=9A=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/run.py b/run.py index d648ddc89..2ed8a7225 100644 --- a/run.py +++ b/run.py @@ -745,21 +745,17 @@ def main() -> None: enable_mock=enable_mock, ) - # ルートディレクトリのパス。優先度は「引数 > デフォルト」 - root_dir = voicevox_dir - if root_dir is None: - root_dir = engine_root() - setting_loader = SettingHandler(args.setting_file) - settings = setting_loader.load() - # CORSの許可モード。優先度は「引数 > 設定ファイル」 + # 複数方式で指定可能な場合、優先度は「引数 > 環境変数 > 設定ファイル > デフォルト値」 + + root_dir = select_first_not_none([voicevox_dir, engine_root()]) + cors_policy_mode = select_first_not_none( [arg_cors_policy_mode, settings.cors_policy_mode] ) - # 許可するオリジン。優先度は「引数 > 設定ファイル > デフォルト」 setting_allow_origin = None if settings.allow_origin is not None: setting_allow_origin = settings.allow_origin.split(" ") @@ -767,8 +763,6 @@ def main() -> None: [arg_allow_origin, setting_allow_origin] ) - # プリセットマネージャー。設定ファイルパスの優先度は「引数 > 環境変数 > ルート」 - # ファイルの存在に関わらず、優先順で最初に指定されたパスをプリセットファイルとして使用する env_preset_path_str = os.getenv("VV_PRESET_FILE") if env_preset_path_str is not None and len(env_preset_path_str) != 0: env_preset_path = Path(env_preset_path_str) @@ -778,9 +772,9 @@ def main() -> None: preset_path = select_first_not_none( [arg_preset_path, env_preset_path, root_preset_path] ) + # ファイルの存在に関わらず指定されたパスをプリセットファイルとして使用する preset_manager = PresetManager(preset_path) - # ミュータブル API の無効化。優先度は「引数 > 環境変数 > デフォルト(False)」 if arg_disable_mutable_api: disable_mutable_api = True else: From 90906a31a6b08addb501818fe5d2fc49b7848d7e Mon Sep 17 00:00:00 2001 From: tarepan Date: Fri, 3 May 2024 13:56:05 +0900 Subject: [PATCH 08/12] fix: typo Co-authored-by: Hiroshiba --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index 376f57810..f2e9e730c 100644 --- a/run.py +++ b/run.py @@ -186,7 +186,7 @@ def get_core(core_version: str | None) -> CoreAdapter: def select_first_not_none(candidates: list[T | None]) -> T: - """None でない最初の値を取り出す。全ての None の場合はエラーを上げる。""" + """None でない最初の値を取り出す。全て None の場合はエラーを上げる。""" for candidate in candidates: if candidate is not None: return candidate From a863ef265cf00f6e60329016c7ec807db6a420ef Mon Sep 17 00:00:00 2001 From: tarepan Date: Fri, 3 May 2024 13:57:31 +0900 Subject: [PATCH 09/12] fix: typo Co-authored-by: Hiroshiba --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index f2e9e730c..ce25fe448 100644 --- a/run.py +++ b/run.py @@ -197,7 +197,7 @@ def select_first_not_none(candidates: list[T | None]) -> T: def select_first_not_none_or_none(candidates: list[S | None]) -> S | None: - """None でない最初の値を取り出そうとし、全ての None の場合は None を返す。""" + """None でない最初の値を取り出そうとし、全て None の場合は None を返す。""" for candidate in candidates: if candidate is not None: return candidate From 364764d09ca240f8163e49890232e551e23b7fd9 Mon Sep 17 00:00:00 2001 From: tarepan Date: Mon, 6 May 2024 12:46:10 +0900 Subject: [PATCH 10/12] =?UTF-8?q?add:=20=E3=82=B5=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=BC=E8=B5=B7=E5=8B=95=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B?= =?UTF-8?q?=20NOTE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hiroshiba --- run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/run.py b/run.py index ce25fe448..dec5d5c9a 100644 --- a/run.py +++ b/run.py @@ -439,7 +439,8 @@ def main() -> None: disable_mutable_api=disable_mutable_api, ) - # ASGI に準拠した VOICEVOX ENGINE HTTP/1.1 サーバを立ち上げる + # VOICEVOX ENGINE サーバーを起動 + # NOTE: デフォルトは ASGI に準拠した HTTP/1.1 サーバー uvicorn.run(app, host=args.host, port=args.port) From 21bad62d86273e5e3942777a34eef4d009304c14 Mon Sep 17 00:00:00 2001 From: tarepan Date: Mon, 6 May 2024 04:27:01 +0000 Subject: [PATCH 11/12] =?UTF-8?q?fix:=20=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E9=96=A2=E9=80=A3=E3=81=AE=E6=97=A5=E6=9C=AC=E8=AA=9E=E8=A8=98?= =?UTF-8?q?=E8=BF=B0=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index dec5d5c9a..a95aca264 100644 --- a/run.py +++ b/run.py @@ -186,7 +186,7 @@ def get_core(core_version: str | None) -> CoreAdapter: def select_first_not_none(candidates: list[T | None]) -> T: - """None でない最初の値を取り出す。全て None の場合はエラーを上げる。""" + """None でない最初の値を取り出す。全て None の場合はエラーを送出する。""" for candidate in candidates: if candidate is not None: return candidate From c3849ac89a0b371ab3570f14b52c652662e0a69e Mon Sep 17 00:00:00 2001 From: tarepan Date: Mon, 6 May 2024 04:27:49 +0000 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20=E5=84=AA=E5=85=88=E5=BA=A6?= =?UTF-8?q?=E8=A1=A8=E8=A8=98=E3=82=92=E4=B8=80=E8=88=AC=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index a95aca264..0993c2e26 100644 --- a/run.py +++ b/run.py @@ -393,7 +393,7 @@ def main() -> None: setting_loader = SettingHandler(args.setting_file) settings = setting_loader.load() - # 複数方式で指定可能な場合、優先度は「引数 > 環境変数 > 設定ファイル > デフォルト値」 + # 複数方式で指定可能な場合、優先度は上から「引数」「環境変数」「設定ファイル」「デフォルト値」 root_dir = select_first_not_none([voicevox_dir, engine_root()])