From dd1a1696eaedd56af7b75c58070daafb8e351f15 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 19 Jun 2026 12:59:36 +0530 Subject: [PATCH] chore: move from HTTP Service to Websocket Service --- api/services/pipecat/inworld_tts.py | 23 -------- api/services/pipecat/service_factory.py | 8 +-- api/tests/test_inworld_tts_service_factory.py | 54 +++++++++++++++++++ 3 files changed, 56 insertions(+), 29 deletions(-) delete mode 100644 api/services/pipecat/inworld_tts.py create mode 100644 api/tests/test_inworld_tts_service_factory.py diff --git a/api/services/pipecat/inworld_tts.py b/api/services/pipecat/inworld_tts.py deleted file mode 100644 index 42558ea4..00000000 --- a/api/services/pipecat/inworld_tts.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Inworld TTS wrapper that closes its aiohttp session in cleanup(). - -Pipecat's InworldHttpTTSService leaves session disposal to the caller. Our -factory creates a fresh session per service instance, so we own its close here -to avoid leaking sockets/FDs on shutdown. -""" - -import aiohttp - -from pipecat.services.inworld.tts import InworldHttpTTSService - - -class InworldOwnedSessionTTSService(InworldHttpTTSService): - """InworldHttpTTSService variant that owns its aiohttp session lifecycle.""" - - def __init__(self, *args, aiohttp_session: aiohttp.ClientSession, **kwargs): - super().__init__(*args, aiohttp_session=aiohttp_session, **kwargs) - self._owned_session = aiohttp_session - - async def cleanup(self): - await super().cleanup() - if not self._owned_session.closed: - await self._owned_session.close() diff --git a/api/services/pipecat/service_factory.py b/api/services/pipecat/service_factory.py index 48d89468..b7f64295 100644 --- a/api/services/pipecat/service_factory.py +++ b/api/services/pipecat/service_factory.py @@ -8,7 +8,6 @@ from loguru import logger from api.constants import MPS_API_URL from api.services.configuration.options import DEEPGRAM_FLUX_MODELS from api.services.configuration.registry import ServiceProviders -from api.services.pipecat.inworld_tts import InworldOwnedSessionTTSService from api.services.pipecat.minimax_tts import MiniMaxOwnedSessionTTSService from api.utils.url_security import validate_user_configured_service_url from pipecat.services.assemblyai.stt import AssemblyAISTTService, AssemblyAISTTSettings @@ -49,7 +48,7 @@ from pipecat.services.huggingface.stt import ( HuggingFaceSTTService, HuggingFaceSTTSettings, ) -from pipecat.services.inworld.tts import InworldTTSSettings +from pipecat.services.inworld.tts import InworldTTSService, InworldTTSSettings from pipecat.services.minimax.llm import MiniMaxLLMService from pipecat.services.minimax.tts import MiniMaxTTSSettings from pipecat.services.openai._constants import OPENAI_SAMPLE_RATE @@ -477,11 +476,8 @@ def create_tts_service( speed = getattr(user_config.tts, "speed", None) language = getattr(user_config.tts, "language", None) or "en-US" delivery_mode = getattr(user_config.tts, "delivery_mode", None) or "BALANCED" - session = aiohttp.ClientSession() - return InworldOwnedSessionTTSService( + return InworldTTSService( api_key=user_config.tts.api_key, - aiohttp_session=session, - streaming=True, settings=InworldTTSSettings( voice=voice, model=model, diff --git a/api/tests/test_inworld_tts_service_factory.py b/api/tests/test_inworld_tts_service_factory.py new file mode 100644 index 00000000..f2d063d7 --- /dev/null +++ b/api/tests/test_inworld_tts_service_factory.py @@ -0,0 +1,54 @@ +from types import SimpleNamespace +from unittest.mock import patch + +from api.services.configuration.registry import ( + InworldTTSConfiguration, + ServiceProviders, +) +from api.services.pipecat.service_factory import create_tts_service + + +def test_inworld_tts_configuration_defaults(): + config = InworldTTSConfiguration(api_key="test-key") + + assert config.provider == ServiceProviders.INWORLD + assert config.model == "inworld-tts-2" + assert config.voice == "Ashley" + assert config.language == "en-US" + assert config.delivery_mode == "BALANCED" + + +def test_create_inworld_tts_service_uses_websocket_service_without_http_session(): + user_config = SimpleNamespace( + tts=SimpleNamespace( + provider=ServiceProviders.INWORLD.value, + api_key="test-key", + model="inworld-tts-2", + voice="Ashley", + speed=1.1, + language="en-US", + delivery_mode="CREATIVE", + ) + ) + audio_config = SimpleNamespace( + transport_out_sample_rate=24000, + transport_in_sample_rate=16000, + ) + + with ( + patch("api.services.pipecat.service_factory.aiohttp.ClientSession") as session, + patch("api.services.pipecat.service_factory.InworldTTSService") as mock_service, + ): + create_tts_service(user_config, audio_config) + + session.assert_not_called() + assert mock_service.call_count == 1 + kwargs = mock_service.call_args.kwargs + assert kwargs["api_key"] == "test-key" + assert "aiohttp_session" not in kwargs + assert "streaming" not in kwargs + assert kwargs["settings"].model == "inworld-tts-2" + assert kwargs["settings"].voice == "Ashley" + assert kwargs["settings"].language == "en-US" + assert kwargs["settings"].speaking_rate == 1.1 + assert kwargs["settings"].delivery_mode == "CREATIVE"