Merge pull request #2168 from pipecat-ai/mb/fix-neuophonic-tts

Fix: NeuphonicTTSService to use latest websocket API
This commit is contained in:
Mark Backman
2025-07-08 11:17:58 -07:00
committed by GitHub
2 changed files with 22 additions and 7 deletions

View File

@@ -33,6 +33,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`UserIdleProcessor` in conjunction with function calls that take a while to
return a result.
### Fixed
- Updated the `NeuphonicTTSService` to work with the updated websocket API.
### Performance
- Remove unncessary push task in each `FrameProcessor`.

View File

@@ -106,7 +106,7 @@ class NeuphonicTTSService(InterruptibleTTSService):
*,
api_key: str,
voice_id: Optional[str] = None,
url: str = "wss://api.neuphonic.com",
url: str = "wss://eu-west-1.api.neuphonic.com",
sample_rate: Optional[int] = 22050,
encoding: str = "pcm_linear",
params: Optional[InputParams] = None,
@@ -281,14 +281,18 @@ class NeuphonicTTSService(InterruptibleTTSService):
"voice_id": self._voice_id,
}
query_params = [f"api_key={self._api_key}"]
query_params = []
for key, value in tts_config.items():
if value is not None:
query_params.append(f"{key}={value}")
url = f"{self._url}/speak/{self._settings['lang_code']}?{'&'.join(query_params)}"
url = f"{self._url}/speak/{self._settings['lang_code']}"
if query_params:
url += f"?{'&'.join(query_params)}"
self._websocket = await websockets.connect(url)
headers = {"x-api-key": self._api_key}
self._websocket = await websockets.connect(url, extra_headers=headers)
except Exception as e:
logger.error(f"{self} initialization error: {e}")
self._websocket = None
@@ -313,7 +317,7 @@ class NeuphonicTTSService(InterruptibleTTSService):
async for message in WatchdogAsyncIterator(self._websocket, manager=self.task_manager):
if isinstance(message, str):
msg = json.loads(message)
if msg.get("data", {}).get("audio") is not None:
if msg.get("data") and msg["data"].get("audio"):
await self.stop_ttfb_metrics()
audio = base64.b64decode(msg["data"]["audio"])
@@ -326,12 +330,19 @@ class NeuphonicTTSService(InterruptibleTTSService):
while True:
self.reset_watchdog()
await asyncio.sleep(KEEPALIVE_SLEEP)
await self._send_text("")
await self._send_keepalive()
async def _send_keepalive(self):
"""Send keepalive message to maintain connection."""
if self._websocket:
# Send empty text for keepalive
msg = {"text": ""}
await self._websocket.send(json.dumps(msg))
async def _send_text(self, text: str):
"""Send text to Neuphonic WebSocket for synthesis."""
if self._websocket:
msg = {"text": text}
msg = {"text": f"{text} <STOP>"}
logger.debug(f"Sending text to websocket: {msg}")
await self._websocket.send(json.dumps(msg))