Skip to content

Commit

Permalink
CancellableEngineが必要な引数だけを受け取るようにする (#762)
Browse files Browse the repository at this point in the history
  • Loading branch information
aoirint authored Oct 16, 2023
1 parent 0a26ebd commit 758b670
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 45 deletions.
36 changes: 27 additions & 9 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,26 +1302,44 @@ def main() -> None:
if args.output_log_utf8:
set_output_log_utf8()

cpu_num_threads: Optional[int] = args.cpu_num_threads
# Synthesis Engine
use_gpu: bool = args.use_gpu
voicevox_dir: Path | None = args.voicevox_dir
voicelib_dirs: list[Path] | None = args.voicelib_dir
runtime_dirs: list[Path] | None = args.runtime_dir
enable_mock: bool = args.enable_mock
cpu_num_threads: int | None = args.cpu_num_threads
load_all_models: bool = args.load_all_models

synthesis_engines = make_synthesis_engines(
use_gpu=args.use_gpu,
voicelib_dirs=args.voicelib_dir,
voicevox_dir=args.voicevox_dir,
runtime_dirs=args.runtime_dir,
use_gpu=use_gpu,
voicelib_dirs=voicelib_dirs,
voicevox_dir=voicevox_dir,
runtime_dirs=runtime_dirs,
cpu_num_threads=cpu_num_threads,
enable_mock=args.enable_mock,
load_all_models=args.load_all_models,
enable_mock=enable_mock,
load_all_models=load_all_models,
)
assert len(synthesis_engines) != 0, "音声合成エンジンがありません。"
latest_core_version = get_latest_core_version(versions=synthesis_engines.keys())

# Cancellable Engine
enable_cancellable_synthesis: bool = args.enable_cancellable_synthesis
init_processes: int = args.init_processes

cancellable_engine: CancellableEngine | None = None
if enable_cancellable_synthesis:
cancellable_engine = CancellableEngine(args)
cancellable_engine = CancellableEngine(
init_processes=init_processes,
use_gpu=use_gpu,
voicelib_dirs=voicelib_dirs,
voicevox_dir=voicevox_dir,
runtime_dirs=runtime_dirs,
cpu_num_threads=cpu_num_threads,
enable_mock=enable_mock,
)

root_dir: Path | None = args.voicevox_dir
root_dir: Path | None = voicevox_dir
if root_dir is None:
root_dir = engine_root()

Expand Down
103 changes: 67 additions & 36 deletions voicevox_engine/cancellable_engine.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import argparse
import asyncio
import queue
import sys
from multiprocessing import Pipe, Process
from multiprocessing.connection import Connection

if sys.platform == "win32":
from multiprocessing.connection import PipeConnection as ConnectionType
else:
from multiprocessing.connection import Connection as ConnectionType

from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import List, Optional, Tuple

import soundfile

Expand All @@ -22,52 +27,72 @@ class CancellableEngine:
初期化後は、synthesis関数で音声合成できる
(オリジナルと比べ引数が増えているので注意)
パラメータ use_gpu, voicelib_dirs, voicevox_dir,
runtime_dirs, cpu_num_threads, enable_mock は、 make_synthesis_engines を参照
Attributes
----------
watch_con_list: List[Tuple[Request, Process]]
watch_con_list: list[tuple[Request, Process]]
Requestは接続の監視に使用され、Processは通信切断時のプロセスキルに使用される
クライアントから接続があるとListにTupleが追加される
接続が切断、もしくは音声合成が終了すると削除される
procs_and_cons: queue.Queue[Tuple[Process, Connection]]
procs_and_cons: queue.Queue[tuple[Process, ConnectionType]]
音声合成の準備が終わっているプロセスのList
(音声合成中のプロセスは入っていない)
"""

def __init__(self, args: argparse.Namespace) -> None:
def __init__(
self,
init_processes: int,
use_gpu: bool,
voicelib_dirs: list[Path] | None,
voicevox_dir: Path | None,
runtime_dirs: list[Path] | None,
cpu_num_threads: int | None,
enable_mock: bool,
) -> None:
"""
変数の初期化を行う
また、args.init_processesの数だけプロセスを起動し、procs_and_consに格納する
また、init_processesの数だけプロセスを起動し、procs_and_consに格納する
"""
self.args = args
if not self.args.enable_cancellable_synthesis:
raise HTTPException(
status_code=404,
detail="実験的機能はデフォルトで無効になっています。使用するには引数を指定してください。",
)

self.watch_con_list: List[Tuple[Request, Process]] = []
self.procs_and_cons: queue.Queue[Tuple[Process, Connection]] = queue.Queue()
for _ in range(self.args.init_processes):
self.procs_and_cons.put(self.start_new_proc())

self.use_gpu = use_gpu
self.voicelib_dirs = voicelib_dirs
self.voicevox_dir = voicevox_dir
self.runtime_dirs = runtime_dirs
self.cpu_num_threads = cpu_num_threads
self.enable_mock = enable_mock

self.watch_con_list: list[tuple[Request, Process]] = []

procs_and_cons: queue.Queue[tuple[Process, ConnectionType]] = queue.Queue()
for _ in range(init_processes):
procs_and_cons.put(self.start_new_proc())
self.procs_and_cons = procs_and_cons

def start_new_proc(
self,
) -> Tuple[Process, Connection]:
) -> tuple[Process, ConnectionType]:
"""
新しく開始したプロセスを返す関数
Returns
-------
ret_proc: Process
新規のプロセス
sub_proc_con1: Connection
sub_proc_con1: ConnectionType
ret_procのプロセスと通信するためのPipe
"""
sub_proc_con1, sub_proc_con2 = Pipe(True)
ret_proc = Process(
target=start_synthesis_subprocess,
kwargs={
"args": self.args,
"use_gpu": self.use_gpu,
"voicelib_dirs": self.voicelib_dirs,
"voicevox_dir": self.voicevox_dir,
"runtime_dirs": self.runtime_dirs,
"cpu_num_threads": self.cpu_num_threads,
"enable_mock": self.enable_mock,
"sub_proc_con": sub_proc_con2,
},
daemon=True,
Expand All @@ -79,7 +104,7 @@ def finalize_con(
self,
req: Request,
proc: Process,
sub_proc_con: Optional[Connection],
sub_proc_con: ConnectionType | None,
) -> None:
"""
接続が切断された時の処理を行う関数
Expand All @@ -94,7 +119,7 @@ def finalize_con(
https://fastapi.tiangolo.com/advanced/using-request-directly/
proc: Process
音声合成を行っていたプロセス
sub_proc_con: Connection, optional
sub_proc_con: ConnectionType, optional
音声合成を行っていたプロセスとのPipe
指定されていない場合、プロセスは再利用されず終了される
"""
Expand All @@ -117,7 +142,7 @@ def _synthesis_impl(
query: AudioQuery,
speaker_id: int,
request: Request,
core_version: Optional[str],
core_version: str | None,
) -> str:
"""
音声合成を行う関数
Expand Down Expand Up @@ -173,28 +198,34 @@ async def catch_disconnection(self):


def start_synthesis_subprocess(
args: argparse.Namespace,
sub_proc_con: Connection,
):
use_gpu: bool,
voicelib_dirs: list[Path] | None,
voicevox_dir: Path | None,
runtime_dirs: list[Path] | None,
cpu_num_threads: int | None,
enable_mock: bool,
sub_proc_con: ConnectionType,
) -> None:
"""
音声合成を行うサブプロセスで行うための関数
pickle化の関係でグローバルに書いている
引数 use_gpu, voicelib_dirs, voicevox_dir,
runtime_dirs, cpu_num_threads, enable_mock は、 make_synthesis_engines を参照
Parameters
----------
args: argparse.Namespace
起動時に作られたものをそのまま渡す
sub_proc_con: Connection
sub_proc_con: ConnectionType
メインプロセスと通信するためのPipe
"""

synthesis_engines = make_synthesis_engines(
use_gpu=args.use_gpu,
voicelib_dirs=args.voicelib_dir,
voicevox_dir=args.voicevox_dir,
runtime_dirs=args.runtime_dir,
cpu_num_threads=args.cpu_num_threads,
enable_mock=args.enable_mock,
use_gpu=use_gpu,
voicelib_dirs=voicelib_dirs,
voicevox_dir=voicevox_dir,
runtime_dirs=runtime_dirs,
cpu_num_threads=cpu_num_threads,
enable_mock=enable_mock,
)
assert len(synthesis_engines) != 0, "音声合成エンジンがありません。"
latest_core_version = get_latest_core_version(versions=synthesis_engines.keys())
Expand Down

0 comments on commit 758b670

Please sign in to comment.