From df8aa3e4b0621461b808f873c6f6590eced75bae Mon Sep 17 00:00:00 2001 From: Roshan Date: Tue, 28 Oct 2025 15:10:46 -0700 Subject: [PATCH 1/4] feat: add generation_config support for Cartesia Sonic-3 Add GenerationConfig dataclass with volume, speed, and emotion parameters for Cartesia Sonic-3 TTS models. This enables fine-grained control over speech generation including volume (0.5-2.0), speed (0.6-1.5), and emotion (60+ options). Changes: - Add GenerationConfig dataclass with proper Google-style docstrings - Update CartesiaTTSService.InputParams to include generation_config - Update CartesiaHttpTTSService.InputParams to include generation_config - Modify _build_msg() to include generation_config in WebSocket messages - Modify run_tts() to include generation_config in HTTP requests - Maintain backward compatibility with existing speed and emotion parameters The legacy speed (literal strings) and emotion (list) parameters remain available for non-Sonic-3 models. --- src/pipecat/services/cartesia/tts.py | 60 ++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/src/pipecat/services/cartesia/tts.py b/src/pipecat/services/cartesia/tts.py index 3c0fe279c..9b5d7b0ac 100644 --- a/src/pipecat/services/cartesia/tts.py +++ b/src/pipecat/services/cartesia/tts.py @@ -10,6 +10,7 @@ import base64 import json import uuid import warnings +from dataclasses import dataclass from typing import AsyncGenerator, List, Literal, Optional, Union from loguru import logger @@ -48,6 +49,27 @@ except ModuleNotFoundError as e: raise Exception(f"Missing module: {e}") +@dataclass +class GenerationConfig: + """Configuration for Cartesia Sonic-3 generation parameters. + + Sonic-3 interprets these parameters as guidance to ensure natural speech. + Test against your content for best results. + + Parameters: + volume: Volume multiplier for generated speech. Valid range: [0.5, 2.0]. Default is 1.0. + speed: Speed multiplier for generated speech. Valid range: [0.6, 1.5]. Default is 1.0. + emotion: Single emotion string to guide the emotional tone. Examples include neutral, + angry, excited, content, sad, scared. Over 60 emotions are supported. For best + results, use with recommended voices: Leo, Jace, Kyle, Gavin, Maya, Tessa, Dana, + and Marian. + """ + + volume: Optional[float] = None + speed: Optional[float] = None + emotion: Optional[str] = None + + def language_to_cartesia_language(language: Language) -> Optional[str]: """Convert a Language enum to Cartesia language code. @@ -101,16 +123,19 @@ class CartesiaTTSService(AudioContextWordTTSService): Parameters: language: Language to use for synthesis. - speed: Voice speed control. - emotion: List of emotion controls. + speed: Voice speed control for non-Sonic-3 models (literal values). + emotion: List of emotion controls for non-Sonic-3 models. .. deprecated:: 0.0.68 The `emotion` parameter is deprecated and will be removed in a future version. + generation_config: Generation configuration for Sonic-3 models. Includes volume, + speed (numeric), and emotion (string) parameters. """ language: Optional[Language] = Language.EN speed: Optional[Literal["slow", "normal", "fast"]] = None emotion: Optional[List[str]] = [] + generation_config: Optional[GenerationConfig] = None def __init__( self, @@ -179,6 +204,7 @@ class CartesiaTTSService(AudioContextWordTTSService): else "en", "speed": params.speed, "emotion": params.emotion, + "generation_config": params.generation_config, } self.set_model_name(model) self.set_voice(voice_id) @@ -297,6 +323,17 @@ class CartesiaTTSService(AudioContextWordTTSService): if self._settings["speed"]: msg["speed"] = self._settings["speed"] + if self._settings["generation_config"]: + gen_config = {} + if self._settings["generation_config"].volume is not None: + gen_config["volume"] = self._settings["generation_config"].volume + if self._settings["generation_config"].speed is not None: + gen_config["speed"] = self._settings["generation_config"].speed + if self._settings["generation_config"].emotion is not None: + gen_config["emotion"] = self._settings["generation_config"].emotion + if gen_config: + msg["generation_config"] = gen_config + return json.dumps(msg) async def start(self, frame: StartFrame): @@ -482,16 +519,19 @@ class CartesiaHttpTTSService(TTSService): Parameters: language: Language to use for synthesis. - speed: Voice speed control. - emotion: List of emotion controls. + speed: Voice speed control for non-Sonic-3 models (literal values). + emotion: List of emotion controls for non-Sonic-3 models. .. deprecated:: 0.0.68 The `emotion` parameter is deprecated and will be removed in a future version. + generation_config: Generation configuration for Sonic-3 models. Includes volume, + speed (numeric), and emotion (string) parameters. """ language: Optional[Language] = Language.EN speed: Optional[Literal["slow", "normal", "fast"]] = None emotion: Optional[List[str]] = Field(default_factory=list) + generation_config: Optional[GenerationConfig] = None def __init__( self, @@ -539,6 +579,7 @@ class CartesiaHttpTTSService(TTSService): else "en", "speed": params.speed, "emotion": params.emotion, + "generation_config": params.generation_config, } self.set_voice(voice_id) self.set_model_name(model) @@ -632,6 +673,17 @@ class CartesiaHttpTTSService(TTSService): if self._settings["speed"]: payload["speed"] = self._settings["speed"] + if self._settings["generation_config"]: + gen_config = {} + if self._settings["generation_config"].volume is not None: + gen_config["volume"] = self._settings["generation_config"].volume + if self._settings["generation_config"].speed is not None: + gen_config["speed"] = self._settings["generation_config"].speed + if self._settings["generation_config"].emotion is not None: + gen_config["emotion"] = self._settings["generation_config"].emotion + if gen_config: + payload["generation_config"] = gen_config + yield TTSStartedFrame() session = await self._client._get_session() From 408264a0fd0002c585a56a989e43560b3a4ff870 Mon Sep 17 00:00:00 2001 From: Roshan Date: Tue, 28 Oct 2025 15:16:49 -0700 Subject: [PATCH 2/4] docs: update CHANGELOG.md for generation_config feature --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c76d57d13..7c6928867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added `generation_config` parameter support to `CartesiaTTSService` and + `CartesiaHttpTTSService` for Cartesia Sonic-3 models. Includes a new + `GenerationConfig` dataclass with `volume` (0.5-2.0), `speed` (0.6-1.5), + and `emotion` (60+ options) parameters for fine-grained speech generation + control. + ### Changed - Updated the default model to `sonic-3` for `CartesiaTTSService` and From b0f5fc02c406c477185c0defc250fe50c109170f Mon Sep 17 00:00:00 2001 From: Roshan Date: Tue, 28 Oct 2025 18:41:58 -0700 Subject: [PATCH 3/4] refactor: use Pydantic BaseModel for GenerationConfig and simplify model_dump() - Change GenerationConfig from dataclass to Pydantic BaseModel for consistency - Simplify _build_msg() to use model_dump(exclude_none=True) instead of manual field extraction - Simplify HTTP run_tts() to use model_dump(exclude_none=True) instead of manual field extraction This addresses feedback from code review and reduces code duplication. --- src/pipecat/services/cartesia/tts.py | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/pipecat/services/cartesia/tts.py b/src/pipecat/services/cartesia/tts.py index 9b5d7b0ac..4e785a374 100644 --- a/src/pipecat/services/cartesia/tts.py +++ b/src/pipecat/services/cartesia/tts.py @@ -10,7 +10,6 @@ import base64 import json import uuid import warnings -from dataclasses import dataclass from typing import AsyncGenerator, List, Literal, Optional, Union from loguru import logger @@ -49,8 +48,7 @@ except ModuleNotFoundError as e: raise Exception(f"Missing module: {e}") -@dataclass -class GenerationConfig: +class GenerationConfig(BaseModel): """Configuration for Cartesia Sonic-3 generation parameters. Sonic-3 interprets these parameters as guidance to ensure natural speech. @@ -324,15 +322,7 @@ class CartesiaTTSService(AudioContextWordTTSService): msg["speed"] = self._settings["speed"] if self._settings["generation_config"]: - gen_config = {} - if self._settings["generation_config"].volume is not None: - gen_config["volume"] = self._settings["generation_config"].volume - if self._settings["generation_config"].speed is not None: - gen_config["speed"] = self._settings["generation_config"].speed - if self._settings["generation_config"].emotion is not None: - gen_config["emotion"] = self._settings["generation_config"].emotion - if gen_config: - msg["generation_config"] = gen_config + msg["generation_config"] = self._settings["generation_config"].model_dump(exclude_none=True) return json.dumps(msg) @@ -674,15 +664,7 @@ class CartesiaHttpTTSService(TTSService): payload["speed"] = self._settings["speed"] if self._settings["generation_config"]: - gen_config = {} - if self._settings["generation_config"].volume is not None: - gen_config["volume"] = self._settings["generation_config"].volume - if self._settings["generation_config"].speed is not None: - gen_config["speed"] = self._settings["generation_config"].speed - if self._settings["generation_config"].emotion is not None: - gen_config["emotion"] = self._settings["generation_config"].emotion - if gen_config: - payload["generation_config"] = gen_config + payload["generation_config"] = self._settings["generation_config"].model_dump(exclude_none=True) yield TTSStartedFrame() From abf34bcccfab15d329dca5c46c05539aa3cb76de Mon Sep 17 00:00:00 2001 From: Roshan Date: Wed, 29 Oct 2025 18:29:51 -0700 Subject: [PATCH 4/4] address pr comments --- CHANGELOG.md | 2 +- src/pipecat/services/cartesia/tts.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c6928867..daeae5d61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `generation_config` parameter support to `CartesiaTTSService` and `CartesiaHttpTTSService` for Cartesia Sonic-3 models. Includes a new - `GenerationConfig` dataclass with `volume` (0.5-2.0), `speed` (0.6-1.5), + `GenerationConfig` class with `volume` (0.5-2.0), `speed` (0.6-1.5), and `emotion` (60+ options) parameters for fine-grained speech generation control. diff --git a/src/pipecat/services/cartesia/tts.py b/src/pipecat/services/cartesia/tts.py index 4e785a374..c2185a355 100644 --- a/src/pipecat/services/cartesia/tts.py +++ b/src/pipecat/services/cartesia/tts.py @@ -126,6 +126,7 @@ class CartesiaTTSService(AudioContextWordTTSService): .. deprecated:: 0.0.68 The `emotion` parameter is deprecated and will be removed in a future version. + generation_config: Generation configuration for Sonic-3 models. Includes volume, speed (numeric), and emotion (string) parameters. """ @@ -322,7 +323,9 @@ class CartesiaTTSService(AudioContextWordTTSService): msg["speed"] = self._settings["speed"] if self._settings["generation_config"]: - msg["generation_config"] = self._settings["generation_config"].model_dump(exclude_none=True) + msg["generation_config"] = self._settings["generation_config"].model_dump( + exclude_none=True + ) return json.dumps(msg) @@ -514,6 +517,7 @@ class CartesiaHttpTTSService(TTSService): .. deprecated:: 0.0.68 The `emotion` parameter is deprecated and will be removed in a future version. + generation_config: Generation configuration for Sonic-3 models. Includes volume, speed (numeric), and emotion (string) parameters. """ @@ -664,7 +668,9 @@ class CartesiaHttpTTSService(TTSService): payload["speed"] = self._settings["speed"] if self._settings["generation_config"]: - payload["generation_config"] = self._settings["generation_config"].model_dump(exclude_none=True) + payload["generation_config"] = self._settings["generation_config"].model_dump( + exclude_none=True + ) yield TTSStartedFrame()