dv-pipecat-ai 0.0.75.dev883__py3-none-any.whl → 0.0.75.dev887__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.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/METADATA +1 -1
- {dv_pipecat_ai-0.0.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/RECORD +6 -5
- pipecat/serializers/asterisk.py +129 -0
- {dv_pipecat_ai-0.0.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/WHEEL +0 -0
- {dv_pipecat_ai-0.0.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/licenses/LICENSE +0 -0
- {dv_pipecat_ai-0.0.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
dv_pipecat_ai-0.0.75.
|
|
1
|
+
dv_pipecat_ai-0.0.75.dev887.dist-info/licenses/LICENSE,sha256=DWY2QGf2eMCFhuu2ChairtT6CB7BEFffNVhXWc4Od08,1301
|
|
2
2
|
pipecat/__init__.py,sha256=j0Xm6adxHhd7D06dIyyPV_GlBYLlBnTAERVvD_jAARQ,861
|
|
3
3
|
pipecat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
pipecat/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -123,6 +123,7 @@ pipecat/runner/run.py,sha256=BuVI9-cpnQHOBxymkPoqpGaSaZImWZKLeu1g0JsvS8E,18818
|
|
|
123
123
|
pipecat/runner/types.py,sha256=iG9A1ox1ePXiEo2bWANsi6RxpGOb5n_Am5O3enbojBM,1599
|
|
124
124
|
pipecat/runner/utils.py,sha256=cT4G46skiIuZexm-KJ9ltrtufcGxPCAk7HW95rCy3tA,17724
|
|
125
125
|
pipecat/serializers/__init__.py,sha256=OV61GQX5ZVU7l7Dt7UTBdv2wUF7ZvtbCoXryo7nnoGY,734
|
|
126
|
+
pipecat/serializers/asterisk.py,sha256=rDb8qMYNGgHzRC_EyCgxB6p99d_1YXXoIm-YW7aHtAc,5236
|
|
126
127
|
pipecat/serializers/base_serializer.py,sha256=OyBUZccs2ZT9mfkBbq2tGsUJMvci6o-j90Cl1sicPaI,2030
|
|
127
128
|
pipecat/serializers/convox.py,sha256=MXCLhV6GMnoP8bI6-EVrObhrftEyTGOmzVeIU5ywmPo,9536
|
|
128
129
|
pipecat/serializers/exotel.py,sha256=LB4wYoXDjPmtkydrZ0G4H4u-SXpQw9KjyRzBZCYloEE,5907
|
|
@@ -334,7 +335,7 @@ pipecat/utils/tracing/service_decorators.py,sha256=HwDCqLGijhYD3F8nxDuQmEw-YkRw0
|
|
|
334
335
|
pipecat/utils/tracing/setup.py,sha256=7TEgPNpq6M8lww8OQvf0P9FzYc5A30xICGklVA-fua0,2892
|
|
335
336
|
pipecat/utils/tracing/turn_context_provider.py,sha256=ikon3plFOx0XbMrH6DdeHttNpb-U0gzMZIm3bWLc9eI,2485
|
|
336
337
|
pipecat/utils/tracing/turn_trace_observer.py,sha256=dma16SBJpYSOE58YDWy89QzHyQFc_9gQZszKeWixuwc,9725
|
|
337
|
-
dv_pipecat_ai-0.0.75.
|
|
338
|
-
dv_pipecat_ai-0.0.75.
|
|
339
|
-
dv_pipecat_ai-0.0.75.
|
|
340
|
-
dv_pipecat_ai-0.0.75.
|
|
338
|
+
dv_pipecat_ai-0.0.75.dev887.dist-info/METADATA,sha256=CdbfPCjvwY1iD7h6U82yAZ0f0EIOtA-e0zr61GDdLuA,32457
|
|
339
|
+
dv_pipecat_ai-0.0.75.dev887.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
340
|
+
dv_pipecat_ai-0.0.75.dev887.dist-info/top_level.txt,sha256=kQzG20CxGf-nSsHmtXHx3hY2-8zHA3jYg8jk0TajqXc,8
|
|
341
|
+
dv_pipecat_ai-0.0.75.dev887.dist-info/RECORD,,
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# asterisk_ws_serializer.py
|
|
2
|
+
import base64
|
|
3
|
+
import json
|
|
4
|
+
from typing import Literal, Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from pipecat.audio.utils import create_stream_resampler, pcm_to_ulaw, ulaw_to_pcm
|
|
9
|
+
from pipecat.frames.frames import (
|
|
10
|
+
AudioRawFrame,
|
|
11
|
+
CancelFrame,
|
|
12
|
+
EndFrame,
|
|
13
|
+
Frame,
|
|
14
|
+
InputAudioRawFrame,
|
|
15
|
+
StartFrame,
|
|
16
|
+
StartInterruptionFrame,
|
|
17
|
+
TransportMessageFrame,
|
|
18
|
+
TransportMessageUrgentFrame,
|
|
19
|
+
)
|
|
20
|
+
from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializerType
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AsteriskFrameSerializer(FrameSerializer):
|
|
24
|
+
class InputParams(BaseModel):
|
|
25
|
+
"""Configuration parameters for AsteriskFrameSerializer.
|
|
26
|
+
|
|
27
|
+
Parameters:
|
|
28
|
+
telephony_encoding: The encoding used by the telephony system (e.g., "pcmu" for μ-law).
|
|
29
|
+
telephony_sample_rate: The sample rate used by the telephony system (e.g., 8000 Hz).
|
|
30
|
+
sample_rate: Optional override for pipeline input sample rate.
|
|
31
|
+
auto_hang_up: Whether to automatically terminate call on EndFrame.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# What the ADAPTER/Asterisk is sending/expecting on the wire:
|
|
35
|
+
# "pcmu" -> μ-law @ 8k; "pcm16" -> signed 16-bit @ 8k
|
|
36
|
+
telephony_encoding: Literal["pcmu", "pcm16"] = "pcmu"
|
|
37
|
+
telephony_sample_rate: int = 8000
|
|
38
|
+
sample_rate: Optional[int] = None # pipeline input rate
|
|
39
|
+
auto_hang_up: bool = False # no-op here; adapter handles hangup
|
|
40
|
+
|
|
41
|
+
def __init__(self, stream_id: str, params: Optional[InputParams] = None):
|
|
42
|
+
self._stream_id = stream_id
|
|
43
|
+
self._params = params or AsteriskFrameSerializer.InputParams()
|
|
44
|
+
self._tel_rate = self._params.telephony_sample_rate
|
|
45
|
+
self._sample_rate = 0
|
|
46
|
+
self._in_resampler = create_stream_resampler()
|
|
47
|
+
self._out_resampler = create_stream_resampler()
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def type(self) -> FrameSerializerType:
|
|
51
|
+
return FrameSerializerType.TEXT # we send/recv JSON strings
|
|
52
|
+
|
|
53
|
+
async def setup(self, frame: StartFrame):
|
|
54
|
+
self._sample_rate = self._params.sample_rate or frame.audio_in_sample_rate
|
|
55
|
+
|
|
56
|
+
# Pipecat -> Adapter (play to caller)
|
|
57
|
+
async def serialize(self, frame: Frame) -> str | bytes | None:
|
|
58
|
+
# On pipeline end, ask bridge to hang up
|
|
59
|
+
if (
|
|
60
|
+
self._params.auto_hang_up
|
|
61
|
+
and not self._hangup_sent
|
|
62
|
+
and isinstance(frame, (EndFrame, CancelFrame))
|
|
63
|
+
):
|
|
64
|
+
self._hangup_sent = True
|
|
65
|
+
return json.dumps({"event": "hangup"})
|
|
66
|
+
if isinstance(frame, StartInterruptionFrame):
|
|
67
|
+
return json.dumps({"event": "clear", "streamId": self._stream_id})
|
|
68
|
+
if isinstance(frame, AudioRawFrame):
|
|
69
|
+
pcm = frame.audio
|
|
70
|
+
if self._params.telephony_encoding == "pcmu":
|
|
71
|
+
ul = await pcm_to_ulaw(pcm, frame.sample_rate, self._tel_rate, self._out_resampler)
|
|
72
|
+
if not ul:
|
|
73
|
+
return None
|
|
74
|
+
payload = base64.b64encode(ul).decode("utf-8")
|
|
75
|
+
return json.dumps(
|
|
76
|
+
{
|
|
77
|
+
"event": "media",
|
|
78
|
+
"encoding": "pcmu",
|
|
79
|
+
"sampleRate": self._tel_rate,
|
|
80
|
+
"payload": payload,
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
else: # "pcm16"
|
|
84
|
+
# resample to 8k if needed, but data stays PCM16 bytes
|
|
85
|
+
pcm8 = await self._out_resampler.resample(pcm, frame.sample_rate, self._tel_rate)
|
|
86
|
+
if not pcm8:
|
|
87
|
+
return None
|
|
88
|
+
payload = base64.b64encode(pcm8).decode("utf-8")
|
|
89
|
+
return json.dumps(
|
|
90
|
+
{
|
|
91
|
+
"event": "media",
|
|
92
|
+
"encoding": "pcm16",
|
|
93
|
+
"sampleRate": self._tel_rate,
|
|
94
|
+
"payload": payload,
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
if isinstance(frame, (TransportMessageFrame, TransportMessageUrgentFrame)):
|
|
98
|
+
return json.dumps(frame.message)
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
# Adapter -> Pipecat (audio from caller)
|
|
102
|
+
async def deserialize(self, data: str | bytes) -> Frame | None:
|
|
103
|
+
try:
|
|
104
|
+
msg = json.loads(data)
|
|
105
|
+
except Exception:
|
|
106
|
+
return None
|
|
107
|
+
if msg.get("event") == "media":
|
|
108
|
+
enc = msg.get("encoding")
|
|
109
|
+
sr = int(msg.get("sampleRate", self._tel_rate))
|
|
110
|
+
raw = base64.b64decode(msg.get("payload", ""))
|
|
111
|
+
if not raw:
|
|
112
|
+
return None
|
|
113
|
+
if enc == "pcmu":
|
|
114
|
+
pcm = await ulaw_to_pcm(raw, sr, self._sample_rate, self._in_resampler)
|
|
115
|
+
elif enc == "pcm16":
|
|
116
|
+
# resample if pipeline rate != 8k
|
|
117
|
+
pcm = await self._in_resampler.resample(raw, sr, self._sample_rate)
|
|
118
|
+
else:
|
|
119
|
+
return None
|
|
120
|
+
if not pcm:
|
|
121
|
+
return None
|
|
122
|
+
return InputAudioRawFrame(audio=pcm, num_channels=1, sample_rate=self._sample_rate)
|
|
123
|
+
elif msg.get("event") == "dtmf":
|
|
124
|
+
# optional: map to InputDTMFFrame if you want
|
|
125
|
+
return None
|
|
126
|
+
elif msg.get("event") == "hangup":
|
|
127
|
+
# Bridge is hanging up; you can treat as EndFrame if you want.
|
|
128
|
+
return CancelFrame()
|
|
129
|
+
return None
|
|
File without changes
|
{dv_pipecat_ai-0.0.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{dv_pipecat_ai-0.0.75.dev883.dist-info → dv_pipecat_ai-0.0.75.dev887.dist-info}/top_level.txt
RENAMED
|
File without changes
|