Update CartesiaHttpTTSService to work with the new cartesia 2.0 client
This commit is contained in:
@@ -326,6 +326,7 @@ class CartesiaHttpTTSService(TTSService):
|
|||||||
voice_id: str,
|
voice_id: str,
|
||||||
model: str = "sonic-2",
|
model: str = "sonic-2",
|
||||||
base_url: str = "https://api.cartesia.ai",
|
base_url: str = "https://api.cartesia.ai",
|
||||||
|
cartesia_version: str = "2024-11-13",
|
||||||
sample_rate: Optional[int] = None,
|
sample_rate: Optional[int] = None,
|
||||||
encoding: str = "pcm_s16le",
|
encoding: str = "pcm_s16le",
|
||||||
container: str = "raw",
|
container: str = "raw",
|
||||||
@@ -335,6 +336,8 @@ class CartesiaHttpTTSService(TTSService):
|
|||||||
super().__init__(sample_rate=sample_rate, **kwargs)
|
super().__init__(sample_rate=sample_rate, **kwargs)
|
||||||
|
|
||||||
self._api_key = api_key
|
self._api_key = api_key
|
||||||
|
self._base_url = base_url
|
||||||
|
self._cartesia_version = cartesia_version
|
||||||
self._settings = {
|
self._settings = {
|
||||||
"output_format": {
|
"output_format": {
|
||||||
"container": container,
|
"container": container,
|
||||||
@@ -350,7 +353,10 @@ class CartesiaHttpTTSService(TTSService):
|
|||||||
self.set_voice(voice_id)
|
self.set_voice(voice_id)
|
||||||
self.set_model_name(model)
|
self.set_model_name(model)
|
||||||
|
|
||||||
self._client = AsyncCartesia(api_key=api_key, base_url=base_url)
|
self._client = AsyncCartesia(
|
||||||
|
api_key=api_key,
|
||||||
|
base_url=base_url,
|
||||||
|
)
|
||||||
|
|
||||||
def can_generate_metrics(self) -> bool:
|
def can_generate_metrics(self) -> bool:
|
||||||
return True
|
return True
|
||||||
@@ -375,45 +381,63 @@ class CartesiaHttpTTSService(TTSService):
|
|||||||
logger.debug(f"{self}: Generating TTS [{text}]")
|
logger.debug(f"{self}: Generating TTS [{text}]")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
voice_controls = None
|
voice_config = {"mode": "id", "id": self._voice_id}
|
||||||
|
|
||||||
if self._settings["emotion"]:
|
if self._settings["emotion"]:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"The 'emotion' parameter in _experimental_voice_controls is deprecated and will be removed in a future version.",
|
"The 'emotion' parameter in voice.__experimental_controls is deprecated and will be removed in a future version.",
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
voice_controls = {}
|
voice_config["__experimental_controls"] = {"emotion": self._settings["emotion"]}
|
||||||
if self._settings["emotion"]:
|
|
||||||
voice_controls["emotion"] = self._settings["emotion"]
|
|
||||||
|
|
||||||
await self.start_ttfb_metrics()
|
await self.start_ttfb_metrics()
|
||||||
|
|
||||||
kwargs = {
|
payload = {
|
||||||
"model_id": self._model_name,
|
"model_id": self._model_name,
|
||||||
"transcript": text,
|
"transcript": text,
|
||||||
"voice_id": self._voice_id,
|
"voice": voice_config,
|
||||||
"output_format": self._settings["output_format"],
|
"output_format": self._settings["output_format"],
|
||||||
"language": self._settings["language"],
|
"language": self._settings["language"],
|
||||||
"stream": False,
|
|
||||||
"_experimental_voice_controls": voice_controls,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self._settings["speed"]:
|
if self._settings["speed"]:
|
||||||
kwargs["speed"] = self._settings["speed"]
|
payload["speed"] = self._settings["speed"]
|
||||||
|
|
||||||
output = await self._client.tts.sse(**kwargs)
|
|
||||||
|
|
||||||
await self.start_tts_usage_metrics(text)
|
|
||||||
|
|
||||||
yield TTSStartedFrame()
|
yield TTSStartedFrame()
|
||||||
|
|
||||||
|
session = await self._client._get_session()
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Cartesia-Version": self._cartesia_version,
|
||||||
|
"X-API-Key": self._api_key,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
url = f"{self._base_url}/tts/bytes"
|
||||||
|
|
||||||
|
async with session.post(url, json=payload, headers=headers) as response:
|
||||||
|
if response.status != 200:
|
||||||
|
error_text = await response.text()
|
||||||
|
logger.error(f"Cartesia API error: {error_text}")
|
||||||
|
await self.push_error(ErrorFrame(f"Cartesia API error: {error_text}"))
|
||||||
|
raise Exception(f"Cartesia API returned status {response.status}: {error_text}")
|
||||||
|
|
||||||
|
audio_data = await response.read()
|
||||||
|
|
||||||
|
await self.start_tts_usage_metrics(text)
|
||||||
|
|
||||||
frame = TTSAudioRawFrame(
|
frame = TTSAudioRawFrame(
|
||||||
audio=output["audio"], sample_rate=self.sample_rate, num_channels=1
|
audio=audio_data,
|
||||||
|
sample_rate=self.sample_rate,
|
||||||
|
num_channels=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
yield frame
|
yield frame
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self} exception: {e}")
|
logger.error(f"{self} exception: {e}")
|
||||||
|
await self.push_error(ErrorFrame(f"Error generating TTS: {e}"))
|
||||||
finally:
|
finally:
|
||||||
await self.stop_ttfb_metrics()
|
await self.stop_ttfb_metrics()
|
||||||
yield TTSStoppedFrame()
|
yield TTSStoppedFrame()
|
||||||
|
|||||||
Reference in New Issue
Block a user