Merge pull request #1154 from pipecat-ai/aleix/twilio-telnyx-sample-rates

serializers: don't update twilio/telnyx sample rates
This commit is contained in:
Aleix Conchillo Flaqué
2025-02-06 09:27:42 -08:00
committed by GitHub
8 changed files with 11 additions and 18 deletions

View File

@@ -13,9 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
resampled to the desired output sample rate. resampled to the desired output sample rate.
- Fixed an issue with the `TwilioFrameSerializer` and `TelnyxFrameSerializer` - Fixed an issue with the `TwilioFrameSerializer` and `TelnyxFrameSerializer`
where `frame.audio_out_sample_rate` was incorrectly used in place of where `twilio_sample_rate` and `telnyx_sample_rate` were incorrectly
`frame.audio_in_sample_rate`, which caused audio input detection to fail when initialized to `audio_in_sample_rate`. Those values currently default to 8000
using different input and output sample rates. and should be set manually from the serializer constructor if a different
value is needed.
## [0.0.55] - 2025-02-05 ## [0.0.55] - 2025-02-05

View File

@@ -65,7 +65,6 @@ async def main():
# English # English
# #
voice_id="cgSgspJ2msm6clMCkdW9", voice_id="cgSgspJ2msm6clMCkdW9",
aiohttp_session=session,
# #
# Spanish # Spanish
# #

View File

@@ -82,7 +82,6 @@ async def main():
# English # English
# #
voice_id="cgSgspJ2msm6clMCkdW9", voice_id="cgSgspJ2msm6clMCkdW9",
aiohttp_session=session,
# #
# Spanish # Spanish
# #

View File

@@ -51,7 +51,6 @@ async def main():
) )
elevenlabs_tts = ElevenLabsTTSService( elevenlabs_tts = ElevenLabsTTSService(
aiohttp_session=session,
api_key=os.getenv("ELEVENLABS_API_KEY"), api_key=os.getenv("ELEVENLABS_API_KEY"),
voice_id=os.getenv("ELEVENLABS_VOICE_ID"), voice_id=os.getenv("ELEVENLABS_VOICE_ID"),
) )

View File

@@ -48,7 +48,6 @@ async def main():
region=os.getenv("AZURE_SPEECH_REGION"), region=os.getenv("AZURE_SPEECH_REGION"),
) )
tts2 = ElevenLabsTTSService( tts2 = ElevenLabsTTSService(
aiohttp_session=session,
api_key=os.getenv("ELEVENLABS_API_KEY"), api_key=os.getenv("ELEVENLABS_API_KEY"),
voice_id="jBpfuIE2acCO8z3wKNLl", voice_id="jBpfuIE2acCO8z3wKNLl",
) )

View File

