Ejemplo n.º 1
0
    async def speak_sentence(self,
                             sentence: str,
                             language: typing.Optional[str] = None):
        """Speak a sentence using text to speech."""
        tts_id = str(uuid4())

        def handle_finished():
            while True:
                _, message = yield

                if isinstance(message, TtsSayFinished) and (message.id
                                                            == tts_id):
                    return True, None

        say = TtsSay(id=tts_id, text=sentence, siteId=self.siteId)
        if language:
            say.lang = language

        messages = [say]
        topics = [TtsSayFinished.topic()]

        # Expecting only a single result
        async for result in self.publish_wait(handle_finished(), messages,
                                              topics):
            return result
Ejemplo n.º 2
0
    async def speak_sentence(
        self,
        sentence: str,
        language: typing.Optional[str] = None,
        capture_audio: bool = False,
        wait_play_finished: bool = True,
        site_id: typing.Optional[str] = None,
        session_id: str = "",
    ) -> typing.Tuple[TtsSayFinished, typing.Optional[AudioPlayBytes]]:
        """Speak a sentence using text to speech."""
        if (self.sound_system == "dummy") and (
            not self.satellite_site_ids["text_to_speech"]
        ):
            raise TtsException("No text to speech system configured")

        site_id = site_id or self.site_id
        tts_id = str(uuid4())

        def handle_finished():
            say_finished: typing.Optional[TtsSayFinished] = None
            play_bytes: typing.Optional[
                AudioPlayBytes
            ] = None if capture_audio else True
            play_finished = not wait_play_finished

            while True:
                topic, message = yield

                if isinstance(message, TtsSayFinished) and (message.id == tts_id):
                    say_finished = message
                    play_finished = True
                elif isinstance(message, TtsError):
                    # Assume audio playback didn't happen
                    say_finished = message
                    play_bytes = True
                    play_finished = True
                elif isinstance(message, AudioPlayBytes):
                    request_id = AudioPlayBytes.get_request_id(topic)
                    if request_id == tts_id:
                        play_bytes = message
                elif isinstance(message, AudioPlayError):
                    play_bytes = message

                if say_finished and play_bytes and play_finished:
                    return (say_finished, play_bytes)

        say = TtsSay(id=tts_id, text=sentence, site_id=site_id, session_id=session_id)
        if language:
            say.lang = language

        messages = [say]
        message_types: typing.List[typing.Type[Message]] = [
            TtsSayFinished,
            TtsError,
            AudioPlayBytes,
            AudioPlayError,
        ]

        # Expecting only a single result
        result = None
        async for response in self.publish_wait(
            handle_finished(), messages, message_types
        ):
            result = response

        assert isinstance(result, tuple), f"Expected tuple, got {result}"
        say_response, play_response = result

        if isinstance(say_response, TtsError):
            _LOGGER.error(say_response)
            raise TtsException(say_response.error)

        assert isinstance(say_response, TtsSayFinished), say_response

        if isinstance(play_response, AudioPlayError):
            _LOGGER.error(play_response)
            raise AudioServerException(play_response.error)

        if capture_audio:
            assert isinstance(play_response, AudioPlayBytes), play_response

        return typing.cast(
            typing.Tuple[TtsSayFinished, typing.Optional[AudioPlayBytes]], result
        )