async def run_tts(self, text: str) -> AsyncGenerator[Frame, None]:
        """Generate speech from text using Piper API.

        Args:
            text: The text to convert to speech

        Yields:
            Frames containing audio data and status information
        """
        logger.debug(f"{self}: Generating TTS [{text}]")
        headers = {
            "Content-Type": "text/plain",
        }
        try:
            await self.start_ttfb_metrics()

            async with self._session.post(self._base_url, data=text, headers=headers) as response:
                if response.status != 200:
                    error = await response.text()
                    logger.error(
                        f"{self} error getting audio (status: {response.status}, error: {error})"
                    )
                    yield ErrorFrame(
                        f"Error getting audio (status: {response.status}, error: {error})"
                    )
                    return

                await self.start_tts_usage_metrics(text)

                CHUNK_SIZE = self.chunk_size

                yield TTSStartedFrame()
                async for chunk in response.content.iter_chunked(CHUNK_SIZE):
                    # remove wav header if present
                    if chunk.startswith(b"RIFF"):
                        chunk = chunk[44:]
                    if len(chunk) > 0:
                        await self.stop_ttfb_metrics()
                        yield TTSAudioRawFrame(chunk, self.sample_rate, 1)
        except Exception as e:
            logger.error(f"Error in run_tts: {e}")
            yield ErrorFrame(error=str(e))
        finally:
            logger.debug(f"{self}: Finished TTS [{text}]")
            await self.stop_ttfb_metrics()
            yield TTSStoppedFrame()
Generate speech from text using Piper API.

        Args:
            text: The text to convert to speech

        Yields:
            Frames containing audio data and status information
        
src/pipecat/services/piper/tts.py