import abc import os import asyncio from loguru import logger class TTSInterface(metaclass=abc.ABCMeta): async def async_generate_audio(self, text: str, file_name_no_ext=None) -> str: """ Asynchronously generate speech audio file using TTS. By default, this runs the synchronous generate_audio in a coroutine. Subclasses can override this method to provide true async implementation. text: str the text to speak file_name_no_ext (optional and deprecated): str name of the file without file extension Returns: str: the path to the generated audio file """ return await asyncio.to_thread(self.generate_audio, text, file_name_no_ext) @abc.abstractmethod def generate_audio(self, text: str, file_name_no_ext=None) -> str: """ Generate speech audio file using TTS. text: str the text to speak file_name_no_ext (optional and deprecated): str name of the file without file extension Returns: str: the path to the generated audio file """ raise NotImplementedError def remove_file(self, filepath: str, verbose: bool = True) -> None: """ Remove a file from the file system. This is a separate method instead of a part of the `play_audio_file_local()` because `play_audio_file_local()` is not the only way to play audio files. This method will be used to remove the audio file after it has been played. Parameters: filepath (str): The path to the file to remove. verbose (bool): If True, print messages to the console. """ if not os.path.exists(filepath): logger.warning(f"File {filepath} does not exist") return try: logger.debug(f"Removing file {filepath}") if verbose else None os.remove(filepath) except Exception as e: logger.error(f"Failed to remove file {filepath}: {e}") def generate_cache_file_name(self, file_name_no_ext=None, file_extension="wav"): """ Generate a cross-platform cache file name. file_name_no_ext: str name of the file without extension file_extension: str file extension Returns: str: the path to the generated cache file """ cache_dir = "cache" if not os.path.exists(cache_dir): os.makedirs(cache_dir) if file_name_no_ext is None: file_name_no_ext = "temp" file_name = f"{file_name_no_ext}.{file_extension}" return os.path.join(cache_dir, file_name)