From c35aabe4975f986f884fead968ef93dc43c0ba03 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sat, 29 Apr 2023 14:24:56 -0500 Subject: [PATCH] Add VoIP error tone (#92260) * Play error tone when pipeline error occurs * Play listening tone at the start of each cycle --- homeassistant/components/voip/error.pcm | Bin 0 -> 64000 bytes homeassistant/components/voip/voip.py | 45 ++++++++++++++++++++---- tests/components/voip/test_voip.py | 4 +++ 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 homeassistant/components/voip/error.pcm diff --git a/homeassistant/components/voip/error.pcm b/homeassistant/components/voip/error.pcm new file mode 100644 index 0000000000000000000000000000000000000000..3d93cdb14db728632917ddb65c1ee0a591ace9e0 GIT binary patch literal 64000 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 z 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 None: @@ -120,6 +121,7 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol): self.buffered_chunks_before_speech = buffered_chunks_before_speech self.listening_tone_enabled = listening_tone_enabled self.processing_tone_enabled = processing_tone_enabled + self.error_tone_enabled = error_tone_enabled self.tone_delay = tone_delay self.tts_extra_timeout = tts_extra_timeout @@ -131,6 +133,8 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol): self._session_id: str | None = None self._tone_bytes: bytes | None = None self._processing_bytes: bytes | None = None + self._error_bytes: bytes | None = None + self._pipeline_error: bool = False def connection_made(self, transport): """Server is ready.""" @@ -161,8 +165,10 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol): """Forward audio to pipeline STT and handle TTS.""" if self._session_id is None: self._session_id = ulid() - if self.listening_tone_enabled: - await self._play_listening_tone() + + # Play listening tone at the start of each cycle + if self.listening_tone_enabled: + await self._play_listening_tone() try: # Wait for speech before starting pipeline @@ -221,11 +227,16 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol): tts_audio_output="raw", ) - # Block until TTS is done speaking. - # - # This is set in _send_tts and has a timeout that's based on the - # length of the TTS audio. - await self._tts_done.wait() + if self._pipeline_error: + self._pipeline_error = False + if self.error_tone_enabled: + await self._play_error_tone() + else: + # Block until TTS is done speaking. + # + # This is set in _send_tts and has a timeout that's based on the + # length of the TTS audio. + await self._tts_done.wait() _LOGGER.debug("Pipeline finished") except asyncio.TimeoutError: @@ -307,6 +318,9 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol): self._send_tts(media_id), "voip_pipeline_tts", ) + elif event.type == PipelineEventType.ERROR: + # Play error tone instead of wait for TTS + self._pipeline_error = True async def _send_tts(self, media_id: str) -> None: """Send TTS audio to caller via RTP.""" @@ -372,6 +386,23 @@ class PipelineRtpDatagramProtocol(RtpDatagramProtocol): ) ) + async def _play_error_tone(self) -> None: + """Play a tone to indicate a pipeline error occurred.""" + if self._error_bytes is None: + # Do I/O in executor + self._error_bytes = await self.hass.async_add_executor_job( + self._load_pcm, + "error.pcm", + ) + + await self.hass.async_add_executor_job( + partial( + self.send_audio, + self._error_bytes, + **RTP_AUDIO_SETTINGS, + ) + ) + def _load_pcm(self, file_name: str) -> bytes: """Load raw audio (16Khz, 16-bit mono).""" return (Path(__file__).parent / file_name).read_bytes() diff --git a/tests/components/voip/test_voip.py b/tests/components/voip/test_voip.py index 19b9806e41e..6ccfae904e8 100644 --- a/tests/components/voip/test_voip.py +++ b/tests/components/voip/test_voip.py @@ -90,6 +90,7 @@ async def test_pipeline( Context(), listening_tone_enabled=False, processing_tone_enabled=False, + error_tone_enabled=False, ) rtp_protocol.transport = Mock() @@ -140,6 +141,7 @@ async def test_pipeline_timeout(hass: HomeAssistant, voip_device: VoIPDevice) -> pipeline_timeout=0.001, listening_tone_enabled=False, processing_tone_enabled=False, + error_tone_enabled=False, ) transport = Mock(spec=["close"]) rtp_protocol.connection_made(transport) @@ -179,6 +181,7 @@ async def test_stt_stream_timeout(hass: HomeAssistant, voip_device: VoIPDevice) audio_timeout=0.001, listening_tone_enabled=False, processing_tone_enabled=False, + error_tone_enabled=False, ) transport = Mock(spec=["close"]) rtp_protocol.connection_made(transport) @@ -262,6 +265,7 @@ async def test_tts_timeout( Context(), listening_tone_enabled=False, processing_tone_enabled=False, + error_tone_enabled=False, ) rtp_protocol.transport = Mock() rtp_protocol.send_audio = Mock(side_effect=send_audio)