Source code for pipecat.utils.text.transforms.phone

#
# Copyright (c) 2024-2026, Daily
#
# SPDX-License-Identifier: BSD 2-Clause License
#

"""Expand phone numbers into space-separated digit sequences for TTS."""

import re

from pipecat.frames.frames import AggregationType

# Matches common phone formats: (123) 456-7890, 123-456-7890, 123.456.7890,
# +1 800 555 1234, etc.
_PHONE_RE = re.compile(
    r"(?<!\d)"  # not preceded by a digit (no partial match inside a longer number)
    r"(\+?1[\s.\-]?)?"  # optional country code
    r"(\(?\d{3}\)?[\s.\-]?)"  # area code
    r"(\d{3}[\s.\-]?)"  # exchange
    r"(\d{4})"  # subscriber
    r"(?!\d)"  # not followed by a digit
)


def _space_digits(match: re.Match) -> str:
    digits = re.sub(r"\D", "", match.group(0))
    return " ".join(digits)


[docs] async def expand_phone_numbers(text: str, aggregation_type: str | AggregationType) -> str: """Space out phone number digits so TTS reads them individually. This transformer is alphanumeric-preserving: digits are kept, only separators change to spaces, so the :class:`WordCompletionTracker` requires no segment-map overhead. Args: text: Input text possibly containing phone numbers. aggregation_type: Aggregation type of the text frame (unused). Returns: Text with phone numbers replaced by space-separated digit sequences. Example:: result = await expand_phone_numbers("Call 123-456-7890 now", "*") # "Call 1 2 3 4 5 6 7 8 9 0 now" """ return _PHONE_RE.sub(_space_digits, text)