# # Copyright (c) 2024, Daily # # SPDX-License-Identifier: BSD 2-Clause License # import aiohttp from typing import AsyncGenerator from pipecat.frames.frames import AudioRawFrame, ErrorFrame, Frame from pipecat.services.ai_services import TTSService from loguru import logger class DeepgramTTSService(TTSService): def __init__( self, *, aiohttp_session: aiohttp.ClientSession, api_key: str, voice: str = "aura-helios-en", **kwargs): super().__init__(**kwargs) self._voice = voice self._api_key = api_key self._aiohttp_session = aiohttp_session def can_generate_metrics(self) -> bool: return True async def run_tts(self, text: str) -> AsyncGenerator[Frame, None]: logger.debug(f"Generating TTS: [{text}]") base_url = "https://api.deepgram.com/v1/speak" request_url = f"{base_url}?model={self._voice}&encoding=linear16&container=none&sample_rate=16000" headers = {"authorization": f"token {self._api_key}"} body = {"text": text} try: await self.start_ttfb_metrics() async with self._aiohttp_session.post(request_url, headers=headers, json=body) as r: if r.status != 200: text = await r.text() logger.error(f"Error getting audio (status: {r.status}, error: {text})") yield ErrorFrame(f"Error getting audio (status: {r.status}, error: {text})") return async for data in r.content: await self.stop_ttfb_metrics() frame = AudioRawFrame(audio=data, sample_rate=16000, num_channels=1) yield frame except Exception as e: logger.error(f"Deepgram exception: {e}")