dv-pipecat-ai 0.0.82.dev857__py3-none-any.whl → 0.0.85.dev837__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.
- {dv_pipecat_ai-0.0.82.dev857.dist-info → dv_pipecat_ai-0.0.85.dev837.dist-info}/METADATA +98 -130
- {dv_pipecat_ai-0.0.82.dev857.dist-info → dv_pipecat_ai-0.0.85.dev837.dist-info}/RECORD +192 -140
- pipecat/adapters/base_llm_adapter.py +38 -1
- pipecat/adapters/services/anthropic_adapter.py +9 -14
- pipecat/adapters/services/aws_nova_sonic_adapter.py +120 -5
- pipecat/adapters/services/bedrock_adapter.py +236 -13
- pipecat/adapters/services/gemini_adapter.py +12 -8
- pipecat/adapters/services/open_ai_adapter.py +19 -7
- pipecat/adapters/services/open_ai_realtime_adapter.py +5 -0
- pipecat/audio/dtmf/dtmf-0.wav +0 -0
- pipecat/audio/dtmf/dtmf-1.wav +0 -0
- pipecat/audio/dtmf/dtmf-2.wav +0 -0
- pipecat/audio/dtmf/dtmf-3.wav +0 -0
- pipecat/audio/dtmf/dtmf-4.wav +0 -0
- pipecat/audio/dtmf/dtmf-5.wav +0 -0
- pipecat/audio/dtmf/dtmf-6.wav +0 -0
- pipecat/audio/dtmf/dtmf-7.wav +0 -0
- pipecat/audio/dtmf/dtmf-8.wav +0 -0
- pipecat/audio/dtmf/dtmf-9.wav +0 -0
- pipecat/audio/dtmf/dtmf-pound.wav +0 -0
- pipecat/audio/dtmf/dtmf-star.wav +0 -0
- pipecat/audio/filters/krisp_viva_filter.py +193 -0
- pipecat/audio/filters/noisereduce_filter.py +15 -0
- pipecat/audio/turn/base_turn_analyzer.py +9 -1
- pipecat/audio/turn/smart_turn/base_smart_turn.py +14 -8
- pipecat/audio/turn/smart_turn/data/__init__.py +0 -0
- pipecat/audio/turn/smart_turn/data/smart-turn-v3.0.onnx +0 -0
- pipecat/audio/turn/smart_turn/http_smart_turn.py +6 -2
- pipecat/audio/turn/smart_turn/local_smart_turn.py +1 -1
- pipecat/audio/turn/smart_turn/local_smart_turn_v2.py +1 -1
- pipecat/audio/turn/smart_turn/local_smart_turn_v3.py +124 -0
- pipecat/audio/vad/data/README.md +10 -0
- pipecat/audio/vad/data/silero_vad_v2.onnx +0 -0
- pipecat/audio/vad/silero.py +9 -3
- pipecat/audio/vad/vad_analyzer.py +13 -1
- pipecat/extensions/voicemail/voicemail_detector.py +5 -5
- pipecat/frames/frames.py +277 -86
- pipecat/observers/loggers/debug_log_observer.py +3 -3
- pipecat/observers/loggers/llm_log_observer.py +7 -3
- pipecat/observers/loggers/user_bot_latency_log_observer.py +22 -10
- pipecat/pipeline/runner.py +18 -6
- pipecat/pipeline/service_switcher.py +64 -36
- pipecat/pipeline/task.py +125 -79
- pipecat/pipeline/tts_switcher.py +30 -0
- pipecat/processors/aggregators/dtmf_aggregator.py +2 -3
- pipecat/processors/aggregators/{gated_openai_llm_context.py → gated_llm_context.py} +9 -9
- pipecat/processors/aggregators/gated_open_ai_llm_context.py +12 -0
- pipecat/processors/aggregators/llm_context.py +40 -2
- pipecat/processors/aggregators/llm_response.py +32 -15
- pipecat/processors/aggregators/llm_response_universal.py +19 -15
- pipecat/processors/aggregators/user_response.py +6 -6
- pipecat/processors/aggregators/vision_image_frame.py +24 -2
- pipecat/processors/audio/audio_buffer_processor.py +43 -8
- pipecat/processors/dtmf_aggregator.py +174 -77
- pipecat/processors/filters/stt_mute_filter.py +17 -0
- pipecat/processors/frame_processor.py +110 -24
- pipecat/processors/frameworks/langchain.py +8 -2
- pipecat/processors/frameworks/rtvi.py +210 -68
- pipecat/processors/frameworks/strands_agents.py +170 -0
- pipecat/processors/logger.py +2 -2
- pipecat/processors/transcript_processor.py +26 -5
- pipecat/processors/user_idle_processor.py +35 -11
- pipecat/runner/daily.py +59 -20
- pipecat/runner/run.py +395 -93
- pipecat/runner/types.py +6 -4
- pipecat/runner/utils.py +51 -10
- pipecat/serializers/__init__.py +5 -1
- pipecat/serializers/asterisk.py +16 -2
- pipecat/serializers/convox.py +41 -4
- pipecat/serializers/custom.py +257 -0
- pipecat/serializers/exotel.py +5 -5
- pipecat/serializers/livekit.py +20 -0
- pipecat/serializers/plivo.py +5 -5
- pipecat/serializers/protobuf.py +6 -5
- pipecat/serializers/telnyx.py +2 -2
- pipecat/serializers/twilio.py +43 -23
- pipecat/serializers/vi.py +324 -0
- pipecat/services/ai_service.py +2 -6
- pipecat/services/anthropic/llm.py +2 -25
- pipecat/services/assemblyai/models.py +6 -0
- pipecat/services/assemblyai/stt.py +13 -5
- pipecat/services/asyncai/tts.py +5 -3
- pipecat/services/aws/__init__.py +1 -0
- pipecat/services/aws/llm.py +147 -105
- pipecat/services/aws/nova_sonic/__init__.py +0 -0
- pipecat/services/aws/nova_sonic/context.py +436 -0
- pipecat/services/aws/nova_sonic/frames.py +25 -0
- pipecat/services/aws/nova_sonic/llm.py +1265 -0
- pipecat/services/aws/stt.py +3 -3
- pipecat/services/aws_nova_sonic/__init__.py +19 -1
- pipecat/services/aws_nova_sonic/aws.py +11 -1151
- pipecat/services/aws_nova_sonic/context.py +8 -354
- pipecat/services/aws_nova_sonic/frames.py +13 -17
- pipecat/services/azure/llm.py +51 -1
- pipecat/services/azure/realtime/__init__.py +0 -0
- pipecat/services/azure/realtime/llm.py +65 -0
- pipecat/services/azure/stt.py +15 -0
- pipecat/services/cartesia/stt.py +77 -70
- pipecat/services/cartesia/tts.py +80 -13
- pipecat/services/deepgram/__init__.py +1 -0
- pipecat/services/deepgram/flux/__init__.py +0 -0
- pipecat/services/deepgram/flux/stt.py +640 -0
- pipecat/services/elevenlabs/__init__.py +4 -1
- pipecat/services/elevenlabs/stt.py +339 -0
- pipecat/services/elevenlabs/tts.py +87 -46
- pipecat/services/fish/tts.py +5 -2
- pipecat/services/gemini_multimodal_live/events.py +38 -524
- pipecat/services/gemini_multimodal_live/file_api.py +23 -173
- pipecat/services/gemini_multimodal_live/gemini.py +41 -1403
- pipecat/services/gladia/stt.py +56 -72
- pipecat/services/google/__init__.py +1 -0
- pipecat/services/google/gemini_live/__init__.py +3 -0
- pipecat/services/google/gemini_live/file_api.py +189 -0
- pipecat/services/google/gemini_live/llm.py +1582 -0
- pipecat/services/google/gemini_live/llm_vertex.py +184 -0
- pipecat/services/google/llm.py +15 -11
- pipecat/services/google/llm_openai.py +3 -3
- pipecat/services/google/llm_vertex.py +86 -16
- pipecat/services/google/stt.py +4 -0
- pipecat/services/google/tts.py +7 -3
- pipecat/services/heygen/api.py +2 -0
- pipecat/services/heygen/client.py +8 -4
- pipecat/services/heygen/video.py +2 -0
- pipecat/services/hume/__init__.py +5 -0
- pipecat/services/hume/tts.py +220 -0
- pipecat/services/inworld/tts.py +6 -6
- pipecat/services/llm_service.py +15 -5
- pipecat/services/lmnt/tts.py +4 -2
- pipecat/services/mcp_service.py +4 -2
- pipecat/services/mem0/memory.py +6 -5
- pipecat/services/mistral/llm.py +29 -8
- pipecat/services/moondream/vision.py +42 -16
- pipecat/services/neuphonic/tts.py +5 -2
- pipecat/services/openai/__init__.py +1 -0
- pipecat/services/openai/base_llm.py +27 -20
- pipecat/services/openai/realtime/__init__.py +0 -0
- pipecat/services/openai/realtime/context.py +272 -0
- pipecat/services/openai/realtime/events.py +1106 -0
- pipecat/services/openai/realtime/frames.py +37 -0
- pipecat/services/openai/realtime/llm.py +829 -0
- pipecat/services/openai/tts.py +49 -10
- pipecat/services/openai_realtime/__init__.py +27 -0
- pipecat/services/openai_realtime/azure.py +21 -0
- pipecat/services/openai_realtime/context.py +21 -0
- pipecat/services/openai_realtime/events.py +21 -0
- pipecat/services/openai_realtime/frames.py +21 -0
- pipecat/services/openai_realtime_beta/azure.py +16 -0
- pipecat/services/openai_realtime_beta/openai.py +17 -5
- pipecat/services/piper/tts.py +7 -9
- pipecat/services/playht/tts.py +34 -4
- pipecat/services/rime/tts.py +12 -12
- pipecat/services/riva/stt.py +3 -1
- pipecat/services/salesforce/__init__.py +9 -0
- pipecat/services/salesforce/llm.py +700 -0
- pipecat/services/sarvam/__init__.py +7 -0
- pipecat/services/sarvam/stt.py +540 -0
- pipecat/services/sarvam/tts.py +97 -13
- pipecat/services/simli/video.py +2 -2
- pipecat/services/speechmatics/stt.py +22 -10
- pipecat/services/stt_service.py +47 -0
- pipecat/services/tavus/video.py +2 -2
- pipecat/services/tts_service.py +75 -22
- pipecat/services/vision_service.py +7 -6
- pipecat/services/vistaar/llm.py +51 -9
- pipecat/tests/utils.py +4 -4
- pipecat/transcriptions/language.py +41 -1
- pipecat/transports/base_input.py +13 -34
- pipecat/transports/base_output.py +140 -104
- pipecat/transports/daily/transport.py +199 -26
- pipecat/transports/heygen/__init__.py +0 -0
- pipecat/transports/heygen/transport.py +381 -0
- pipecat/transports/livekit/transport.py +228 -63
- pipecat/transports/local/audio.py +6 -1
- pipecat/transports/local/tk.py +11 -2
- pipecat/transports/network/fastapi_websocket.py +1 -1
- pipecat/transports/smallwebrtc/connection.py +103 -19
- pipecat/transports/smallwebrtc/request_handler.py +246 -0
- pipecat/transports/smallwebrtc/transport.py +65 -23
- pipecat/transports/tavus/transport.py +23 -12
- pipecat/transports/websocket/client.py +41 -5
- pipecat/transports/websocket/fastapi.py +21 -11
- pipecat/transports/websocket/server.py +14 -7
- pipecat/transports/whatsapp/api.py +8 -0
- pipecat/transports/whatsapp/client.py +47 -0
- pipecat/utils/base_object.py +54 -22
- pipecat/utils/redis.py +58 -0
- pipecat/utils/string.py +13 -1
- pipecat/utils/tracing/service_decorators.py +21 -21
- pipecat/serializers/genesys.py +0 -95
- pipecat/services/google/test-google-chirp.py +0 -45
- pipecat/services/openai.py +0 -698
- {dv_pipecat_ai-0.0.82.dev857.dist-info → dv_pipecat_ai-0.0.85.dev837.dist-info}/WHEEL +0 -0
- {dv_pipecat_ai-0.0.82.dev857.dist-info → dv_pipecat_ai-0.0.85.dev837.dist-info}/licenses/LICENSE +0 -0
- {dv_pipecat_ai-0.0.82.dev857.dist-info → dv_pipecat_ai-0.0.85.dev837.dist-info}/top_level.txt +0 -0
- /pipecat/services/{aws_nova_sonic → aws/nova_sonic}/ready.wav +0 -0
|
@@ -25,19 +25,20 @@ from pydantic import BaseModel
|
|
|
25
25
|
from pipecat.audio.vad.vad_analyzer import VADAnalyzer, VADParams
|
|
26
26
|
from pipecat.frames.frames import (
|
|
27
27
|
CancelFrame,
|
|
28
|
+
ControlFrame,
|
|
28
29
|
EndFrame,
|
|
29
30
|
ErrorFrame,
|
|
30
31
|
Frame,
|
|
31
32
|
InputAudioRawFrame,
|
|
32
|
-
|
|
33
|
+
InputTransportMessageFrame,
|
|
33
34
|
InterimTranscriptionFrame,
|
|
34
35
|
OutputAudioRawFrame,
|
|
35
36
|
OutputImageRawFrame,
|
|
37
|
+
OutputTransportMessageFrame,
|
|
38
|
+
OutputTransportMessageUrgentFrame,
|
|
36
39
|
SpriteFrame,
|
|
37
40
|
StartFrame,
|
|
38
41
|
TranscriptionFrame,
|
|
39
|
-
TransportMessageFrame,
|
|
40
|
-
TransportMessageUrgentFrame,
|
|
41
42
|
UserAudioRawFrame,
|
|
42
43
|
UserImageRawFrame,
|
|
43
44
|
UserImageRequestFrame,
|
|
@@ -61,9 +62,7 @@ try:
|
|
|
61
62
|
VirtualCameraDevice,
|
|
62
63
|
VirtualSpeakerDevice,
|
|
63
64
|
)
|
|
64
|
-
from daily import
|
|
65
|
-
LogLevel as DailyLogLevel,
|
|
66
|
-
)
|
|
65
|
+
from daily import LogLevel as DailyLogLevel
|
|
67
66
|
except ModuleNotFoundError as e:
|
|
68
67
|
logger.error(f"Exception: {e}")
|
|
69
68
|
logger.error(
|
|
@@ -75,7 +74,7 @@ VAD_RESET_PERIOD_MS = 2000
|
|
|
75
74
|
|
|
76
75
|
|
|
77
76
|
@dataclass
|
|
78
|
-
class
|
|
77
|
+
class DailyOutputTransportMessageFrame(OutputTransportMessageFrame):
|
|
79
78
|
"""Frame for transport messages in Daily calls.
|
|
80
79
|
|
|
81
80
|
Parameters:
|
|
@@ -86,7 +85,7 @@ class DailyTransportMessageFrame(TransportMessageFrame):
|
|
|
86
85
|
|
|
87
86
|
|
|
88
87
|
@dataclass
|
|
89
|
-
class
|
|
88
|
+
class DailyOutputTransportMessageUrgentFrame(OutputTransportMessageUrgentFrame):
|
|
90
89
|
"""Frame for urgent transport messages in Daily calls.
|
|
91
90
|
|
|
92
91
|
Parameters:
|
|
@@ -97,7 +96,59 @@ class DailyTransportMessageUrgentFrame(TransportMessageUrgentFrame):
|
|
|
97
96
|
|
|
98
97
|
|
|
99
98
|
@dataclass
|
|
100
|
-
class
|
|
99
|
+
class DailyTransportMessageFrame(DailyOutputTransportMessageFrame):
|
|
100
|
+
"""Frame for transport messages in Daily calls.
|
|
101
|
+
|
|
102
|
+
.. deprecated:: 0.0.87
|
|
103
|
+
This frame is deprecated and will be removed in a future version.
|
|
104
|
+
Instead, use `DailyOutputTransportMessageFrame`.
|
|
105
|
+
|
|
106
|
+
Parameters:
|
|
107
|
+
participant_id: Optional ID of the participant this message is for/from.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
def __post_init__(self):
|
|
111
|
+
super().__post_init__()
|
|
112
|
+
import warnings
|
|
113
|
+
|
|
114
|
+
with warnings.catch_warnings():
|
|
115
|
+
warnings.simplefilter("always")
|
|
116
|
+
warnings.warn(
|
|
117
|
+
"DailyTransportMessageFrame is deprecated and will be removed in a future version. "
|
|
118
|
+
"Instead, use DailyOutputTransportMessageFrame.",
|
|
119
|
+
DeprecationWarning,
|
|
120
|
+
stacklevel=2,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@dataclass
|
|
125
|
+
class DailyTransportMessageUrgentFrame(DailyOutputTransportMessageUrgentFrame):
|
|
126
|
+
"""Frame for urgent transport messages in Daily calls.
|
|
127
|
+
|
|
128
|
+
.. deprecated:: 0.0.87
|
|
129
|
+
This frame is deprecated and will be removed in a future version.
|
|
130
|
+
Instead, use `DailyOutputTransportMessageUrgentFrame`.
|
|
131
|
+
|
|
132
|
+
Parameters:
|
|
133
|
+
participant_id: Optional ID of the participant this message is for/from.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
def __post_init__(self):
|
|
137
|
+
super().__post_init__()
|
|
138
|
+
import warnings
|
|
139
|
+
|
|
140
|
+
with warnings.catch_warnings():
|
|
141
|
+
warnings.simplefilter("always")
|
|
142
|
+
warnings.warn(
|
|
143
|
+
"DailyTransportMessageUrgentFrame is deprecated and will be removed in a future version. "
|
|
144
|
+
"Instead, use DailyOutputTransportMessageUrgentFrame.",
|
|
145
|
+
DeprecationWarning,
|
|
146
|
+
stacklevel=2,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass
|
|
151
|
+
class DailyInputTransportMessageFrame(InputTransportMessageFrame):
|
|
101
152
|
"""Frame for input urgent transport messages in Daily calls.
|
|
102
153
|
|
|
103
154
|
Parameters:
|
|
@@ -107,6 +158,62 @@ class DailyInputTransportMessageUrgentFrame(InputTransportMessageUrgentFrame):
|
|
|
107
158
|
participant_id: Optional[str] = None
|
|
108
159
|
|
|
109
160
|
|
|
161
|
+
class DailyInputTransportMessageUrgentFrame(DailyInputTransportMessageFrame):
|
|
162
|
+
"""Frame for input urgent transport messages in Daily calls.
|
|
163
|
+
|
|
164
|
+
.. deprecated:: 0.0.87
|
|
165
|
+
This frame is deprecated and will be removed in a future version.
|
|
166
|
+
Instead, use `DailyInputTransportMessageFrame`.
|
|
167
|
+
|
|
168
|
+
Parameters:
|
|
169
|
+
participant_id: Optional ID of the participant this message is for/from.
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
def __post_init__(self):
|
|
173
|
+
super().__post_init__()
|
|
174
|
+
import warnings
|
|
175
|
+
|
|
176
|
+
with warnings.catch_warnings():
|
|
177
|
+
warnings.simplefilter("always")
|
|
178
|
+
warnings.warn(
|
|
179
|
+
"DailyInputTransportMessageUrgentFrame is deprecated and will be removed in a future version. "
|
|
180
|
+
"Instead, use DailyInputTransportMessageFrame.",
|
|
181
|
+
DeprecationWarning,
|
|
182
|
+
stacklevel=2,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass
|
|
187
|
+
class DailyUpdateRemoteParticipantsFrame(ControlFrame):
|
|
188
|
+
"""Frame to update remote participants in Daily calls.
|
|
189
|
+
|
|
190
|
+
.. deprecated:: 0.0.87
|
|
191
|
+
`DailyUpdateRemoteParticipantsFrame` is deprecated and will be removed in a future version.
|
|
192
|
+
Create your own custom frame and use a custom processor to handle it or use, for example,
|
|
193
|
+
`on_after_push_frame` event instead in the output transport.
|
|
194
|
+
|
|
195
|
+
Parameters:
|
|
196
|
+
remote_participants: See https://reference-python.daily.co/api_reference.html#daily.CallClient.update_remote_participants.
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
remote_participants: Mapping[str, Any] = None
|
|
200
|
+
|
|
201
|
+
def __post_init__(self):
|
|
202
|
+
super().__post_init__()
|
|
203
|
+
import warnings
|
|
204
|
+
|
|
205
|
+
with warnings.catch_warnings():
|
|
206
|
+
warnings.simplefilter("always")
|
|
207
|
+
warnings.warn(
|
|
208
|
+
"DailyUpdateRemoteParticipantsFrame is deprecated and will be removed in a future version."
|
|
209
|
+
"Instead, create your own custom frame and handle it in the "
|
|
210
|
+
'`@transport.output().event_handler("on_after_push_frame")` event handler or a '
|
|
211
|
+
"custom processor.",
|
|
212
|
+
DeprecationWarning,
|
|
213
|
+
stacklevel=2,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
110
217
|
class WebRTCVADAnalyzer(VADAnalyzer):
|
|
111
218
|
"""Voice Activity Detection analyzer using WebRTC.
|
|
112
219
|
|
|
@@ -217,6 +324,7 @@ class DailyCallbacks(BaseModel):
|
|
|
217
324
|
on_active_speaker_changed: Called when the active speaker of the call has changed.
|
|
218
325
|
on_joined: Called when bot successfully joined a room.
|
|
219
326
|
on_left: Called when bot left a room.
|
|
327
|
+
on_before_leave: Called when bot is about to leave the room.
|
|
220
328
|
on_error: Called when an error occurs.
|
|
221
329
|
on_app_message: Called when receiving an app message.
|
|
222
330
|
on_call_state_updated: Called when call state changes.
|
|
@@ -246,6 +354,7 @@ class DailyCallbacks(BaseModel):
|
|
|
246
354
|
on_active_speaker_changed: Callable[[Mapping[str, Any]], Awaitable[None]]
|
|
247
355
|
on_joined: Callable[[Mapping[str, Any]], Awaitable[None]]
|
|
248
356
|
on_left: Callable[[], Awaitable[None]]
|
|
357
|
+
on_before_leave: Callable[[], Awaitable[None]]
|
|
249
358
|
on_error: Callable[[str], Awaitable[None]]
|
|
250
359
|
on_app_message: Callable[[Any, str], Awaitable[None]]
|
|
251
360
|
on_call_state_updated: Callable[[str], Awaitable[None]]
|
|
@@ -361,6 +470,7 @@ class DailyTransportClient(EventHandler):
|
|
|
361
470
|
self._transcription_ids = []
|
|
362
471
|
self._transcription_status = None
|
|
363
472
|
self._dial_out_session_id: str = ""
|
|
473
|
+
self._dial_in_session_id: str = ""
|
|
364
474
|
|
|
365
475
|
self._joining = False
|
|
366
476
|
self._joined = False
|
|
@@ -441,7 +551,9 @@ class DailyTransportClient(EventHandler):
|
|
|
441
551
|
"""
|
|
442
552
|
return self._out_sample_rate
|
|
443
553
|
|
|
444
|
-
async def send_message(
|
|
554
|
+
async def send_message(
|
|
555
|
+
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
|
|
556
|
+
):
|
|
445
557
|
"""Send an application message to participants.
|
|
446
558
|
|
|
447
559
|
Args:
|
|
@@ -451,7 +563,9 @@ class DailyTransportClient(EventHandler):
|
|
|
451
563
|
return
|
|
452
564
|
|
|
453
565
|
participant_id = None
|
|
454
|
-
if isinstance(
|
|
566
|
+
if isinstance(
|
|
567
|
+
frame, (DailyOutputTransportMessageFrame, DailyOutputTransportMessageUrgentFrame)
|
|
568
|
+
):
|
|
455
569
|
participant_id = frame.participant_id
|
|
456
570
|
|
|
457
571
|
future = self._get_event_loop().create_future()
|
|
@@ -493,11 +607,14 @@ class DailyTransportClient(EventHandler):
|
|
|
493
607
|
self._custom_audio_tracks[destination] = await self.add_custom_audio_track(destination)
|
|
494
608
|
self._client.update_publishing({"customAudio": {destination: True}})
|
|
495
609
|
|
|
496
|
-
async def write_audio_frame(self, frame: OutputAudioRawFrame):
|
|
610
|
+
async def write_audio_frame(self, frame: OutputAudioRawFrame) -> bool:
|
|
497
611
|
"""Write an audio frame to the appropriate audio track.
|
|
498
612
|
|
|
499
613
|
Args:
|
|
500
614
|
frame: The audio frame to write.
|
|
615
|
+
|
|
616
|
+
Returns:
|
|
617
|
+
True if the audio frame was written successfully, False otherwise.
|
|
501
618
|
"""
|
|
502
619
|
future = self._get_event_loop().create_future()
|
|
503
620
|
|
|
@@ -513,18 +630,24 @@ class DailyTransportClient(EventHandler):
|
|
|
513
630
|
audio_source.write_frames(frame.audio, completion=completion_callback(future))
|
|
514
631
|
else:
|
|
515
632
|
logger.warning(f"{self} unable to write audio frames to destination [{destination}]")
|
|
516
|
-
future.set_result(
|
|
633
|
+
future.set_result(0)
|
|
517
634
|
|
|
518
|
-
await future
|
|
635
|
+
num_frames = await future
|
|
636
|
+
return num_frames > 0
|
|
519
637
|
|
|
520
|
-
async def write_video_frame(self, frame: OutputImageRawFrame):
|
|
638
|
+
async def write_video_frame(self, frame: OutputImageRawFrame) -> bool:
|
|
521
639
|
"""Write a video frame to the camera device.
|
|
522
640
|
|
|
523
641
|
Args:
|
|
524
642
|
frame: The image frame to write.
|
|
643
|
+
|
|
644
|
+
Returns:
|
|
645
|
+
True if the video frame was written successfully, False otherwise.
|
|
525
646
|
"""
|
|
526
647
|
if not frame.transport_destination and self._camera:
|
|
527
648
|
self._camera.write_frame(frame.image)
|
|
649
|
+
return True
|
|
650
|
+
return False
|
|
528
651
|
|
|
529
652
|
async def setup(self, setup: FrameProcessorSetup):
|
|
530
653
|
"""Setup the client with task manager and event queues.
|
|
@@ -721,6 +844,9 @@ class DailyTransportClient(EventHandler):
|
|
|
721
844
|
|
|
722
845
|
logger.info(f"Leaving {self._room_url}")
|
|
723
846
|
|
|
847
|
+
# Call callback before leaving.
|
|
848
|
+
await self._callbacks.on_before_leave()
|
|
849
|
+
|
|
724
850
|
if self._params.transcription_enabled:
|
|
725
851
|
await self.stop_transcription()
|
|
726
852
|
|
|
@@ -825,6 +951,16 @@ class DailyTransportClient(EventHandler):
|
|
|
825
951
|
Args:
|
|
826
952
|
settings: SIP call transfer settings.
|
|
827
953
|
"""
|
|
954
|
+
session_id = (
|
|
955
|
+
settings.get("sessionId") or self._dial_out_session_id or self._dial_in_session_id
|
|
956
|
+
)
|
|
957
|
+
if not session_id:
|
|
958
|
+
logger.error("Unable to transfer SIP call: 'sessionId' is not set")
|
|
959
|
+
return
|
|
960
|
+
|
|
961
|
+
# Update 'sessionId' field.
|
|
962
|
+
settings["sessionId"] = session_id
|
|
963
|
+
|
|
828
964
|
future = self._get_event_loop().create_future()
|
|
829
965
|
self._client.sip_call_transfer(settings, completion=completion_callback(future))
|
|
830
966
|
await future
|
|
@@ -1143,6 +1279,7 @@ class DailyTransportClient(EventHandler):
|
|
|
1143
1279
|
Args:
|
|
1144
1280
|
data: Dial-in connection data.
|
|
1145
1281
|
"""
|
|
1282
|
+
self._dial_in_session_id = data["sessionId"] if "sessionId" in data else ""
|
|
1146
1283
|
self._call_event_callback(self._callbacks.on_dialin_connected, data)
|
|
1147
1284
|
|
|
1148
1285
|
def on_dialin_ready(self, sip_endpoint: str):
|
|
@@ -1159,6 +1296,9 @@ class DailyTransportClient(EventHandler):
|
|
|
1159
1296
|
Args:
|
|
1160
1297
|
data: Dial-in stop data.
|
|
1161
1298
|
"""
|
|
1299
|
+
# Cleanup only if our session stopped.
|
|
1300
|
+
if data.get("sessionId") == self._dial_in_session_id:
|
|
1301
|
+
self._dial_in_session_id = ""
|
|
1162
1302
|
self._call_event_callback(self._callbacks.on_dialin_stopped, data)
|
|
1163
1303
|
|
|
1164
1304
|
def on_dialin_error(self, data: Any):
|
|
@@ -1167,6 +1307,9 @@ class DailyTransportClient(EventHandler):
|
|
|
1167
1307
|
Args:
|
|
1168
1308
|
data: Dial-in error data.
|
|
1169
1309
|
"""
|
|
1310
|
+
# Cleanup only if our session errored out.
|
|
1311
|
+
if data.get("sessionId") == self._dial_in_session_id:
|
|
1312
|
+
self._dial_in_session_id = ""
|
|
1170
1313
|
self._call_event_callback(self._callbacks.on_dialin_error, data)
|
|
1171
1314
|
|
|
1172
1315
|
def on_dialin_warning(self, data: Any):
|
|
@@ -1201,7 +1344,7 @@ class DailyTransportClient(EventHandler):
|
|
|
1201
1344
|
data: Dial-out stop data.
|
|
1202
1345
|
"""
|
|
1203
1346
|
# Cleanup only if our session stopped.
|
|
1204
|
-
if data
|
|
1347
|
+
if data.get("sessionId") == self._dial_out_session_id:
|
|
1205
1348
|
self._dial_out_session_id = ""
|
|
1206
1349
|
self._call_event_callback(self._callbacks.on_dialout_stopped, data)
|
|
1207
1350
|
|
|
@@ -1212,7 +1355,7 @@ class DailyTransportClient(EventHandler):
|
|
|
1212
1355
|
data: Dial-out error data.
|
|
1213
1356
|
"""
|
|
1214
1357
|
# Cleanup only if our session errored out.
|
|
1215
|
-
if data
|
|
1358
|
+
if data.get("sessionId") == self._dial_out_session_id:
|
|
1216
1359
|
self._dial_out_session_id = ""
|
|
1217
1360
|
self._call_event_callback(self._callbacks.on_dialout_error, data)
|
|
1218
1361
|
|
|
@@ -1559,7 +1702,7 @@ class DailyInputTransport(BaseInputTransport):
|
|
|
1559
1702
|
message: The message data to send.
|
|
1560
1703
|
sender: ID of the message sender.
|
|
1561
1704
|
"""
|
|
1562
|
-
frame =
|
|
1705
|
+
frame = DailyInputTransportMessageFrame(message=message, participant_id=sender)
|
|
1563
1706
|
await self.push_frame(frame)
|
|
1564
1707
|
|
|
1565
1708
|
#
|
|
@@ -1769,7 +1912,21 @@ class DailyOutputTransport(BaseOutputTransport):
|
|
|
1769
1912
|
# Leave the room.
|
|
1770
1913
|
await self._client.leave()
|
|
1771
1914
|
|
|
1772
|
-
async def
|
|
1915
|
+
async def process_frame(self, frame: Frame, direction: FrameDirection):
|
|
1916
|
+
"""Process outgoing frames, including transport messages.
|
|
1917
|
+
|
|
1918
|
+
Args:
|
|
1919
|
+
frame: The frame to process.
|
|
1920
|
+
direction: The direction of frame flow in the pipeline.
|
|
1921
|
+
"""
|
|
1922
|
+
await super().process_frame(frame, direction)
|
|
1923
|
+
|
|
1924
|
+
if isinstance(frame, DailyUpdateRemoteParticipantsFrame):
|
|
1925
|
+
await self._client.update_remote_participants(frame.remote_participants)
|
|
1926
|
+
|
|
1927
|
+
async def send_message(
|
|
1928
|
+
self, frame: OutputTransportMessageFrame | OutputTransportMessageUrgentFrame
|
|
1929
|
+
):
|
|
1773
1930
|
"""Send a transport message to participants.
|
|
1774
1931
|
|
|
1775
1932
|
Args:
|
|
@@ -1790,24 +1947,33 @@ class DailyOutputTransport(BaseOutputTransport):
|
|
|
1790
1947
|
|
|
1791
1948
|
Args:
|
|
1792
1949
|
destination: The destination identifier to register.
|
|
1950
|
+
|
|
1951
|
+
Returns:
|
|
1952
|
+
True if the audio frame was written successfully, False otherwise.
|
|
1793
1953
|
"""
|
|
1794
1954
|
await self._client.register_audio_destination(destination)
|
|
1795
1955
|
|
|
1796
|
-
async def write_audio_frame(self, frame: OutputAudioRawFrame):
|
|
1956
|
+
async def write_audio_frame(self, frame: OutputAudioRawFrame) -> bool:
|
|
1797
1957
|
"""Write an audio frame to the Daily call.
|
|
1798
1958
|
|
|
1799
1959
|
Args:
|
|
1800
1960
|
frame: The audio frame to write.
|
|
1961
|
+
|
|
1962
|
+
Returns:
|
|
1963
|
+
True if the audio frame was written successfully, False otherwise.
|
|
1801
1964
|
"""
|
|
1802
|
-
await self._client.write_audio_frame(frame)
|
|
1965
|
+
return await self._client.write_audio_frame(frame)
|
|
1803
1966
|
|
|
1804
|
-
async def write_video_frame(self, frame: OutputImageRawFrame):
|
|
1967
|
+
async def write_video_frame(self, frame: OutputImageRawFrame) -> bool:
|
|
1805
1968
|
"""Write a video frame to the Daily call.
|
|
1806
1969
|
|
|
1807
1970
|
Args:
|
|
1808
1971
|
frame: The video frame to write.
|
|
1972
|
+
|
|
1973
|
+
Returns:
|
|
1974
|
+
True if the video frame was written successfully, False otherwise.
|
|
1809
1975
|
"""
|
|
1810
|
-
await self._client.write_video_frame(frame)
|
|
1976
|
+
return await self._client.write_video_frame(frame)
|
|
1811
1977
|
|
|
1812
1978
|
def _supports_native_dtmf(self) -> bool:
|
|
1813
1979
|
"""Daily supports native DTMF via telephone events.
|
|
@@ -1864,6 +2030,7 @@ class DailyTransport(BaseTransport):
|
|
|
1864
2030
|
on_active_speaker_changed=self._on_active_speaker_changed,
|
|
1865
2031
|
on_joined=self._on_joined,
|
|
1866
2032
|
on_left=self._on_left,
|
|
2033
|
+
on_before_leave=self._on_before_leave,
|
|
1867
2034
|
on_error=self._on_error,
|
|
1868
2035
|
on_app_message=self._on_app_message,
|
|
1869
2036
|
on_call_state_updated=self._on_call_state_updated,
|
|
@@ -1927,6 +2094,7 @@ class DailyTransport(BaseTransport):
|
|
|
1927
2094
|
self._register_event_handler("on_recording_started")
|
|
1928
2095
|
self._register_event_handler("on_recording_stopped")
|
|
1929
2096
|
self._register_event_handler("on_recording_error")
|
|
2097
|
+
self._register_event_handler("on_before_leave", sync=True)
|
|
1930
2098
|
|
|
1931
2099
|
#
|
|
1932
2100
|
# BaseTransport
|
|
@@ -2178,6 +2346,10 @@ class DailyTransport(BaseTransport):
|
|
|
2178
2346
|
"""Handle room left events."""
|
|
2179
2347
|
await self._call_event_handler("on_left")
|
|
2180
2348
|
|
|
2349
|
+
async def _on_before_leave(self):
|
|
2350
|
+
"""Handle before leave room events."""
|
|
2351
|
+
await self._call_event_handler("on_before_leave")
|
|
2352
|
+
|
|
2181
2353
|
async def _on_error(self, error):
|
|
2182
2354
|
"""Handle error events and push error frames."""
|
|
2183
2355
|
await self._call_event_handler("on_error", error)
|
|
@@ -2317,7 +2489,7 @@ class DailyTransport(BaseTransport):
|
|
|
2317
2489
|
"""Handle participant updated events."""
|
|
2318
2490
|
await self._call_event_handler("on_participant_updated", participant)
|
|
2319
2491
|
|
|
2320
|
-
async def _on_transcription_message(self, message):
|
|
2492
|
+
async def _on_transcription_message(self, message: Mapping[str, Any]) -> None:
|
|
2321
2493
|
"""Handle transcription message events."""
|
|
2322
2494
|
await self._call_event_handler("on_transcription_message", message)
|
|
2323
2495
|
|
|
@@ -2329,9 +2501,10 @@ class DailyTransport(BaseTransport):
|
|
|
2329
2501
|
|
|
2330
2502
|
text = message["text"]
|
|
2331
2503
|
timestamp = message["timestamp"]
|
|
2332
|
-
|
|
2504
|
+
raw_response = message.get("rawResponse", {})
|
|
2505
|
+
is_final = raw_response.get("is_final", False)
|
|
2333
2506
|
try:
|
|
2334
|
-
language =
|
|
2507
|
+
language = raw_response["channel"]["alternatives"][0]["languages"][0]
|
|
2335
2508
|
language = Language(language)
|
|
2336
2509
|
except KeyError:
|
|
2337
2510
|
language = None
|
|
File without changes
|