Merge pull request #2137 from pipecat-ai/mb/fish-audio-normalize
FishAudioTTSService: arg cleanup, add new InputParam and arg
This commit is contained in:
15
CHANGELOG.md
15
CHANGELOG.md
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added `normalize` and `model_id` to `FishAudioTTSService`.
|
||||||
|
|
||||||
- Added `run_llm` field to `LLMMessagesAppendFrame` and `LLMMessagesUpdateFrame`
|
- Added `run_llm` field to `LLMMessagesAppendFrame` and `LLMMessagesUpdateFrame`
|
||||||
frames. If true, a context frame will be pushed triggering the LLM to respond.
|
frames. If true, a context frame will be pushed triggering the LLM to respond.
|
||||||
|
|
||||||
@@ -61,8 +63,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- Added `session_token` parameter to `AWSNovaSonicLLMService`.
|
- Added `session_token` parameter to `AWSNovaSonicLLMService`.
|
||||||
|
|
||||||
- Added Gemini Multimodal Live File API for uploading, fetching, listing, and
|
- Added Gemini Multimodal Live File API for uploading, fetching, listing, and
|
||||||
deleting files. See `26f-gemini-multimodal-live-files-api.py` for example usage.
|
deleting files. See `26f-gemini-multimodal-live-files-api.py` for example usage.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ deleting files. See `26f-gemini-multimodal-live-files-api.py` for example usage.
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed an issue where audio would get stuck in the queue when an interrupt occurs
|
- Fixed an issue where audio would get stuck in the queue when an interrupt occurs
|
||||||
during Azure TTS synthesis.
|
during Azure TTS synthesis.
|
||||||
|
|
||||||
- Fixed a race condition that occurs in Python 3.10+ where the task could miss
|
- Fixed a race condition that occurs in Python 3.10+ where the task could miss
|
||||||
@@ -83,6 +85,13 @@ deleting files. See `26f-gemini-multimodal-live-files-api.py` for example usage.
|
|||||||
|
|
||||||
- Fixed a `AWSNovaSonicLLMService` issue introduced in 0.0.72.
|
- Fixed a `AWSNovaSonicLLMService` issue introduced in 0.0.72.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
- 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
|
## [0.0.73] - 2025-06-26
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -58,12 +58,14 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
Parameters:
|
Parameters:
|
||||||
language: Language for synthesis. Defaults to English.
|
language: Language for synthesis. Defaults to English.
|
||||||
latency: Latency mode ("normal" or "balanced"). Defaults to "normal".
|
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_speed: Speech speed multiplier (0.5-2.0). Defaults to 1.0.
|
||||||
prosody_volume: Volume adjustment in dB. Defaults to 0.
|
prosody_volume: Volume adjustment in dB. Defaults to 0.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
language: Optional[Language] = Language.EN
|
language: Optional[Language] = Language.EN
|
||||||
latency: Optional[str] = "normal" # "normal" or "balanced"
|
latency: Optional[str] = "normal" # "normal" or "balanced"
|
||||||
|
normalize: Optional[bool] = True
|
||||||
prosody_speed: Optional[float] = 1.0 # Speech speed (0.5-2.0)
|
prosody_speed: Optional[float] = 1.0 # Speech speed (0.5-2.0)
|
||||||
prosody_volume: Optional[int] = 0 # Volume adjustment in dB
|
prosody_volume: Optional[int] = 0 # Volume adjustment in dB
|
||||||
|
|
||||||
@@ -71,7 +73,9 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
api_key: str,
|
api_key: str,
|
||||||
model: str, # This is the reference_id
|
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",
|
output_format: FishAudioOutputFormat = "pcm",
|
||||||
sample_rate: Optional[int] = None,
|
sample_rate: Optional[int] = None,
|
||||||
params: Optional[InputParams] = None,
|
params: Optional[InputParams] = None,
|
||||||
@@ -81,7 +85,14 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
api_key: Fish Audio API key for authentication.
|
api_key: Fish Audio API key for authentication.
|
||||||
model: Reference ID of the voice model to use for synthesis.
|
reference_id: Reference ID of the voice model to use for synthesis.
|
||||||
|
model: Deprecated. Reference ID of the voice model to use for synthesis.
|
||||||
|
|
||||||
|
.. deprecated:: 0.0.74
|
||||||
|
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".
|
output_format: Audio output format. Defaults to "pcm".
|
||||||
sample_rate: Audio sample rate. If None, uses default.
|
sample_rate: Audio sample rate. If None, uses default.
|
||||||
params: Additional input parameters for voice customization.
|
params: Additional input parameters for voice customization.
|
||||||
@@ -96,6 +107,26 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
|
|
||||||
params = params or FishAudioTTSService.InputParams()
|
params = params or FishAudioTTSService.InputParams()
|
||||||
|
|
||||||
|
# Validation for model and reference_id parameters
|
||||||
|
if model and reference_id:
|
||||||
|
raise ValueError(
|
||||||
|
"Cannot specify both 'model' and 'reference_id'. Use 'reference_id' only."
|
||||||
|
)
|
||||||
|
|
||||||
|
if model is None and reference_id is None:
|
||||||
|
raise ValueError("Must specify 'reference_id' (or deprecated 'model') parameter.")
|
||||||
|
|
||||||
|
if model:
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"Parameter 'model' is deprecated and will be removed in a future version. "
|
||||||
|
"Use 'reference_id' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
reference_id = model
|
||||||
|
|
||||||
self._api_key = api_key
|
self._api_key = api_key
|
||||||
self._base_url = "wss://api.fish.audio/v1/tts/live"
|
self._base_url = "wss://api.fish.audio/v1/tts/live"
|
||||||
self._websocket = None
|
self._websocket = None
|
||||||
@@ -107,14 +138,15 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
"sample_rate": 0,
|
"sample_rate": 0,
|
||||||
"latency": params.latency,
|
"latency": params.latency,
|
||||||
"format": output_format,
|
"format": output_format,
|
||||||
|
"normalize": params.normalize,
|
||||||
"prosody": {
|
"prosody": {
|
||||||
"speed": params.prosody_speed,
|
"speed": params.prosody_speed,
|
||||||
"volume": params.prosody_volume,
|
"volume": params.prosody_volume,
|
||||||
},
|
},
|
||||||
"reference_id": model,
|
"reference_id": reference_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_model_name(model)
|
self.set_model_name(model_id)
|
||||||
|
|
||||||
def can_generate_metrics(self) -> bool:
|
def can_generate_metrics(self) -> bool:
|
||||||
"""Check if this service can generate processing metrics.
|
"""Check if this service can generate processing metrics.
|
||||||
@@ -125,14 +157,15 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
async def set_model(self, model: str):
|
async def set_model(self, model: str):
|
||||||
"""Set the TTS model (reference ID).
|
"""Set the TTS model and reconnect.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
model: The reference ID of the voice model to use.
|
model: The model name to use for synthesis.
|
||||||
"""
|
"""
|
||||||
self._settings["reference_id"] = model
|
|
||||||
await super().set_model(model)
|
await super().set_model(model)
|
||||||
logger.info(f"Switching TTS model to: [{model}]")
|
logger.info(f"Switching TTS model to: [{model}]")
|
||||||
|
await self._disconnect()
|
||||||
|
await self._connect()
|
||||||
|
|
||||||
async def start(self, frame: StartFrame):
|
async def start(self, frame: StartFrame):
|
||||||
"""Start the Fish Audio TTS service.
|
"""Start the Fish Audio TTS service.
|
||||||
@@ -182,6 +215,7 @@ class FishAudioTTSService(InterruptibleTTSService):
|
|||||||
|
|
||||||
logger.debug("Connecting to Fish Audio")
|
logger.debug("Connecting to Fish Audio")
|
||||||
headers = {"Authorization": f"Bearer {self._api_key}"}
|
headers = {"Authorization": f"Bearer {self._api_key}"}
|
||||||
|
headers["model"] = self.model_name
|
||||||
self._websocket = await websockets.connect(self._base_url, extra_headers=headers)
|
self._websocket = await websockets.connect(self._base_url, extra_headers=headers)
|
||||||
|
|
||||||
# Send initial start message with ormsgpack
|
# Send initial start message with ormsgpack
|
||||||
|
|||||||
Reference in New Issue
Block a user