Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

整理: Speaker と内部型の分離 #1202

Merged
merged 10 commits into from
May 6, 2024
4 changes: 2 additions & 2 deletions test/test_metas_store.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import uuid
from unittest import TestCase

from voicevox_engine.metas.Metas import Speaker, SpeakerStyle, StyleType
from voicevox_engine.metas.Metas import Speaker, SpeakerStyle, StyleId, StyleType
from voicevox_engine.metas.MetasStore import filter_speakers_and_styles


Expand All @@ -12,7 +12,7 @@ def _gen_speaker(style_types: list[StyleType]) -> Speaker:
styles=[
SpeakerStyle(
name="",
id=0,
id=StyleId(0),
type=style_type,
)
for style_type in style_types
Expand Down
19 changes: 2 additions & 17 deletions voicevox_engine/metas/Metas.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,35 +49,20 @@ class SpeakerSupportedFeatures(BaseModel):
)


class CoreSpeaker(BaseModel):
class Speaker(BaseModel):
"""
コアに含まれる話者情報
話者情報
"""

name: str = Field(title="名前")
speaker_uuid: str = Field(title="話者のUUID")
styles: List[SpeakerStyle] = Field(title="スタイルの一覧")
version: str = Field("話者のバージョン")


class EngineSpeaker(BaseModel):
"""
エンジンに含まれる話者情報
"""

supported_features: SpeakerSupportedFeatures = Field(
title="話者の対応機能", default_factory=SpeakerSupportedFeatures
)


class Speaker(CoreSpeaker, EngineSpeaker):
"""
話者情報
"""

pass


class StyleInfo(BaseModel):
"""
スタイルの追加情報
Expand Down
74 changes: 66 additions & 8 deletions voicevox_engine/metas/MetasStore.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import json
from copy import deepcopy
from pathlib import Path
from typing import TYPE_CHECKING, Dict, List, Literal, Tuple
from typing import TYPE_CHECKING, Dict, List, Literal, NewType, Optional, Tuple

from pydantic import BaseModel, Field

from voicevox_engine.metas.Metas import (
CoreSpeaker,
EngineSpeaker,
Speaker,
SpeakerStyle,
SpeakerSupportedFeatures,
StyleId,
StyleType,
)
Expand All @@ -16,6 +17,58 @@
from voicevox_engine.core.core_adapter import CoreAdapter


_CoreStyleId = NewType("_CoreStyleId", int)
_CoreStyleType = Literal["talk", "singing_teacher", "frame_decode", "sing"]


class _CoreSpeakerStyle(BaseModel):
"""
話者のスタイル情報
"""

name: str = Field(title="スタイル名")
id: _CoreStyleId = Field(title="スタイルID")
type: Optional[_CoreStyleType] = Field(
default="talk",
title=(
"スタイルの種類。"
"talk:音声合成クエリの作成と音声合成が可能。"
"singing_teacher:歌唱音声合成用のクエリの作成が可能。"
"frame_decode:歌唱音声合成が可能。"
"sing:歌唱音声合成用のクエリの作成と歌唱音声合成が可能。"
),
)
tarepan marked this conversation as resolved.
Show resolved Hide resolved


def cast_styles(cores: list[_CoreSpeakerStyle]) -> list[SpeakerStyle]:
"""コアから取得したスタイル情報をエンジン形式へキャストする。"""
return [
SpeakerStyle(name=core.name, id=StyleId(core.id), type=core.type)
for core in cores
]


class _CoreSpeaker(BaseModel):
"""
コアに含まれる話者情報
"""

name: str = Field(title="名前")
speaker_uuid: str = Field(title="話者のUUID")
styles: List[_CoreSpeakerStyle] = Field(title="スタイルの一覧")
version: str = Field("話者のバージョン")


class _EngineSpeaker(BaseModel):
"""
エンジンに含まれる話者情報
"""

supported_features: SpeakerSupportedFeatures = Field(
title="話者の対応機能", default_factory=SpeakerSupportedFeatures
)


class MetasStore:
"""
話者やスタイルのメタ情報を管理する
Expand All @@ -29,8 +82,8 @@ def __init__(self, engine_speakers_path: Path) -> None:
エンジンに含まれる話者メタ情報ディレクトリのパス。
"""
# エンジンに含まれる各話者のメタ情報
self._loaded_metas: Dict[str, EngineSpeaker] = {
folder.name: EngineSpeaker(
self._loaded_metas: Dict[str, _EngineSpeaker] = {
folder.name: _EngineSpeaker(
**json.loads((folder / "metas.json").read_text(encoding="utf-8"))
)
for folder in engine_speakers_path.iterdir()
Expand All @@ -51,12 +104,17 @@ def load_combined_metas(self, core: "CoreAdapter") -> List[Speaker]:
エンジンとコアに含まれる話者メタ情報
"""
# コアに含まれる話者メタ情報の収集
core_metas = [CoreSpeaker(**speaker) for speaker in json.loads(core.speakers)]
core_metas = [_CoreSpeaker(**speaker) for speaker in json.loads(core.speakers)]
# エンジンに含まれる話者メタ情報との統合
return [
Speaker(
**self._loaded_metas[speaker_meta.speaker_uuid].dict(),
**speaker_meta.dict(),
supported_features=self._loaded_metas[
speaker_meta.speaker_uuid
].supported_features,
name=speaker_meta.name,
speaker_uuid=speaker_meta.speaker_uuid,
styles=cast_styles(speaker_meta.styles),
version=speaker_meta.version,
)
for speaker_meta in core_metas
]
Expand Down