From 2e1f397d17a5f46f05c96641e29a8b6bf76c80ef Mon Sep 17 00:00:00 2001 From: Jessie Wei Date: Wed, 10 Sep 2025 14:30:10 +0000 Subject: [PATCH 1/3] Support TwilioFrameSerializer region/edge settings to that the call is terminated successfully for regions other than default us1 region --- src/pipecat/serializers/twilio.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pipecat/serializers/twilio.py b/src/pipecat/serializers/twilio.py index 57e7c8dba..7493ded3a 100644 --- a/src/pipecat/serializers/twilio.py +++ b/src/pipecat/serializers/twilio.py @@ -61,6 +61,8 @@ class TwilioFrameSerializer(FrameSerializer): call_sid: Optional[str] = None, account_sid: Optional[str] = None, auth_token: Optional[str] = None, + region: Optional[str] = None, + edge: Optional[str] = None, params: Optional[InputParams] = None, ): """Initialize the TwilioFrameSerializer. @@ -76,6 +78,8 @@ class TwilioFrameSerializer(FrameSerializer): self._call_sid = call_sid self._account_sid = account_sid self._auth_token = auth_token + self._region = region + self._edge = edge self._params = params or TwilioFrameSerializer.InputParams() self._twilio_sample_rate = self._params.twilio_sample_rate @@ -172,10 +176,13 @@ class TwilioFrameSerializer(FrameSerializer): f"Cannot hang up Twilio call: missing required parameters: {', '.join(missing)}" ) return + + region_prefix = f"{self._region}." if self._region else "" + edge_prefix = f"{self._edge}." if self._edge else "" # Twilio API endpoint for updating calls endpoint = ( - f"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Calls/{call_sid}.json" + f"https://api.{edge_prefix}{region_prefix}twilio.com/2010-04-01/Accounts/{account_sid}/Calls/{call_sid}.json" ) # Create basic auth from account_sid and auth_token From 305108be9a2bfd42c224d0c2a61a40f58f013617 Mon Sep 17 00:00:00 2001 From: Jessie Wei Date: Wed, 10 Sep 2025 23:00:15 +0000 Subject: [PATCH 2/3] [TwilioFrameSerializer]: Add parameter validation --- src/pipecat/serializers/twilio.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pipecat/serializers/twilio.py b/src/pipecat/serializers/twilio.py index 7493ded3a..6903b9480 100644 --- a/src/pipecat/serializers/twilio.py +++ b/src/pipecat/serializers/twilio.py @@ -162,6 +162,8 @@ class TwilioFrameSerializer(FrameSerializer): account_sid = self._account_sid auth_token = self._auth_token call_sid = self._call_sid + region = self._region + edge = self._edge if not call_sid or not account_sid or not auth_token: missing = [] @@ -176,9 +178,15 @@ class TwilioFrameSerializer(FrameSerializer): f"Cannot hang up Twilio call: missing required parameters: {', '.join(missing)}" ) return - - region_prefix = f"{self._region}." if self._region else "" - edge_prefix = f"{self._edge}." if self._edge else "" + + if (region and not edge) or (edge and not region): + logger.warning( + "Cannot hang up Twilio call: both edge and region are required if one is set" + ) + return + + region_prefix = f"{region}." if region else "" + edge_prefix = f"{edge}." if edge else "" # Twilio API endpoint for updating calls endpoint = ( From 5b4655f45ad6c5920b8aac0254a0c684c2ca30cd Mon Sep 17 00:00:00 2001 From: Jessie Wei Date: Wed, 24 Sep 2025 00:22:56 +0000 Subject: [PATCH 3/3] chore: Update per review comments --- src/pipecat/serializers/twilio.py | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/pipecat/serializers/twilio.py b/src/pipecat/serializers/twilio.py index 1ec5d3edd..7b468f8ac 100644 --- a/src/pipecat/serializers/twilio.py +++ b/src/pipecat/serializers/twilio.py @@ -72,8 +72,30 @@ class TwilioFrameSerializer(FrameSerializer): call_sid: The associated Twilio Call SID (optional, but required for auto hang-up). account_sid: Twilio account SID (required for auto hang-up). auth_token: Twilio auth token (required for auto hang-up). + region: Twilio region (e.g., "au1", "ie1"). Must be specified with edge. + edge: Twilio edge location (e.g., "sydney", "dublin"). Must be specified with region. params: Configuration parameters. """ + if not call_sid or not account_sid or not auth_token: + missing = [] + if not call_sid: + missing.append("call_sid") + if not account_sid: + missing.append("account_sid") + if not auth_token: + missing.append("auth_token") + + raise ValueError( + f"Cannot hang up Twilio call: missing required parameters: {', '.join(missing)}" + ) + + if (region and not edge) or (edge and not region): + raise ValueError( + "Both edge and region parameters are required if one is set. " + f"Twilio's FQDN format requires both: api.{{edge}}.{{region}}.twilio.com. " + f"Got: region='{region}', edge='{edge}'" + ) + self._stream_sid = stream_sid self._call_sid = call_sid self._account_sid = account_sid @@ -165,33 +187,11 @@ class TwilioFrameSerializer(FrameSerializer): region = self._region edge = self._edge - if not call_sid or not account_sid or not auth_token: - missing = [] - if not call_sid: - missing.append("call_sid") - if not account_sid: - missing.append("account_sid") - if not auth_token: - missing.append("auth_token") - - logger.warning( - f"Cannot hang up Twilio call: missing required parameters: {', '.join(missing)}" - ) - return - - if (region and not edge) or (edge and not region): - logger.warning( - "Cannot hang up Twilio call: both edge and region are required if one is set" - ) - return - region_prefix = f"{region}." if region else "" edge_prefix = f"{edge}." if edge else "" # Twilio API endpoint for updating calls - endpoint = ( - f"https://api.{edge_prefix}{region_prefix}twilio.com/2010-04-01/Accounts/{account_sid}/Calls/{call_sid}.json" - ) + endpoint = f"https://api.{edge_prefix}{region_prefix}twilio.com/2010-04-01/Accounts/{account_sid}/Calls/{call_sid}.json" # Create basic auth from account_sid and auth_token auth = aiohttp.BasicAuth(account_sid, auth_token)