File size: 4,112 Bytes
f3bc85b
 
 
 
fc4c46a
 
 
 
 
 
 
 
 
 
f3bc85b
 
fc4c46a
 
 
f3bc85b
fc4c46a
1575031
 
 
 
8ff9b2c
1575031
 
 
 
 
 
8ff9b2c
 
5b36399
8ff9b2c
 
 
3c2e8c5
 
5b36399
3c2e8c5
 
8ff9b2c
1575031
8ff9b2c
1575031
 
8ff9b2c
d9c1048
8ff9b2c
 
d9c1048
8ff9b2c
 
 
 
 
 
 
 
1575031
 
d9c1048
 
 
 
 
8ff9b2c
 
5232d84
8ff9b2c
d9c1048
8ff9b2c
3c2e8c5
5232d84
3c2e8c5
 
1575031
3c2e8c5
 
 
 
 
 
 
 
 
1575031
 
 
3c2e8c5
 
1575031
d9c1048
 
8ff9b2c
d9c1048
 
 
8ff9b2c
 
 
 
 
d9c1048
1575031
 
fc4c46a
 
 
 
 
 
 
 
 
8ff9b2c
1575031
 
8ff9b2c
 
 
 
fc4c46a
 
 
 
 
8ff9b2c
 
fc4c46a
f3bc85b
8ff9b2c
fc4c46a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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("<h2>🎤 Human-Like Voices (Pro Plan)</h2>")
    
    with gr.Column(elem_classes="voice-container"):
        for voice in voices:
            with gr.Column(elem_classes="voice-box"):
                # Hidden Audio Component
                audio = gr.Audio(None, autoplay=False, elem_id=voice["name"], visible=False)
                # Round Play Button
                btn = gr.Button("▶", elem_classes="play-btn")
                # Voice Details (Name in Bold, Other Info Below)
                info = gr.Markdown(f"<div class='voice-info'><b>{voice['name']}</b><br><span>{voice['gender']} | {voice['country']}</span></div>")
                
                btn.click(fn=toggle_audio, inputs=[], outputs=[audio, btn])

# Launch App
demo.launch()