diff --git a/CHANGELOG.md b/CHANGELOG.md index a552daed8..46a4082eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed an issue in the `BaseOutputTransport`, mainly reproducible with + `FastAPIWebsocketOutputTransport` when the audio mixer was enabled, where the + loop could consume 100% CPU by continuously returning without delay, preventing + other asyncio tasks (such as cancellation or shutdown signals) from being + processed. + - Fixed an issue where `BotStartedSpeakingFrame` and `BotStoppedSpeakingFrame` were not emitted when using `TavusVideoService` or `HeyGenVideoService`. diff --git a/src/pipecat/transports/base_output.py b/src/pipecat/transports/base_output.py index 313c36fc0..9c2da1d22 100644 --- a/src/pipecat/transports/base_output.py +++ b/src/pipecat/transports/base_output.py @@ -658,6 +658,11 @@ class BaseOutputTransport(FrameProcessor): num_channels=self._params.audio_out_channels, ) yield frame + # Allow other asyncio tasks to execute by adding a small sleep + # Without this sleep, in task cancellation scenarios, this loop would + # continuously return without any delay, leading to 100% CPU utilization + # and preventing cancel/stop signals from being processed properly + await asyncio.sleep(0) if self._mixer: return with_mixer(BOT_VAD_STOP_SECS) diff --git a/src/pipecat/transports/network/fastapi_websocket.py b/src/pipecat/transports/network/fastapi_websocket.py index a256134a7..d3e3362b4 100644 --- a/src/pipecat/transports/network/fastapi_websocket.py +++ b/src/pipecat/transports/network/fastapi_websocket.py @@ -419,12 +419,7 @@ class FastAPIWebsocketOutputTransport(BaseOutputTransport): Args: frame: The output audio frame to write. """ - if self._client.is_closing: - return - - if not self._client.is_connected: - # Simulate audio playback with a sleep. - await self._write_audio_sleep() + if self._client.is_closing or not self._client.is_connected: return frame = OutputAudioRawFrame( diff --git a/src/pipecat/transports/network/websocket_server.py b/src/pipecat/transports/network/websocket_server.py index e957b01be..ffeee5338 100644 --- a/src/pipecat/transports/network/websocket_server.py +++ b/src/pipecat/transports/network/websocket_server.py @@ -353,8 +353,6 @@ class WebsocketServerOutputTransport(BaseOutputTransport): frame: The output audio frame to write. """ if not self._websocket: - # Simulate audio playback with a sleep. - await self._write_audio_sleep() return frame = OutputAudioRawFrame(