From c5e5f3af293590174144d1b51d6f933efd570909 Mon Sep 17 00:00:00 2001 From: tarepan Date: Thu, 20 Jun 2024 00:34:13 +0900 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86:=20`CoreSpeaker`=20=E3=82=92?= =?UTF-8?q?=20`dataclass`=20=E3=81=B8=E5=A4=89=E6=9B=B4=20+=20=E3=83=AA?= =?UTF-8?q?=E3=83=8D=E3=83=BC=E3=83=A0=20(#1409)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: `CoreSpeaker` BaseModel → `CoreCharacter` dataclass へ移行 * refactor: `CoreSpeakerStyle` BaseModel → `CoreCharacterStyle` dataclass へ移行 * fix: `Field` 削除による移行追従 & lint * fix: lint * refactor: `CoreAdapter.speakers` → `CoreAdapter.characters` へリネーム --- voicevox_engine/app/routers/morphing.py | 4 +-- voicevox_engine/app/routers/speaker.py | 8 +++--- voicevox_engine/core/core_adapter.py | 35 +++++++++++++------------ voicevox_engine/metas/MetasStore.py | 6 ++--- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/voicevox_engine/app/routers/morphing.py b/voicevox_engine/app/routers/morphing.py index 364a3ebbb..35635b2cf 100644 --- a/voicevox_engine/app/routers/morphing.py +++ b/voicevox_engine/app/routers/morphing.py @@ -57,7 +57,7 @@ def morphable_targets( version = core_version or core_manager.latest_version() core = core_manager.get_core(version) - speakers = metas_store.load_combined_metas(core.speakers) + speakers = metas_store.load_combined_metas(core.characters) try: morphable_targets = get_morphable_targets(speakers, base_style_ids) except StyleIdNotFoundError as e: @@ -97,7 +97,7 @@ def _synthesis_morphing( core = core_manager.get_core(version) # モーフィングが許可されないキャラクターペアを拒否する - speakers = metas_store.load_combined_metas(core.speakers) + speakers = metas_store.load_combined_metas(core.characters) try: morphable = is_morphable(speakers, base_style_id, target_style_id) except StyleIdNotFoundError as e: diff --git a/voicevox_engine/app/routers/speaker.py b/voicevox_engine/app/routers/speaker.py index d32afe8c1..e5ed9d1c0 100644 --- a/voicevox_engine/app/routers/speaker.py +++ b/voicevox_engine/app/routers/speaker.py @@ -29,7 +29,7 @@ def speakers(core_version: str | SkipJsonSchema[None] = None) -> list[Speaker]: """話者情報の一覧を取得します。""" version = core_version or core_manager.latest_version() core = core_manager.get_core(version) - speakers = metas_store.load_combined_metas(core.speakers) + speakers = metas_store.load_combined_metas(core.characters) return filter_speakers_and_styles(speakers, "speaker") @router.get("/speaker_info") @@ -78,8 +78,8 @@ def _speaker_info( version = core_version or core_manager.latest_version() # 該当話者を検索する - core_speakers = core_manager.get_core(version).speakers - speakers = metas_store.load_combined_metas(core_speakers) + core_characters = core_manager.get_core(version).characters + speakers = metas_store.load_combined_metas(core_characters) speakers = filter_speakers_and_styles(speakers, speaker_or_singer) speaker = next( filter(lambda spk: spk.speaker_uuid == speaker_uuid, speakers), None @@ -143,7 +143,7 @@ def singers(core_version: str | SkipJsonSchema[None] = None) -> list[Speaker]: """歌手情報の一覧を取得します""" version = core_version or core_manager.latest_version() core = core_manager.get_core(version) - singers = metas_store.load_combined_metas(core.speakers) + singers = metas_store.load_combined_metas(core.characters) return filter_speakers_and_styles(singers, "singer") @router.get("/singer_info") diff --git a/voicevox_engine/core/core_adapter.py b/voicevox_engine/core/core_adapter.py index 2ada0ea8f..ecf8264f3 100644 --- a/voicevox_engine/core/core_adapter.py +++ b/voicevox_engine/core/core_adapter.py @@ -3,11 +3,11 @@ import json import threading from dataclasses import dataclass -from typing import Literal, NewType +from typing import Any, Literal, NewType import numpy as np from numpy.typing import NDArray -from pydantic import BaseModel, Field +from pydantic import TypeAdapter from ..metas.Metas import StyleId from .core_wrapper import CoreWrapper, OldCoreError @@ -16,25 +16,26 @@ CoreStyleType = Literal["talk", "singing_teacher", "frame_decode", "sing"] -class CoreSpeakerStyle(BaseModel): - """ - 話者のスタイル情報 - """ +@dataclass(frozen=True) +class CoreCharacterStyle: + """コアに含まれるキャラクターのスタイル情報""" name: str id: CoreStyleId - type: CoreStyleType | None = Field(default="talk") + type: CoreStyleType | None = "talk" -class CoreSpeaker(BaseModel): - """ - コアに含まれる話者情報 - """ +@dataclass(frozen=True) +class CoreCharacter: + """コアに含まれるキャラクター情報""" name: str speaker_uuid: str - styles: list[CoreSpeakerStyle] - version: str = Field(title="話者のバージョン") + styles: list[CoreCharacterStyle] + version: str # 話者のバージョン + + +_core_character_adapter = TypeAdapter(CoreCharacter) @dataclass(frozen=True) @@ -62,10 +63,10 @@ def default_sampling_rate(self) -> int: return self.core.default_sampling_rate @property - def speakers(self) -> list[CoreSpeaker]: - """話者情報""" - metas = self.core.metas() - return [CoreSpeaker(**speaker) for speaker in json.loads(metas)] + def characters(self) -> list[CoreCharacter]: + """キャラクター情報""" + metas: list[Any] = json.loads(self.core.metas()) + return list(map(_core_character_adapter.validate_python, metas)) @property def supported_devices(self) -> DeviceSupport | None: diff --git a/voicevox_engine/metas/MetasStore.py b/voicevox_engine/metas/MetasStore.py index 9d3fcffb4..d1c1aca73 100644 --- a/voicevox_engine/metas/MetasStore.py +++ b/voicevox_engine/metas/MetasStore.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, Field -from voicevox_engine.core.core_adapter import CoreSpeaker, CoreSpeakerStyle +from voicevox_engine.core.core_adapter import CoreCharacter, CoreCharacterStyle from voicevox_engine.metas.Metas import ( Speaker, SpeakerStyle, @@ -15,7 +15,7 @@ ) -def cast_styles(cores: list[CoreSpeakerStyle]) -> list[SpeakerStyle]: +def cast_styles(cores: list[CoreCharacterStyle]) -> list[SpeakerStyle]: """コアから取得したスタイル情報をエンジン形式へキャストする。""" return [ SpeakerStyle(name=core.name, id=StyleId(core.id), type=core.type) @@ -53,7 +53,7 @@ def __init__(self, engine_speakers_path: Path) -> None: for folder in engine_speakers_path.iterdir() } - def load_combined_metas(self, core_metas: list[CoreSpeaker]) -> list[Speaker]: + def load_combined_metas(self, core_metas: list[CoreCharacter]) -> list[Speaker]: """コアとエンジンのメタ情報を統合する。""" return [ Speaker(