diff --git a/CHANGELOG.md b/CHANGELOG.md index 87187becc..e6fba5eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Added `HumeTTSService` for text-to-speech synthesis using Hume AI's expressive voice models. - Provides high-quality, emotionally expressive speech synthesis with support for various voice models. - Includes example in `examples/foundational/07ad-interruptible-hume.py`. +- Added `HumeTTSService` for text-to-speech synthesis using Hume AI's + expressive voice models. Provides high-quality, emotionally expressive speech + synthesis with support for various voice models. Includes example in + `examples/foundational/07ad-interruptible-hume.py`. - Added `hume` optional dependency group for Hume AI TTS integration. diff --git a/examples/foundational/07ae-interruptible-hume.py b/examples/foundational/07ae-interruptible-hume.py index 91f680ddf..fbcccadd8 100644 --- a/examples/foundational/07ae-interruptible-hume.py +++ b/examples/foundational/07ae-interruptible-hume.py @@ -7,7 +7,12 @@ import os from dotenv import load_dotenv +from loguru import logger +from pipecat.audio.turn.smart_turn.base_smart_turn import SmartTurnParams +from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3 +from pipecat.audio.vad.silero import SileroVADAnalyzer +from pipecat.audio.vad.vad_analyzer import VADParams from pipecat.frames.frames import LLMRunFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner @@ -32,14 +37,21 @@ transport_params = { "daily": lambda: DailyParams( audio_in_enabled=True, audio_out_enabled=True, - vad_analyzer=SileroVADAnalyzer(), + vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.2)), + turn_analyzer=LocalSmartTurnAnalyzerV3(params=SmartTurnParams()), ), "twilio": lambda: FastAPIWebsocketParams( audio_in_enabled=True, audio_out_enabled=True, - vad_analyzer=SileroVADAnalyzer(), + vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.2)), + turn_analyzer=LocalSmartTurnAnalyzerV3(params=SmartTurnParams()), + ), + "webrtc": lambda: TransportParams( + audio_in_enabled=True, + audio_out_enabled=True, + vad_analyzer=SileroVADAnalyzer(params=VADParams(stop_secs=0.2)), + turn_analyzer=LocalSmartTurnAnalyzerV3(params=SmartTurnParams()), ), - "webrtc": lambda: TransportParams(), } @@ -108,7 +120,6 @@ async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): async def bot(runner_args: RunnerArguments): """Main bot entry point compatible with Pipecat Cloud.""" transport = await create_transport(runner_args, transport_params) - await run_bot(transport, runner_args) diff --git a/src/pipecat/services/hume/tts.py b/src/pipecat/services/hume/tts.py index 94c71bd0a..0629a8909 100644 --- a/src/pipecat/services/hume/tts.py +++ b/src/pipecat/services/hume/tts.py @@ -201,12 +201,20 @@ class HumeTTSService(TTSService): if len(self._audio_bytes) < self.chunk_size: continue - yield TTSAudioRawFrame(self._audio_bytes, self.sample_rate, 1) + frame = TTSAudioRawFrame( + audio=self._audio_bytes, + sample_rate=self.sample_rate, + num_channels=1, + ) + + yield frame + self._audio_bytes = b"" except Exception as e: logger.exception(f"{self} error generating TTS: {e}") - yield ErrorFrame(error=str(e)) + await self.push_error(ErrorFrame(f"Error generating TTS: {e}")) finally: # Ensure TTFB timer is stopped even on early failures + await self.stop_ttfb_metrics() yield TTSStoppedFrame()