dv-pipecat-ai 0.0.74.dev770__py3-none-any.whl → 0.0.82.dev776__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dv-pipecat-ai might be problematic. Click here for more details.

Files changed (244) hide show
  1. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/METADATA +137 -93
  2. dv_pipecat_ai-0.0.82.dev776.dist-info/RECORD +340 -0
  3. pipecat/__init__.py +17 -0
  4. pipecat/adapters/base_llm_adapter.py +36 -1
  5. pipecat/adapters/schemas/direct_function.py +296 -0
  6. pipecat/adapters/schemas/function_schema.py +15 -6
  7. pipecat/adapters/schemas/tools_schema.py +55 -7
  8. pipecat/adapters/services/anthropic_adapter.py +22 -3
  9. pipecat/adapters/services/aws_nova_sonic_adapter.py +23 -3
  10. pipecat/adapters/services/bedrock_adapter.py +22 -3
  11. pipecat/adapters/services/gemini_adapter.py +16 -3
  12. pipecat/adapters/services/open_ai_adapter.py +17 -2
  13. pipecat/adapters/services/open_ai_realtime_adapter.py +23 -3
  14. pipecat/audio/filters/base_audio_filter.py +30 -6
  15. pipecat/audio/filters/koala_filter.py +37 -2
  16. pipecat/audio/filters/krisp_filter.py +59 -6
  17. pipecat/audio/filters/noisereduce_filter.py +37 -0
  18. pipecat/audio/interruptions/base_interruption_strategy.py +25 -5
  19. pipecat/audio/interruptions/min_words_interruption_strategy.py +21 -4
  20. pipecat/audio/mixers/base_audio_mixer.py +30 -7
  21. pipecat/audio/mixers/soundfile_mixer.py +53 -6
  22. pipecat/audio/resamplers/base_audio_resampler.py +17 -9
  23. pipecat/audio/resamplers/resampy_resampler.py +26 -1
  24. pipecat/audio/resamplers/soxr_resampler.py +32 -1
  25. pipecat/audio/resamplers/soxr_stream_resampler.py +101 -0
  26. pipecat/audio/utils.py +194 -1
  27. pipecat/audio/vad/silero.py +60 -3
  28. pipecat/audio/vad/vad_analyzer.py +114 -30
  29. pipecat/clocks/base_clock.py +19 -0
  30. pipecat/clocks/system_clock.py +25 -0
  31. pipecat/extensions/voicemail/__init__.py +0 -0
  32. pipecat/extensions/voicemail/voicemail_detector.py +707 -0
  33. pipecat/frames/frames.py +590 -156
  34. pipecat/metrics/metrics.py +64 -1
  35. pipecat/observers/base_observer.py +58 -19
  36. pipecat/observers/loggers/debug_log_observer.py +56 -64
  37. pipecat/observers/loggers/llm_log_observer.py +8 -1
  38. pipecat/observers/loggers/transcription_log_observer.py +19 -7
  39. pipecat/observers/loggers/user_bot_latency_log_observer.py +32 -5
  40. pipecat/observers/turn_tracking_observer.py +26 -1
  41. pipecat/pipeline/base_pipeline.py +5 -7
  42. pipecat/pipeline/base_task.py +52 -9
  43. pipecat/pipeline/parallel_pipeline.py +121 -177
  44. pipecat/pipeline/pipeline.py +129 -20
  45. pipecat/pipeline/runner.py +50 -1
  46. pipecat/pipeline/sync_parallel_pipeline.py +132 -32
  47. pipecat/pipeline/task.py +263 -280
  48. pipecat/pipeline/task_observer.py +85 -34
  49. pipecat/pipeline/to_be_updated/merge_pipeline.py +32 -2
  50. pipecat/processors/aggregators/dtmf_aggregator.py +29 -22
  51. pipecat/processors/aggregators/gated.py +25 -24
  52. pipecat/processors/aggregators/gated_openai_llm_context.py +22 -2
  53. pipecat/processors/aggregators/llm_response.py +398 -89
  54. pipecat/processors/aggregators/openai_llm_context.py +161 -13
  55. pipecat/processors/aggregators/sentence.py +25 -14
  56. pipecat/processors/aggregators/user_response.py +28 -3
  57. pipecat/processors/aggregators/vision_image_frame.py +24 -14
  58. pipecat/processors/async_generator.py +28 -0
  59. pipecat/processors/audio/audio_buffer_processor.py +78 -37
  60. pipecat/processors/consumer_processor.py +25 -6
  61. pipecat/processors/filters/frame_filter.py +23 -0
  62. pipecat/processors/filters/function_filter.py +30 -0
  63. pipecat/processors/filters/identity_filter.py +17 -2
  64. pipecat/processors/filters/null_filter.py +24 -1
  65. pipecat/processors/filters/stt_mute_filter.py +56 -21
  66. pipecat/processors/filters/wake_check_filter.py +46 -3
  67. pipecat/processors/filters/wake_notifier_filter.py +21 -3
  68. pipecat/processors/frame_processor.py +488 -131
  69. pipecat/processors/frameworks/langchain.py +38 -3
  70. pipecat/processors/frameworks/rtvi.py +719 -34
  71. pipecat/processors/gstreamer/pipeline_source.py +41 -0
  72. pipecat/processors/idle_frame_processor.py +26 -3
  73. pipecat/processors/logger.py +23 -0
  74. pipecat/processors/metrics/frame_processor_metrics.py +77 -4
  75. pipecat/processors/metrics/sentry.py +42 -4
  76. pipecat/processors/producer_processor.py +34 -14
  77. pipecat/processors/text_transformer.py +22 -10
  78. pipecat/processors/transcript_processor.py +48 -29
  79. pipecat/processors/user_idle_processor.py +31 -21
  80. pipecat/runner/__init__.py +1 -0
  81. pipecat/runner/daily.py +132 -0
  82. pipecat/runner/livekit.py +148 -0
  83. pipecat/runner/run.py +543 -0
  84. pipecat/runner/types.py +67 -0
  85. pipecat/runner/utils.py +515 -0
  86. pipecat/serializers/base_serializer.py +42 -0
  87. pipecat/serializers/exotel.py +17 -6
  88. pipecat/serializers/genesys.py +95 -0
  89. pipecat/serializers/livekit.py +33 -0
  90. pipecat/serializers/plivo.py +16 -15
  91. pipecat/serializers/protobuf.py +37 -1
  92. pipecat/serializers/telnyx.py +18 -17
  93. pipecat/serializers/twilio.py +32 -16
  94. pipecat/services/ai_service.py +5 -3
  95. pipecat/services/anthropic/llm.py +113 -43
  96. pipecat/services/assemblyai/models.py +63 -5
  97. pipecat/services/assemblyai/stt.py +64 -11
  98. pipecat/services/asyncai/__init__.py +0 -0
  99. pipecat/services/asyncai/tts.py +501 -0
  100. pipecat/services/aws/llm.py +185 -111
  101. pipecat/services/aws/stt.py +217 -23
  102. pipecat/services/aws/tts.py +118 -52
  103. pipecat/services/aws/utils.py +101 -5
  104. pipecat/services/aws_nova_sonic/aws.py +82 -64
  105. pipecat/services/aws_nova_sonic/context.py +15 -6
  106. pipecat/services/azure/common.py +10 -2
  107. pipecat/services/azure/image.py +32 -0
  108. pipecat/services/azure/llm.py +9 -7
  109. pipecat/services/azure/stt.py +65 -2
  110. pipecat/services/azure/tts.py +154 -23
  111. pipecat/services/cartesia/stt.py +125 -8
  112. pipecat/services/cartesia/tts.py +102 -38
  113. pipecat/services/cerebras/llm.py +15 -23
  114. pipecat/services/deepgram/stt.py +19 -11
  115. pipecat/services/deepgram/tts.py +36 -0
  116. pipecat/services/deepseek/llm.py +14 -23
  117. pipecat/services/elevenlabs/tts.py +330 -64
  118. pipecat/services/fal/image.py +43 -0
  119. pipecat/services/fal/stt.py +48 -10
  120. pipecat/services/fireworks/llm.py +14 -21
  121. pipecat/services/fish/tts.py +109 -9
  122. pipecat/services/gemini_multimodal_live/__init__.py +1 -0
  123. pipecat/services/gemini_multimodal_live/events.py +83 -2
  124. pipecat/services/gemini_multimodal_live/file_api.py +189 -0
  125. pipecat/services/gemini_multimodal_live/gemini.py +218 -21
  126. pipecat/services/gladia/config.py +17 -10
  127. pipecat/services/gladia/stt.py +82 -36
  128. pipecat/services/google/frames.py +40 -0
  129. pipecat/services/google/google.py +2 -0
  130. pipecat/services/google/image.py +39 -2
  131. pipecat/services/google/llm.py +176 -58
  132. pipecat/services/google/llm_openai.py +26 -4
  133. pipecat/services/google/llm_vertex.py +37 -15
  134. pipecat/services/google/rtvi.py +41 -0
  135. pipecat/services/google/stt.py +65 -17
  136. pipecat/services/google/test-google-chirp.py +45 -0
  137. pipecat/services/google/tts.py +390 -19
  138. pipecat/services/grok/llm.py +8 -6
  139. pipecat/services/groq/llm.py +8 -6
  140. pipecat/services/groq/stt.py +13 -9
  141. pipecat/services/groq/tts.py +40 -0
  142. pipecat/services/hamsa/__init__.py +9 -0
  143. pipecat/services/hamsa/stt.py +241 -0
  144. pipecat/services/heygen/__init__.py +5 -0
  145. pipecat/services/heygen/api.py +281 -0
  146. pipecat/services/heygen/client.py +620 -0
  147. pipecat/services/heygen/video.py +338 -0
  148. pipecat/services/image_service.py +5 -3
  149. pipecat/services/inworld/__init__.py +1 -0
  150. pipecat/services/inworld/tts.py +592 -0
  151. pipecat/services/llm_service.py +127 -45
  152. pipecat/services/lmnt/tts.py +80 -7
  153. pipecat/services/mcp_service.py +85 -44
  154. pipecat/services/mem0/memory.py +42 -13
  155. pipecat/services/minimax/tts.py +74 -15
  156. pipecat/services/mistral/__init__.py +0 -0
  157. pipecat/services/mistral/llm.py +185 -0
  158. pipecat/services/moondream/vision.py +55 -10
  159. pipecat/services/neuphonic/tts.py +275 -48
  160. pipecat/services/nim/llm.py +8 -6
  161. pipecat/services/ollama/llm.py +27 -7
  162. pipecat/services/openai/base_llm.py +54 -16
  163. pipecat/services/openai/image.py +30 -0
  164. pipecat/services/openai/llm.py +7 -5
  165. pipecat/services/openai/stt.py +13 -9
  166. pipecat/services/openai/tts.py +42 -10
  167. pipecat/services/openai_realtime_beta/azure.py +11 -9
  168. pipecat/services/openai_realtime_beta/context.py +7 -5
  169. pipecat/services/openai_realtime_beta/events.py +10 -7
  170. pipecat/services/openai_realtime_beta/openai.py +37 -18
  171. pipecat/services/openpipe/llm.py +30 -24
  172. pipecat/services/openrouter/llm.py +9 -7
  173. pipecat/services/perplexity/llm.py +15 -19
  174. pipecat/services/piper/tts.py +26 -12
  175. pipecat/services/playht/tts.py +227 -65
  176. pipecat/services/qwen/llm.py +8 -6
  177. pipecat/services/rime/tts.py +128 -17
  178. pipecat/services/riva/stt.py +160 -22
  179. pipecat/services/riva/tts.py +67 -2
  180. pipecat/services/sambanova/llm.py +19 -17
  181. pipecat/services/sambanova/stt.py +14 -8
  182. pipecat/services/sarvam/tts.py +60 -13
  183. pipecat/services/simli/video.py +82 -21
  184. pipecat/services/soniox/__init__.py +0 -0
  185. pipecat/services/soniox/stt.py +398 -0
  186. pipecat/services/speechmatics/stt.py +29 -17
  187. pipecat/services/stt_service.py +47 -11
  188. pipecat/services/tavus/video.py +94 -25
  189. pipecat/services/together/llm.py +8 -6
  190. pipecat/services/tts_service.py +77 -53
  191. pipecat/services/ultravox/stt.py +46 -43
  192. pipecat/services/vision_service.py +5 -3
  193. pipecat/services/websocket_service.py +12 -11
  194. pipecat/services/whisper/base_stt.py +58 -12
  195. pipecat/services/whisper/stt.py +69 -58
  196. pipecat/services/xtts/tts.py +59 -2
  197. pipecat/sync/base_notifier.py +19 -0
  198. pipecat/sync/event_notifier.py +24 -0
  199. pipecat/tests/utils.py +73 -5
  200. pipecat/transcriptions/language.py +24 -0
  201. pipecat/transports/base_input.py +112 -8
  202. pipecat/transports/base_output.py +235 -13
  203. pipecat/transports/base_transport.py +119 -0
  204. pipecat/transports/local/audio.py +76 -0
  205. pipecat/transports/local/tk.py +84 -0
  206. pipecat/transports/network/fastapi_websocket.py +174 -15
  207. pipecat/transports/network/small_webrtc.py +383 -39
  208. pipecat/transports/network/webrtc_connection.py +214 -8
  209. pipecat/transports/network/websocket_client.py +171 -1
  210. pipecat/transports/network/websocket_server.py +147 -9
  211. pipecat/transports/services/daily.py +792 -70
  212. pipecat/transports/services/helpers/daily_rest.py +122 -129
  213. pipecat/transports/services/livekit.py +339 -4
  214. pipecat/transports/services/tavus.py +273 -38
  215. pipecat/utils/asyncio/task_manager.py +92 -186
  216. pipecat/utils/base_object.py +83 -1
  217. pipecat/utils/network.py +2 -0
  218. pipecat/utils/string.py +114 -58
  219. pipecat/utils/text/base_text_aggregator.py +44 -13
  220. pipecat/utils/text/base_text_filter.py +46 -0
  221. pipecat/utils/text/markdown_text_filter.py +70 -14
  222. pipecat/utils/text/pattern_pair_aggregator.py +18 -14
  223. pipecat/utils/text/simple_text_aggregator.py +43 -2
  224. pipecat/utils/text/skip_tags_aggregator.py +21 -13
  225. pipecat/utils/time.py +36 -0
  226. pipecat/utils/tracing/class_decorators.py +32 -7
  227. pipecat/utils/tracing/conversation_context_provider.py +12 -2
  228. pipecat/utils/tracing/service_attributes.py +80 -64
  229. pipecat/utils/tracing/service_decorators.py +48 -21
  230. pipecat/utils/tracing/setup.py +13 -7
  231. pipecat/utils/tracing/turn_context_provider.py +12 -2
  232. pipecat/utils/tracing/turn_trace_observer.py +27 -0
  233. pipecat/utils/utils.py +14 -14
  234. dv_pipecat_ai-0.0.74.dev770.dist-info/RECORD +0 -319
  235. pipecat/examples/daily_runner.py +0 -64
  236. pipecat/examples/run.py +0 -265
  237. pipecat/utils/asyncio/watchdog_async_iterator.py +0 -72
  238. pipecat/utils/asyncio/watchdog_event.py +0 -42
  239. pipecat/utils/asyncio/watchdog_priority_queue.py +0 -48
  240. pipecat/utils/asyncio/watchdog_queue.py +0 -48
  241. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/WHEEL +0 -0
  242. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/licenses/LICENSE +0 -0
  243. {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/top_level.txt +0 -0
  244. /pipecat/{examples → extensions}/__init__.py +0 -0
@@ -4,6 +4,13 @@
4
4
  # SPDX-License-Identifier: BSD 2-Clause License
5
5
  #
6
6
 
7
+ """WebSocket server transport implementation for Pipecat.
8
+
9
+ This module provides WebSocket server transport functionality for real-time
10
+ audio and data streaming, including client connection management, session
11
+ handling, and frame serialization.
12
+ """
13
+
7
14
  import asyncio
8
15
  import io
9
16
  import time
@@ -32,6 +39,8 @@ from pipecat.transports.base_transport import BaseTransport, TransportParams
32
39
 
33
40
  try:
34
41
  import websockets
42
+ from websockets.asyncio.server import serve as websocket_serve
43
+ from websockets.protocol import State
35
44
  except ModuleNotFoundError as e:
36
45
  logger.error(f"Exception: {e}")
37
46
  logger.error("In order to use websockets, you need to `pip install pipecat-ai[websocket]`.")
@@ -39,12 +48,29 @@ except ModuleNotFoundError as e:
39
48
 
40
49
 
41
50
  class WebsocketServerParams(TransportParams):
51
+ """Configuration parameters for WebSocket server transport.
52
+
53
+ Parameters:
54
+ add_wav_header: Whether to add WAV headers to audio frames.
55
+ serializer: Frame serializer for message encoding/decoding.
56
+ session_timeout: Timeout in seconds for client sessions.
57
+ """
58
+
42
59
  add_wav_header: bool = False
43
60
  serializer: Optional[FrameSerializer] = None
44
61
  session_timeout: Optional[int] = None
45
62
 
46
63
 
47
64
  class WebsocketServerCallbacks(BaseModel):
65
+ """Callback functions for WebSocket server events.
66
+
67
+ Parameters:
68
+ on_client_connected: Called when a client connects to the server.
69
+ on_client_disconnected: Called when a client disconnects from the server.
70
+ on_session_timeout: Called when a client session times out.
71
+ on_websocket_ready: Called when the WebSocket server is ready to accept connections.
72
+ """
73
+
48
74
  on_client_connected: Callable[[websockets.WebSocketServerProtocol], Awaitable[None]]
49
75
  on_client_disconnected: Callable[[websockets.WebSocketServerProtocol], Awaitable[None]]
50
76
  on_session_timeout: Callable[[websockets.WebSocketServerProtocol], Awaitable[None]]
@@ -52,6 +78,12 @@ class WebsocketServerCallbacks(BaseModel):
52
78
 
53
79
 
54
80
  class WebsocketServerInputTransport(BaseInputTransport):
81
+ """WebSocket server input transport for receiving client data.
82
+
83
+ Handles incoming WebSocket connections, message processing, and client
84
+ session management including timeout monitoring and connection lifecycle.
85
+ """
86
+
55
87
  def __init__(
56
88
  self,
57
89
  transport: BaseTransport,
@@ -61,6 +93,16 @@ class WebsocketServerInputTransport(BaseInputTransport):
61
93
  callbacks: WebsocketServerCallbacks,
62
94
  **kwargs,
63
95
  ):
96
+ """Initialize the WebSocket server input transport.
97
+
98
+ Args:
99
+ transport: The parent transport instance.
100
+ host: Host address to bind the WebSocket server to.
101
+ port: Port number to bind the WebSocket server to.
102
+ params: WebSocket server configuration parameters.
103
+ callbacks: Callback functions for WebSocket events.
104
+ **kwargs: Additional arguments passed to parent class.
105
+ """
64
106
  super().__init__(params, **kwargs)
65
107
 
66
108
  self._transport = transport
@@ -82,6 +124,11 @@ class WebsocketServerInputTransport(BaseInputTransport):
82
124
  self._initialized = False
83
125
 
84
126
  async def start(self, frame: StartFrame):
127
+ """Start the WebSocket server and initialize components.
128
+
129
+ Args:
130
+ frame: The start frame containing initialization parameters.
131
+ """
85
132
  await super().start(frame)
86
133
 
87
134
  if self._initialized:
@@ -96,16 +143,26 @@ class WebsocketServerInputTransport(BaseInputTransport):
96
143
  await self.set_transport_ready(frame)
97
144
 
98
145
  async def stop(self, frame: EndFrame):
146
+ """Stop the WebSocket server and cleanup resources.
147
+
148
+ Args:
149
+ frame: The end frame signaling transport shutdown.
150
+ """
99
151
  await super().stop(frame)
100
152
  self._stop_server_event.set()
101
153
  if self._monitor_task:
102
154
  await self.cancel_task(self._monitor_task)
103
155
  self._monitor_task = None
104
156
  if self._server_task:
105
- await self.wait_for_task(self._server_task)
157
+ await self._server_task
106
158
  self._server_task = None
107
159
 
108
160
  async def cancel(self, frame: CancelFrame):
161
+ """Cancel the WebSocket server and stop all processing.
162
+
163
+ Args:
164
+ frame: The cancel frame signaling immediate cancellation.
165
+ """
109
166
  await super().cancel(frame)
110
167
  if self._monitor_task:
111
168
  await self.cancel_task(self._monitor_task)
@@ -115,16 +172,19 @@ class WebsocketServerInputTransport(BaseInputTransport):
115
172
  self._server_task = None
116
173
 
117
174
  async def cleanup(self):
175
+ """Cleanup resources and parent transport."""
118
176
  await super().cleanup()
119
177
  await self._transport.cleanup()
120
178
 
121
179
  async def _server_task_handler(self):
180
+ """Handle WebSocket server startup and client connections."""
122
181
  logger.info(f"Starting websocket server on {self._host}:{self._port}")
123
- async with websockets.serve(self._client_handler, self._host, self._port) as server:
182
+ async with websocket_serve(self._client_handler, self._host, self._port) as server:
124
183
  await self._callbacks.on_websocket_ready()
125
184
  await self._stop_server_event.wait()
126
185
 
127
- async def _client_handler(self, websocket: websockets.WebSocketServerProtocol, path):
186
+ async def _client_handler(self, websocket: websockets.WebSocketServerProtocol):
187
+ """Handle individual client connections and message processing."""
128
188
  logger.info(f"New client connection from {websocket.remote_address}")
129
189
  if self._websocket:
130
190
  await self._websocket.close()
@@ -170,12 +230,10 @@ class WebsocketServerInputTransport(BaseInputTransport):
170
230
  async def _monitor_websocket(
171
231
  self, websocket: websockets.WebSocketServerProtocol, session_timeout: int
172
232
  ):
173
- """Wait for session_timeout seconds, if the websocket is still open,
174
- trigger timeout event.
175
- """
233
+ """Monitor WebSocket connection for session timeout."""
176
234
  try:
177
235
  await asyncio.sleep(session_timeout)
178
- if not websocket.closed:
236
+ if websocket.state is not State.CLOSED:
179
237
  await self._callbacks.on_session_timeout(websocket)
180
238
  except asyncio.CancelledError:
181
239
  logger.info(f"Monitoring task cancelled for: {websocket.remote_address}")
@@ -183,7 +241,20 @@ class WebsocketServerInputTransport(BaseInputTransport):
183
241
 
184
242
 
185
243
  class WebsocketServerOutputTransport(BaseOutputTransport):
244
+ """WebSocket server output transport for sending data to clients.
245
+
246
+ Handles outgoing frame serialization, audio streaming with timing control,
247
+ and client connection management for WebSocket communication.
248
+ """
249
+
186
250
  def __init__(self, transport: BaseTransport, params: WebsocketServerParams, **kwargs):
251
+ """Initialize the WebSocket server output transport.
252
+
253
+ Args:
254
+ transport: The parent transport instance.
255
+ params: WebSocket server configuration parameters.
256
+ **kwargs: Additional arguments passed to parent class.
257
+ """
187
258
  super().__init__(params, **kwargs)
188
259
 
189
260
  self._transport = transport
@@ -203,12 +274,22 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
203
274
  self._initialized = False
204
275
 
205
276
  async def set_client_connection(self, websocket: Optional[websockets.WebSocketServerProtocol]):
277
+ """Set the active client WebSocket connection.
278
+
279
+ Args:
280
+ websocket: The WebSocket connection to set as active, or None to clear.
281
+ """
206
282
  if self._websocket:
207
283
  await self._websocket.close()
208
284
  logger.warning("Only one client allowed, using new connection")
209
285
  self._websocket = websocket
210
286
 
211
287
  async def start(self, frame: StartFrame):
288
+ """Start the output transport and initialize components.
289
+
290
+ Args:
291
+ frame: The start frame containing initialization parameters.
292
+ """
212
293
  await super().start(frame)
213
294
 
214
295
  if self._initialized:
@@ -222,18 +303,35 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
222
303
  await self.set_transport_ready(frame)
223
304
 
224
305
  async def stop(self, frame: EndFrame):
306
+ """Stop the output transport and send final frame.
307
+
308
+ Args:
309
+ frame: The end frame signaling transport shutdown.
310
+ """
225
311
  await super().stop(frame)
226
312
  await self._write_frame(frame)
227
313
 
228
314
  async def cancel(self, frame: CancelFrame):
315
+ """Cancel the output transport and send cancellation frame.
316
+
317
+ Args:
318
+ frame: The cancel frame signaling immediate cancellation.
319
+ """
229
320
  await super().cancel(frame)
230
321
  await self._write_frame(frame)
231
322
 
232
323
  async def cleanup(self):
324
+ """Cleanup resources and parent transport."""
233
325
  await super().cleanup()
234
326
  await self._transport.cleanup()
235
327
 
236
328
  async def process_frame(self, frame: Frame, direction: FrameDirection):
329
+ """Process frames and handle interruption timing.
330
+
331
+ Args:
332
+ frame: The frame to process.
333
+ direction: The direction of frame flow in the pipeline.
334
+ """
237
335
  await super().process_frame(frame, direction)
238
336
 
239
337
  if isinstance(frame, StartInterruptionFrame):
@@ -241,12 +339,20 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
241
339
  self._next_send_time = 0
242
340
 
243
341
  async def send_message(self, frame: TransportMessageFrame | TransportMessageUrgentFrame):
342
+ """Send a transport message frame to the client.
343
+
344
+ Args:
345
+ frame: The transport message frame to send.
346
+ """
244
347
  await self._write_frame(frame)
245
348
 
246
349
  async def write_audio_frame(self, frame: OutputAudioRawFrame):
350
+ """Write an audio frame to the WebSocket client with timing control.
351
+
352
+ Args:
353
+ frame: The output audio frame to write.
354
+ """
247
355
  if not self._websocket:
248
- # Simulate audio playback with a sleep.
249
- await self._write_audio_sleep()
250
356
  return
251
357
 
252
358
  frame = OutputAudioRawFrame(
@@ -275,6 +381,7 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
275
381
  await self._write_audio_sleep()
276
382
 
277
383
  async def _write_frame(self, frame: Frame):
384
+ """Serialize and send a frame to the WebSocket client."""
278
385
  if not self._params.serializer:
279
386
  return
280
387
 
@@ -286,6 +393,7 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
286
393
  logger.error(f"{self} exception sending data: {e.__class__.__name__} ({e})")
287
394
 
288
395
  async def _write_audio_sleep(self):
396
+ """Simulate audio device timing by sleeping between audio chunks."""
289
397
  # Simulate a clock.
290
398
  current_time = time.monotonic()
291
399
  sleep_duration = max(0, self._next_send_time - current_time)
@@ -297,6 +405,13 @@ class WebsocketServerOutputTransport(BaseOutputTransport):
297
405
 
298
406
 
299
407
  class WebsocketServerTransport(BaseTransport):
408
+ """WebSocket server transport for bidirectional real-time communication.
409
+
410
+ Provides a complete WebSocket server implementation with separate input and
411
+ output transports, client connection management, and event handling for
412
+ real-time audio and data streaming applications.
413
+ """
414
+
300
415
  def __init__(
301
416
  self,
302
417
  params: WebsocketServerParams,
@@ -305,6 +420,15 @@ class WebsocketServerTransport(BaseTransport):
305
420
  input_name: Optional[str] = None,
306
421
  output_name: Optional[str] = None,
307
422
  ):
423
+ """Initialize the WebSocket server transport.
424
+
425
+ Args:
426
+ params: WebSocket server configuration parameters.
427
+ host: Host address to bind the server to. Defaults to "localhost".
428
+ port: Port number to bind the server to. Defaults to 8765.
429
+ input_name: Optional name for the input processor.
430
+ output_name: Optional name for the output processor.
431
+ """
308
432
  super().__init__(input_name=input_name, output_name=output_name)
309
433
  self._host = host
310
434
  self._port = port
@@ -328,6 +452,11 @@ class WebsocketServerTransport(BaseTransport):
328
452
  self._register_event_handler("on_websocket_ready")
329
453
 
330
454
  def input(self) -> WebsocketServerInputTransport:
455
+ """Get the input transport for receiving client data.
456
+
457
+ Returns:
458
+ The WebSocket server input transport instance.
459
+ """
331
460
  if not self._input:
332
461
  self._input = WebsocketServerInputTransport(
333
462
  self, self._host, self._port, self._params, self._callbacks, name=self._input_name
@@ -335,6 +464,11 @@ class WebsocketServerTransport(BaseTransport):
335
464
  return self._input
336
465
 
337
466
  def output(self) -> WebsocketServerOutputTransport:
467
+ """Get the output transport for sending data to clients.
468
+
469
+ Returns:
470
+ The WebSocket server output transport instance.
471
+ """
338
472
  if not self._output:
339
473
  self._output = WebsocketServerOutputTransport(
340
474
  self, self._params, name=self._output_name
@@ -342,6 +476,7 @@ class WebsocketServerTransport(BaseTransport):
342
476
  return self._output
343
477
 
344
478
  async def _on_client_connected(self, websocket):
479
+ """Handle client connection events."""
345
480
  if self._output:
346
481
  await self._output.set_client_connection(websocket)
347
482
  await self._call_event_handler("on_client_connected", websocket)
@@ -349,6 +484,7 @@ class WebsocketServerTransport(BaseTransport):
349
484
  logger.error("A WebsocketServerTransport output is missing in the pipeline")
350
485
 
351
486
  async def _on_client_disconnected(self, websocket):
487
+ """Handle client disconnection events."""
352
488
  if self._output:
353
489
  await self._output.set_client_connection(None)
354
490
  await self._call_event_handler("on_client_disconnected", websocket)
@@ -356,7 +492,9 @@ class WebsocketServerTransport(BaseTransport):
356
492
  logger.error("A WebsocketServerTransport output is missing in the pipeline")
357
493
 
358
494
  async def _on_session_timeout(self, websocket):
495
+ """Handle client session timeout events."""
359
496
  await self._call_event_handler("on_session_timeout", websocket)
360
497
 
361
498
  async def _on_websocket_ready(self):
499
+ """Handle WebSocket server ready events."""
362
500
  await self._call_event_handler("on_websocket_ready")