import gradio as gr import subprocess import os import tempfile def speak_text_via_festival(text): """ Uses Festival to speak the given text and returns the path to the generated audio file. """ if not text: return None # Create a temporary WAV file for Festival output # Using tempfile to ensure unique and safely managed temporary files with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_audio_file: audio_filepath = temp_audio_file.name try: # Command to make Festival speak and output to a WAV file # (audio_mode 'wav) makes it output to a file instead of direct playback # (utt.save.wave utt "filename.wav") saves the utterance festival_command = f""" (set! utt (SayText "{text}")) (utt.save.wave utt "{audio_filepath}") """ process = subprocess.Popen(['festival', '--pipe'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = process.communicate(input=festival_command) if process.returncode != 0: print(f"Error speaking text with Festival: {stderr}") if os.path.exists(audio_filepath): os.remove(audio_filepath) # Clean up partial file return None # Gradio's gr.Audio component expects a path to the audio file return audio_filepath except FileNotFoundError: print("Error: Festival executable not found. Make sure Festival is installed and in your PATH.") if os.path.exists(audio_filepath): os.remove(audio_filepath) return None except Exception as e: print(f"An unexpected error occurred: {e}") if os.path.exists(audio_filepath): os.remove(audio_filepath) return None # Define the Gradio Interface iface = gr.Interface( fn=speak_text_via_festival, inputs=gr.Textbox(lines=2, label="Enter text for Festival TTS:"), outputs=gr.Audio(label="Generated Audio", type="filepath", autoplay=True), title="Festival TTS with Gradio", description="Enter text to synthesize speech using the local Festival system." ) # Launch the Gradio app if __name__ == "__main__": iface.launch()