import gradio as gr # Define available voices voices = [ {"name": "Jessica", "gender": "Female", "country": "US", "file": "jessica.mp3"}, {"name": "Michael", "gender": "Male", "country": "UK", "file": "michael.mp3"}, {"name": "Sophia", "gender": "Female", "country": "Canada", "file": "sophia.mp3"}, {"name": "David", "gender": "Male", "country": "Australia", "file": "david.mp3"}, {"name": "Emma", "gender": "Female", "country": "Germany", "file": "emma.mp3"}, {"name": "Lucas", "gender": "Male", "country": "France", "file": "lucas.mp3"}, {"name": "Liam", "gender": "Male", "country": "India", "file": "liam.mp3"}, {"name": "Olivia", "gender": "Female", "country": "Brazil", "file": "olivia.mp3"}, {"name": "Noah", "gender": "Male", "country": "Japan", "file": "noah.mp3"}, {"name": "Ava", "gender": "Female", "country": "South Korea", "file": "ava.mp3"}, ] # Function to return audio file path def play_audio(file): return f"voices/{file}" # Custom CSS for better design and responsiveness custom_css = """ h2 { text-align: center; color: #ffffff; font-size: 26px; margin-bottom: 20px; } body { background-color: #121212; font-family: Arial, sans-serif; } .voice-container { display: grid; grid-template-columns: repeat(2, 1fr); /* Default: 2 per row */ gap: 15px; padding: 20px; } @media (min-width: 1024px) { .voice-container { grid-template-columns: repeat(3, 1fr); /* 3 per row on PC */ } } .voice-box { background: #1e1e1e; border-radius: 12px; padding: 15px; text-align: center; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.3); display: flex; flex-direction: column; justify-content: center; align-items: center; width: 100%; max-width: 220px; height: 220px; margin: auto; transition: transform 0.2s ease-in-out; } .voice-box:hover { transform: scale(1.05); } .play-btn { background-color: #FF5722 !important; color: white; border-radius: 50%; width: 60px; height: 60px; font-size: 26px; border: none; cursor: pointer; margin-bottom: 10px; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.2); transition: background 0.3s ease-in-out; position: relative; } .play-btn.playing { background-color: #4CAF50 !important; /* Green when playing */ } .play-btn.playing::after { content: ""; position: absolute; top: -5px; left: -5px; width: 70px; height: 70px; border-radius: 50%; border: 4px solid #2196F3; /* Blue ring */ animation: pulse 1s infinite alternate; } @keyframes pulse { 0% { transform: scale(1); opacity: 0.7; } 100% { transform: scale(1.2); opacity: 1; } } .voice-info { color: #ffffff; text-align: center; } .voice-info b { font-weight: bold; font-size: 16px; } .voice-info span { font-size: 14px; color: #bbbbbb; } """ # State to track playing voices playing_states = {voice["file"]: False for voice in voices} # Function to toggle play/pause def toggle_audio(file): global playing_states playing_states[file] = not playing_states[file] return (f"voices/{file}" if playing_states[file] else None), gr.update(elem_classes="play-btn playing" if playing_states[file] else "play-btn") # Create Gradio UI with gr.Blocks(css=custom_css) as demo: gr.Markdown("