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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-ai
3
- Version: 0.0.75.dev883
3
+ Version: 0.0.75.dev887
4
4
  Summary: An open source framework for voice (and multimodal) assistants
5
5
  License-Expression: BSD-2-Clause
6
6
  Project-URL: Source, https://github.com/pipecat-ai/pipecat
@@ -1,4 +1,4 @@
1
- dv_pipecat_ai-0.0.75.dev883.dist-info/licenses/LICENSE,sha256=DWY2QGf2eMCFhuu2ChairtT6CB7BEFffNVhXWc4Od08,1301
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.dev883.dist-info/METADATA,sha256=WazpBSK55s_idzcY9pZlaoHkljfRPeTqCj24OeXO6DU,32457
338
- dv_pipecat_ai-0.0.75.dev883.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
339
- dv_pipecat_ai-0.0.75.dev883.dist-info/top_level.txt,sha256=kQzG20CxGf-nSsHmtXHx3hY2-8zHA3jYg8jk0TajqXc,8
340
- dv_pipecat_ai-0.0.75.dev883.dist-info/RECORD,,
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