audio(dtmf): added DTMF audio files and load_dtmf_audio()
This commit is contained in:
@@ -20,6 +20,7 @@ classifiers = [
|
||||
"Topic :: Scientific/Engineering :: Artificial Intelligence"
|
||||
]
|
||||
dependencies = [
|
||||
"aiofiles>=24.1.0,<25",
|
||||
"aiohttp>=3.11.12,<4",
|
||||
"audioop-lts~=0.2.1; python_version>='3.13'",
|
||||
"docstring_parser~=0.16",
|
||||
@@ -137,6 +138,20 @@ where = ["src"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"pipecat" = ["py.typed"]
|
||||
"pipecat.audio.dtmf" = [
|
||||
"src/pipecat/audio/dtmf/dtmf-0.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-1.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-2.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-3.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-4.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-5.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-6.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-7.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-8.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-9.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-pound.wav",
|
||||
"src/pipecat/audio/dtmf/dtmf-star.wav",
|
||||
]
|
||||
"pipecat.services.aws_nova_sonic" = ["src/pipecat/services/aws_nova_sonic/ready.wav"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
|
||||
BIN
src/pipecat/audio/dtmf/dtmf-0.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-0.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-1.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-1.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-2.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-2.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-3.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-3.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-4.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-4.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-5.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-5.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-6.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-6.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-7.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-7.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-8.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-8.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-9.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-9.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-pound.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-pound.wav
Normal file
Binary file not shown.
BIN
src/pipecat/audio/dtmf/dtmf-star.wav
Normal file
BIN
src/pipecat/audio/dtmf/dtmf-star.wav
Normal file
Binary file not shown.
70
src/pipecat/audio/dtmf/utils.py
Normal file
70
src/pipecat/audio/dtmf/utils.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# Copyright (c) 2024–2025, Daily
|
||||
#
|
||||
# SPDX-License-Identifier: BSD 2-Clause License
|
||||
#
|
||||
|
||||
"""DTMF audio utilities.
|
||||
|
||||
This module provides functionality to load DTMF (Dual-Tone Multi-Frequency)
|
||||
audio files corresponding to phone keypad entries. Audio data is cached
|
||||
in-memory after first load to improve performance on subsequent accesses.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import io
|
||||
import wave
|
||||
from importlib.resources import files
|
||||
from typing import Dict, Optional
|
||||
|
||||
import aiofiles
|
||||
|
||||
from pipecat.audio.dtmf.types import KeypadEntry
|
||||
from pipecat.audio.resamplers.base_audio_resampler import BaseAudioResampler
|
||||
from pipecat.audio.utils import create_file_resampler
|
||||
|
||||
__DTMF_LOCK__ = asyncio.Lock()
|
||||
__DTMF_AUDIO__: Dict[KeypadEntry, bytes] = {}
|
||||
__DTMF_RESAMPLER__: Optional[BaseAudioResampler] = None
|
||||
|
||||
__DTMF_FILE_NAME = {
|
||||
KeypadEntry.POUND: "dtmf-pound.wav",
|
||||
KeypadEntry.STAR: "dtmf-star.wav",
|
||||
}
|
||||
|
||||
|
||||
async def load_dtmf_audio(button: KeypadEntry, *, sample_rate: int = 8000) -> bytes:
|
||||
"""Load audio for DTMF tones associated with the given button.
|
||||
|
||||
Args:
|
||||
button (KeypadEntry): The button for which the DTMF audio is to be loaded.
|
||||
sample_rate (int, optional): The sample rate for the audio. Defaults to 8000.
|
||||
|
||||
Returns:
|
||||
bytes: The audio data for the DTMF tone as bytes.
|
||||
"""
|
||||
global __DTMF_AUDIO__, __DTMF_RESAMPLER__
|
||||
|
||||
async with __DTMF_LOCK__:
|
||||
if button in __DTMF_AUDIO__:
|
||||
return __DTMF_AUDIO__[button]
|
||||
|
||||
if not __DTMF_RESAMPLER__:
|
||||
__DTMF_RESAMPLER__ = create_file_resampler()
|
||||
|
||||
dtmf_file_name = __DTMF_FILE_NAME.get(button, f"dtmf-{button.value}.wav")
|
||||
dtmf_file_path = files("pipecat.audio.dtmf").joinpath(dtmf_file_name)
|
||||
|
||||
async with aiofiles.open(dtmf_file_path, "rb") as f:
|
||||
data = await f.read()
|
||||
|
||||
with io.BytesIO(data) as buffer:
|
||||
with wave.open(buffer, "rb") as wf:
|
||||
audio = wf.readframes(wf.getnframes())
|
||||
in_sample_rate = wf.getframerate()
|
||||
resampled_audio = await __DTMF_RESAMPLER__.resample(
|
||||
audio, in_sample_rate, sample_rate
|
||||
)
|
||||
__DTMF_AUDIO__[button] = resampled_audio
|
||||
|
||||
return __DTMF_AUDIO__[button]
|
||||
2
uv.lock
generated
2
uv.lock
generated
@@ -4189,6 +4189,7 @@ wheels = [
|
||||
name = "pipecat-ai"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "aiofiles" },
|
||||
{ name = "aiohttp" },
|
||||
{ name = "audioop-lts", marker = "python_full_version >= '3.13'" },
|
||||
{ name = "docstring-parser" },
|
||||
@@ -4409,6 +4410,7 @@ docs = [
|
||||
requires-dist = [
|
||||
{ name = "accelerate", marker = "extra == 'moondream'", specifier = "~=1.10.0" },
|
||||
{ name = "aioboto3", marker = "extra == 'aws'", specifier = "~=15.0.0" },
|
||||
{ name = "aiofiles", specifier = ">=24.1.0,<25" },
|
||||
{ name = "aiohttp", specifier = ">=3.11.12,<4" },
|
||||
{ name = "aiortc", marker = "extra == 'webrtc'", specifier = "~=1.11.0" },
|
||||
{ name = "anthropic", marker = "extra == 'anthropic'", specifier = "~=0.49.0" },
|
||||
|
||||
Reference in New Issue
Block a user