import gradio as gr import numpy as np import io import base64 import requests import re from scipy.io import wavfile from murf import Murf # Global variable to track the number of tries. attempt_count = 0 # Initialize the Murf client with your initial API key. client = Murf(api_key="ap2_94209101-077d-4962-9f4b-daeec8caeda2") def extract_voice_id(selection): """ Extracts the voice ID from the dropdown selection. Expects a string in the format "Label (voice_id)". """ match = re.search(r'\((.*?)\)', selection) if match: return match.group(1) return selection def generate_voice_murf(text, voice_selection): global attempt_count, client # Check if the try limit is reached. if attempt_count >= 5: raise gr.Error("Limit of 5 tries reached. Please update your API key. To fetch your new API key, visit https://murf.ai/api/dashboard.") attempt_count += 1 # Extract the voice_id from the dropdown selection. voice_id = extract_voice_id(voice_selection) try: # Limit text to 250 characters. text = text[:250] # Call the Murf API to generate speech. response = client.text_to_speech.generate( text=text, voice_id=voice_id, format="WAV" ) # Try to access the audio data. if hasattr(response, "encoded_audio") and response.encoded_audio: audio_bytes = base64.b64decode(response.encoded_audio) elif hasattr(response, "audio_file") and response.audio_file: audio_url = response.audio_file r = requests.get(audio_url) if r.status_code != 200: raise Exception("Error downloading audio file.") audio_bytes = r.content else: raise Exception("No audio returned by the API.") # Convert the audio bytes to a NumPy array for Gradio. audio_file = io.BytesIO(audio_bytes) sample_rate, audio_data = wavfile.read(audio_file) return (sample_rate, audio_data) except Exception as e: raise gr.Error(str(e)) def update_api_key(new_key): global client, attempt_count if new_key.strip() == "": raise gr.Error("Please provide a valid API key.") client = Murf(api_key=new_key) attempt_count = 0 # Reset try counter return "API key updated successfully. You can now try again." # Define sample voice options as friendly strings. voice_options = [ "Natalie (en-US-natalie)", "Matt (en-UK-matt)" ] with gr.Blocks() as demo: gr.Markdown("# Murf TTS Demo") gr.Markdown("A demo using the Murf API to generate speech from text. Enter some text (max 250 characters) and choose a voice.") input_text = gr.Textbox( label="Input Text (250 characters max)", lines=2, value="Hello, welcome to the Murf TTS demo!", elem_id="input_text" ) voice_dropdown = gr.Dropdown( label="Voice", choices=voice_options, value=voice_options[0], elem_id="voice_dropdown" ) generate_button = gr.Button("Generate Voice", elem_id="generate_button") out_audio = gr.Audio(label="Generated Voice", type="numpy", elem_id="out_audio") generate_button.click( fn=generate_voice_murf, inputs=[input_text, voice_dropdown], outputs=out_audio, queue=True ) # Update API Key section – only needed after a "Limit of 5 tries reached" error. gr.Markdown("### Update API Key (Only update after receiving a 'Limit of 5 tries reached' error)") gr.Markdown("To fetch your new API key, visit [Murf Dashboard](https://murf.ai/api/dashboard).") new_api_key = gr.Textbox( label="New API Key", placeholder="Enter new API key here...", elem_id="new_api_key" ) update_button = gr.Button("Update API Key", elem_id="update_button") api_key_status = gr.Textbox(label="Status", interactive=False, elem_id="api_key_status") update_button.click( fn=update_api_key, inputs=new_api_key, outputs=api_key_status, queue=True ) demo.launch()