11from typing import Any , Dict , List , Optional
2+ from urllib .parse import urlsplit
23
3- from pydantic import ConfigDict , Field , model_validator
4+ from pydantic import ConfigDict , Field , field_validator , model_validator
45
56from .base import BaseTTS , CartesiaSampleRate , ElevenLabsSampleRate , GoogleTTSSampleRate , MicrosoftSampleRate
67from ..presets import MiniMaxPresetModels , OpenAITtsPresetModels
@@ -63,9 +64,9 @@ class MicrosoftTTS(BaseTTS):
6364 def to_config (self ) -> Dict [str , Any ]:
6465 params : Dict [str , Any ] = dict (self .additional_params or {})
6566 params .update ({
66- "key" : self .key ,
67- "region" : self .region ,
68- "voice_name" : self .voice_name ,
67+ "key" : self .key ,
68+ "region" : self .region ,
69+ "voice_name" : self .voice_name ,
6970 })
7071
7172 if self .sample_rate is not None :
@@ -241,8 +242,8 @@ class DeepgramTTS(BaseTTS):
241242 def to_config (self ) -> Dict [str , Any ]:
242243 params : Dict [str , Any ] = dict (self .additional_params or {})
243244 params .update ({
244- "api_key" : self .api_key ,
245- "model" : self .model ,
245+ "api_key" : self .api_key ,
246+ "model" : self .model ,
246247 })
247248
248249 if self .base_url is not None :
@@ -516,10 +517,10 @@ def to_config(self) -> Dict[str, Any]:
516517class GenericTTS (BaseTTS ):
517518 model_config = ConfigDict (extra = "forbid" )
518519
519- url : str = Field (..., description = "Callback address of the generic TTS service" )
520- headers : Dict [str , str ] = Field (... , description = "Custom headers to include in requests to the generic TTS service " )
521- model : str = Field (... , description = "TTS model name" )
522- voice : str = Field (... , description = "Voice name" )
520+ url : str = Field (..., description = "HTTP(S) endpoint of the generic TTS service" )
521+ headers : Optional [ Dict [str , str ]] = Field (default = None , description = "Custom request headers " )
522+ model : Optional [ str ] = Field (default = None , description = "TTS model name" )
523+ voice : Optional [ str ] = Field (default = None , description = "Voice name" )
523524 api_key : Optional [str ] = Field (default = None , description = "API key for the generic TTS service" )
524525 speed : Optional [float ] = Field (default = None , description = "Speech rate" )
525526 sample_rate : Optional [int ] = Field (default = None , description = "Output audio sample rate in Hz" )
@@ -528,12 +529,22 @@ class GenericTTS(BaseTTS):
528529 additional_params : Optional [Dict [str , Any ]] = Field (default = None , description = "Additional generic TTS params" )
529530 skip_patterns : Optional [List [int ]] = Field (default = None )
530531
532+ @field_validator ("url" )
533+ @classmethod
534+ def validate_url (cls , value : str ) -> str :
535+ parsed = urlsplit (value )
536+ if parsed .scheme .lower () not in {"http" , "https" } or not parsed .netloc :
537+ raise ValueError ("GenericTTS url must be a valid HTTP(S) endpoint" )
538+ return value
539+
531540 def to_config (self ) -> Dict [str , Any ]:
532541 params : Dict [str , Any ] = dict (self .additional_params or {})
533542 if self .api_key is not None :
534543 params ["api_key" ] = self .api_key
535- params ["model" ] = self .model
536- params ["voice" ] = self .voice
544+ if self .model is not None :
545+ params ["model" ] = self .model
546+ if self .voice is not None :
547+ params ["voice" ] = self .voice
537548 if self .speed is not None :
538549 params ["speed" ] = self .speed
539550 if self .sample_rate is not None :
@@ -544,11 +555,12 @@ def to_config(self) -> Dict[str, Any]:
544555 params ["instruction" ] = self .instruction
545556
546557 result : Dict [str , Any ] = {
547- "vendor" : "generic " ,
558+ "vendor" : "generic_http " ,
548559 "url" : self .url ,
549- "headers" : self .headers ,
550560 "params" : params ,
551561 }
562+ if self .headers is not None :
563+ result ["headers" ] = self .headers
552564 if self .skip_patterns is not None :
553565 result ["skip_patterns" ] = self .skip_patterns
554566 return result
0 commit comments