DTMF: Add support for native DTMF implementation where available

This commit is contained in:
Mark Backman
2025-09-05 17:50:24 -04:00
parent 516f0e08ab
commit fbe4338440
3 changed files with 54 additions and 2 deletions

View File

@@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Using the universal `LLMContext` and associated `LLMContextAggregatorPair` is
a pre-requisite for using `LLMSwitcher` to switch between LLMs at runtime.
### Changed
- Restored `DailyTransport`'s native DTMF support using Daily's `send_dtmf()`
method instead of generated audio tones.
### Fixed
- Fixed a `AWSBedrockLLMService` crash caused by an extra `await`.

View File

@@ -219,7 +219,34 @@ class BaseOutputTransport(FrameProcessor):
pass
async def write_dtmf(self, frame: OutputDTMFFrame | OutputDTMFUrgentFrame):
"""Write a DTMF tone to the transport.
"""Write a DTMF tone using the transport's preferred method.
Args:
frame: The DTMF frame to write.
"""
if self._supports_native_dtmf():
await self._write_dtmf_native(frame)
else:
await self._write_dtmf_audio(frame)
def _supports_native_dtmf(self) -> bool:
"""Override in transport implementations that support native DTMF.
Returns:
True if the transport supports native DTMF, False otherwise.
"""
return False
async def _write_dtmf_native(self, frame: OutputDTMFFrame | OutputDTMFUrgentFrame):
"""Override in transport implementations for native DTMF.
Args:
frame: The DTMF frame to write.
"""
raise NotImplementedError("Transport claims native DTMF support but doesn't implement it")
async def _write_dtmf_audio(self, frame: OutputDTMFFrame | OutputDTMFUrgentFrame):
"""Generate and send audio tones for DTMF.
Args:
frame: The DTMF frame to write.
@@ -228,7 +255,6 @@ class BaseOutputTransport(FrameProcessor):
dtmf_audio_frame = OutputAudioRawFrame(
audio=dtmf_audio, sample_rate=self._sample_rate, num_channels=1
)
dtmf_audio_frame.transport_destination = frame.transport_destination
await self.write_audio_frame(dtmf_audio_frame)
async def send_audio(self, frame: OutputAudioRawFrame):

View File

@@ -1809,6 +1809,27 @@ class DailyOutputTransport(BaseOutputTransport):
"""
await self._client.write_video_frame(frame)
def _supports_native_dtmf(self) -> bool:
"""Daily supports native DTMF via telephone events.
Returns:
True, as Daily supports native DTMF transmission.
"""
return True
async def _write_dtmf_native(self, frame):
"""Use Daily's native send_dtmf method for telephone events.
Args:
frame: The DTMF frame to write.
"""
await self._client.send_dtmf(
{
"sessionId": frame.transport_destination,
"tones": frame.button.value,
}
)
class DailyTransport(BaseTransport):
"""Transport implementation for Daily audio and video calls.