Spaces:
Running
Running
| import os | |
| import gradio as gr | |
| from google import genai | |
| from google.genai import types | |
| import wave | |
| import io | |
| # --- Configuration --- | |
| VOICE_NAME = 'Fenrir' | |
| # --- API Client Initialization --- | |
| try: | |
| client = genai.Client(api_key=os.environ.get("GEMINI_API_KEY")) | |
| except Exception as e: | |
| print(f"Error initializing Gemini client: {e}. Ensure GEMINI_API_KEY secret is set.") | |
| client = None | |
| # --- Helper Function for Saving Audio --- | |
| def wave_file(filename, pcm, channels=1, rate=24000, sample_width=2): | |
| """Saves PCM data to a WAV file.""" | |
| with wave.open(filename, "wb") as wf: | |
| wf.setnchannels(channels) | |
| wf.setsampwidth(sample_width) | |
| wf.setframerate(rate) | |
| wf.writeframes(pcm) | |
| # --- The Gradio Interface Function --- | |
| def gemini_tts_kurmanji(kurmanji_text: str) -> str: | |
| """ | |
| Takes a Kurmanji text prompt, handles API errors, and checks the response content. | |
| """ | |
| if not client: | |
| raise gr.Error("Gemini API Client failed to initialize. Check the GEMINI_API_KEY secret.") | |
| print(f"Attempting to generate Kurmanji speech: '{kurmanji_text}' with voice {VOICE_NAME}") | |
| try: | |
| prompt = f"Speak the following text in Kurdish Kurmanji: {kurmanji_text}" | |
| response = client.models.generate_content( | |
| model="gemini-2.5-flash-preview-tts", | |
| contents=prompt, | |
| config=types.GenerateContentConfig( | |
| response_modalities=["AUDIO"], | |
| speech_config=types.SpeechConfig( | |
| voice_config=types.VoiceConfig( | |
| prebuilt_voice_config=types.PrebuiltVoiceConfig( | |
| voice_name=VOICE_NAME, | |
| ) | |
| ) | |
| ), | |
| ) | |
| ) | |
| # --- NEW: Robust Error Checking --- | |
| if not response.candidates or not response.candidates[0].content: | |
| # Check for block reasons (e.g., safety, policy) | |
| block_reason = response.candidates[0].finish_reason.name if response.candidates else "NO_CANDIDATE" | |
| # This is the most important part for debugging your 'NoneType' error: | |
| raise gr.Error( | |
| f"TTS Generation Failed. Reason: The model returned an empty response. " | |
| f"The finish reason was: {block_reason}. " | |
| f"This may indicate a quota limit, or the model could not generate the requested Kurmanji speech." | |
| ) | |
| # Proceed if the content part is valid | |
| data = response.candidates[0].content.parts[0].inline_data.data | |
| file_name = 'kurmanji_output.wav' | |
| wave_file(file_name, data) | |
| return file_name | |
| except Exception as e: | |
| error_message = f"An API error occurred during TTS generation: {e}" | |
| print(error_message) | |
| # Display the error in the Gradio interface | |
| raise gr.Error(error_message) | |
| # --- Gradio Interface Definition --- | |
| demo = gr.Interface( | |
| fn=gemini_tts_kurmanji, | |
| inputs=gr.Textbox( | |
| lines=3, | |
| placeholder="Mînak: Silav, roj baş. Ez dixwazim Kurdî biaxivim.", | |
| label="Kurmanji Text to Convert" | |
| ), | |
| outputs=gr.Audio( | |
| type="filepath", | |
| label="Generated Kurmanji Speech" | |
| ), | |
| title=f"🗣️ Gemini TTS for Kurdish Kurmanji (Voice: {VOICE_NAME})", | |
| description="Uses Gemini 2.5 Flash and natural language prompting. Check the logs for specific failure reasons." | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |