Skip to main content
Glama

NijiVoice-MCP

by ryoooo
models.py6.02 kB
from typing import Optional, List, Literal import logging from pydantic import BaseModel, field_serializer, Field, ConfigDict # ロガーの設定 logger = logging.getLogger('nijivoice_mcp.models') class RecommendedParameters(BaseModel): """にじボイスの推奨パラメータモデル""" emotional_level: Optional[float] = Field(1.0, alias="emotionalLevel") sound_duration: Optional[float] = Field(1.0, alias="soundDuration") # 未知のフィールドをスキップする設定 model_config = ConfigDict( populate_by_name=True, extra="ignore" # 未知のフィールドを無視する ) class VoiceStyle(BaseModel): """にじボイスのVoice Styleモデル""" id: int style: str model_config = ConfigDict( populate_by_name=True, extra="ignore" # 未知のフィールドを無視する ) class VoiceActor(BaseModel): """にじボイスのVoice Actorモデル""" id: str name: str name_reading: Optional[str] = Field(None, alias="nameReading") age: Optional[int] = None gender: Optional[str] = None birth_month: Optional[int] = Field(None, alias="birthMonth") birth_day: Optional[int] = Field(None, alias="birthDay") description: Optional[str] = "" # 画像URL small_image_url: Optional[str] = Field(None, alias="smallImageUrl") medium_image_url: Optional[str] = Field(None, alias="mediumImageUrl") large_image_url: Optional[str] = Field(None, alias="largeImageUrl") image_url: Optional[str] = Field(None, alias="imageUrl") # 後方互換性のため # 音声サンプル sample_voice_url: Optional[str] = Field(None, alias="sampleVoiceUrl") sample_audio_url: Optional[str] = Field(None, alias="sampleAudioUrl") # 後方互換性のため sample_script: Optional[str] = Field(None, alias="sampleScript") # 推奨パラメータ recommended_voice_speed: Optional[float] = Field(None, alias="recommendedVoiceSpeed") recommended_emotional_level: Optional[float] = Field(None, alias="recommendedEmotionalLevel") recommended_sound_duration: Optional[float] = Field(None, alias="recommendedSoundDuration") recommended_parameters: Optional[RecommendedParameters] = Field(None, alias="recommendedParameters") # ボイススタイル voice_styles: Optional[List[VoiceStyle]] = Field(None, alias="voiceStyles") # 未知のフィールドをスキップする設定 model_config = ConfigDict( populate_by_name=True, extra="ignore" # 未知のフィールドを無視する ) class VoiceGenerationRequest(BaseModel): """音声生成リクエストモデル""" id: str = Field(default="5c7f729f-5814-436f-9e81-95aa837f9737", description="Voice Actor ID") script: str = Field(default="これはにじボイスMCPで生成しました", description="生成する音声のテキスト") speed: float = Field(default=1.0, description="話速", ge=0.4, le=3.0) emotional_level: Optional[float] = Field( default=None, alias="emotionalLevel", description="感情レベル", ge=0.0, le=1.5 ) sound_duration: Optional[float] = Field( default=None, alias="soundDuration", description="音の継続時間", ge=0.0, le=1.7 ) format: Literal["mp3", "wav"] = Field( default="mp3", description="音声フォーマット" ) model_config = ConfigDict(populate_by_name=True, extra="ignore") @field_serializer('speed') def serialize_speed(self, speed: float) -> str: return str(speed) @field_serializer('emotional_level') def serialize_emotional_level(self, emotional_level: Optional[float]) -> Optional[str]: return str(emotional_level) if emotional_level is not None else None @field_serializer('sound_duration') def serialize_sound_duration(self, sound_duration: Optional[float]) -> Optional[str]: return str(sound_duration) if sound_duration is not None else None @field_serializer('format') def serialize_format(self, fmt: str): return fmt.lower() def model_dump(self, **kwargs): """カスタムdump処理: Noneの値を持つフィールドは除外""" data = super().model_dump(**kwargs) # Noneの値を持つフィールドを削除 return {k: v for k, v in data.items() if v is not None} class Balance(BaseModel): """クレジット残高モデル""" balance: Optional[int] = None balances: Optional[dict] = None model_config = ConfigDict( populate_by_name=True, extra="ignore" # 未知のフィールドを無視する ) def get_credit(self) -> int: """異なるレスポンス形式に対応してクレジット残高を取得する""" # 直接balanceフィールドがある場合 if self.balance is not None: return self.balance # balancesオブジェクト内の様々な構造に対応 if self.balances and isinstance(self.balances, dict): # remainingBalanceがある場合 if 'remainingBalance' in self.balances: return self.balances['remainingBalance'] # balanceがある場合 elif 'balance' in self.balances: return self.balances['balance'] # creditsリストがあり、その中にbalanceがある場合 if 'credits' in self.balances and isinstance(self.balances['credits'], list) and len(self.balances['credits']) > 0: for credit in self.balances['credits']: if isinstance(credit, dict) and 'balance' in credit: return credit['balance'] # どのフィールドにも残高情報がない場合 logger.warning("クレジット残高情報が見つかりませんでした") return 0

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ryoooo/nijivoice-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server