From ec09505f6bed113a6b64586e68d5884c550c1af3 Mon Sep 17 00:00:00 2001 From: Mark Backman Date: Thu, 3 Jul 2025 13:14:15 -0700 Subject: [PATCH] FishAudioTTSService: Add normalize as InputParam, model_id as arg --- CHANGELOG.md | 9 ++++++--- src/pipecat/services/fish/tts.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 696dd99fd..79b9c04f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added `normalize` and `model_id` to `FishAudioTTSService`. + - Added `run_llm` field to `LLMMessagesAppendFrame` and `LLMMessagesUpdateFrame` frames. If true, a context frame will be pushed triggering the LLM to respond. @@ -85,9 +87,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Deprecated -- In `FishTTSService`, deprecated `model` and replaced with `reference_id`. - This change is to better align with Fish Audio's variable naming and to - reduce confusion about what functionality the variable controls. +- In `FishAudioTTSService`, deprecated `model` and replaced with + `reference_id`. This change is to better align with Fish Audio's variable + naming and to reduce confusion about what functionality the variable + controls. ## [0.0.73] - 2025-06-26 diff --git a/src/pipecat/services/fish/tts.py b/src/pipecat/services/fish/tts.py index 9d5af657e..598bac0f3 100644 --- a/src/pipecat/services/fish/tts.py +++ b/src/pipecat/services/fish/tts.py @@ -58,12 +58,14 @@ class FishAudioTTSService(InterruptibleTTSService): Parameters: language: Language for synthesis. Defaults to English. latency: Latency mode ("normal" or "balanced"). Defaults to "normal". + normalize: Whether to normalize audio output. Defaults to True. prosody_speed: Speech speed multiplier (0.5-2.0). Defaults to 1.0. prosody_volume: Volume adjustment in dB. Defaults to 0. """ language: Optional[Language] = Language.EN latency: Optional[str] = "normal" # "normal" or "balanced" + normalize: Optional[bool] = True prosody_speed: Optional[float] = 1.0 # Speech speed (0.5-2.0) prosody_volume: Optional[int] = 0 # Volume adjustment in dB @@ -73,6 +75,7 @@ class FishAudioTTSService(InterruptibleTTSService): api_key: str, reference_id: Optional[str] = None, # This is the voice ID model: Optional[str] = None, # Deprecated + model_id: str = "speech-1.5", output_format: FishAudioOutputFormat = "pcm", sample_rate: Optional[int] = None, params: Optional[InputParams] = None, @@ -89,6 +92,7 @@ class FishAudioTTSService(InterruptibleTTSService): The `model` parameter is deprecated and will be removed in version 0.1.0. Use `reference_id` instead to specify the voice model. + model_id: Specify which Fish Audio TTS model to use (e.g. "speech-1.5") output_format: Audio output format. Defaults to "pcm". sample_rate: Audio sample rate. If None, uses default. params: Additional input parameters for voice customization. @@ -134,6 +138,7 @@ class FishAudioTTSService(InterruptibleTTSService): "sample_rate": 0, "latency": params.latency, "format": output_format, + "normalize": params.normalize, "prosody": { "speed": params.prosody_speed, "volume": params.prosody_volume, @@ -141,6 +146,8 @@ class FishAudioTTSService(InterruptibleTTSService): "reference_id": reference_id, } + self.set_model_name(model_id) + def can_generate_metrics(self) -> bool: """Check if this service can generate processing metrics. @@ -149,6 +156,17 @@ class FishAudioTTSService(InterruptibleTTSService): """ return True + async def set_model(self, model: str): + """Set the TTS model and reconnect. + + Args: + model: The model name to use for synthesis. + """ + await super().set_model(model) + logger.info(f"Switching TTS model to: [{model}]") + await self._disconnect() + await self._connect() + async def start(self, frame: StartFrame): """Start the Fish Audio TTS service. @@ -197,6 +215,7 @@ class FishAudioTTSService(InterruptibleTTSService): logger.debug("Connecting to Fish Audio") headers = {"Authorization": f"Bearer {self._api_key}"} + headers["model"] = self.model_name self._websocket = await websockets.connect(self._base_url, extra_headers=headers) # Send initial start message with ormsgpack