@@ -8,7 +8,7 @@ from loguru import logger
from openai.types.chat import ChatCompletionToolParam from openai.types.chat import ChatCompletionToolParam
from pipecat.audio.vad.silero import SileroVADAnalyzer from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.frames.frames import EndFrame, EndTaskFrame from pipecat.frames.frames import EndTaskFrame
from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineParams, PipelineTask from pipecat.pipeline.task import PipelineParams, PipelineTask
@@ -99,14 +99,14 @@ async def main(
- **ASSUME IT IS A VOICEMAIL. DO NOT WAIT FOR MORE CONFIRMATION.** - **ASSUME IT IS A VOICEMAIL. DO NOT WAIT FOR MORE CONFIRMATION.**
#### **Step 2: Leave a Voicemail Message** #### **Step 2: Leave a Voicemail Message**
- Immediately say: - Immediately say:
*"Hello, this is a message for Pipecat example user. This is Chatbot. Please call back on 123-456-7891. Thank you."* *"Hello, this is a message for Pipecat example user. This is Chatbot. Please call back on 123-456-7891. Thank you."*
- **IMMEDIATELY AFTER LEAVING THE MESSAGE, CALL `terminate_call`.** - **IMMEDIATELY AFTER LEAVING THE MESSAGE, CALL `terminate_call`.**
- **DO NOT SPEAK AFTER CALLING `terminate_call`.** - **DO NOT SPEAK AFTER CALLING `terminate_call`.**
- **FAILURE TO CALL `terminate_call` IMMEDIATELY IS A MISTAKE.** - **FAILURE TO CALL `terminate_call` IMMEDIATELY IS A MISTAKE.**
#### **Step 3: If Speaking to a Human** #### **Step 3: If Speaking to a Human**
- If the call is answered by a human, say: - If the call is answered by a human, say:
*"Oh, hello! I'm a friendly chatbot. Is there anything I can help you with?"* *"Oh, hello! I'm a friendly chatbot. Is there anything I can help you with?"*
- Keep responses **brief and helpful**. - Keep responses **brief and helpful**.
- If the user no longer needs assistance, **call `terminate_call` immediately.** - If the user no longer needs assistance, **call `terminate_call` immediately.**

View File

@@ -31,7 +31,7 @@ from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializer
class TelnyxFrameSerializer(FrameSerializer): class TelnyxFrameSerializer(FrameSerializer):
class InputParams(BaseModel): class InputParams(BaseModel):
telnyx_sample_rate: Optional[int] = None # Default Telnyx rate (8kHz) telnyx_sample_rate: int = 8000 # Default Telnyx rate (8kHz)
sample_rate: Optional[int] = None # Pipeline input rate sample_rate: Optional[int] = None # Pipeline input rate
inbound_encoding: str = "PCMU" inbound_encoding: str = "PCMU"
outbound_encoding: str = "PCMU" outbound_encoding: str = "PCMU"
@@ -48,7 +48,7 @@ class TelnyxFrameSerializer(FrameSerializer):
params.inbound_encoding = inbound_encoding params.inbound_encoding = inbound_encoding
self._params = params self._params = params
self._telnyx_sample_rate = 0 # Fixed rate for Telnyx (8kHz) self._telnyx_sample_rate = self._params.telnyx_sample_rate
self._sample_rate = 0 # Pipeline input rate self._sample_rate = 0 # Pipeline input rate
self._resampler = create_default_resampler() self._resampler = create_default_resampler()
@@ -58,8 +58,6 @@ class TelnyxFrameSerializer(FrameSerializer):
return FrameSerializerType.TEXT return FrameSerializerType.TEXT
async def setup(self, frame: StartFrame): async def setup(self, frame: StartFrame):
# Configure rates for input path: Telnyx (8kHz encoded) -> Pipeline (PCM)
self._telnyx_sample_rate = self._params.telnyx_sample_rate or frame.audio_in_sample_rate
self._sample_rate = self._params.sample_rate or frame.audio_in_sample_rate self._sample_rate = self._params.sample_rate or frame.audio_in_sample_rate
async def serialize(self, frame: Frame) -> str | bytes | None: async def serialize(self, frame: Frame) -> str | bytes | None:

View File

@@ -27,14 +27,14 @@ from pipecat.serializers.base_serializer import FrameSerializer, FrameSerializer
class TwilioFrameSerializer(FrameSerializer): class TwilioFrameSerializer(FrameSerializer):
class InputParams(BaseModel): class InputParams(BaseModel):
twilio_sample_rate: Optional[int] = None # Default Twilio rate (8kHz) twilio_sample_rate: int = 8000 # Default Twilio rate (8kHz)
sample_rate: Optional[int] = None # Pipeline input rate sample_rate: Optional[int] = None # Pipeline input rate
def __init__(self, stream_sid: str, params: InputParams = InputParams()): def __init__(self, stream_sid: str, params: InputParams = InputParams()):
self._stream_sid = stream_sid self._stream_sid = stream_sid
self._params = params self._params = params
self._twilio_sample_rate = 0 # Fixed rate for Twilio (8kHz) self._twilio_sample_rate = self._params.twilio_sample_rate
self._sample_rate = 0 # Pipeline input rate self._sample_rate = 0 # Pipeline input rate
self._resampler = create_default_resampler() self._resampler = create_default_resampler()
@@ -44,8 +44,6 @@ class TwilioFrameSerializer(FrameSerializer):
return FrameSerializerType.TEXT return FrameSerializerType.TEXT
async def setup(self, frame: StartFrame): async def setup(self, frame: StartFrame):
# Configure rates for input path: Twilio (8kHz μ-law) -> Pipeline (PCM)
self._twilio_sample_rate = self._params.twilio_sample_rate or frame.audio_in_sample_rate
self._sample_rate = self._params.sample_rate or frame.audio_in_sample_rate self._sample_rate = self._params.sample_rate or frame.audio_in_sample_rate
async def serialize(self, frame: Frame) -> str | bytes | None: async def serialize(self, frame: Frame) -> str | bytes | None: