Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- .gitattributes +35 -35
- LICENSE +21 -0
- app.py +105 -0
- assets/demo.png +0 -0
- requirements.txt +5 -0
.gitattributes
CHANGED
@@ -1,35 +1,35 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2025 Snackshell
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
app.py
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import tempfile
|
2 |
+
import edge_tts
|
3 |
+
import gradio as gr
|
4 |
+
import asyncio
|
5 |
+
|
6 |
+
# --- Final, VERIFIED Language & Voice Configuration ---
|
7 |
+
language_dict = {
|
8 |
+
"English": {
|
9 |
+
"Jenny (Female, US)": "en-US-JennyNeural",
|
10 |
+
"Andrew (Male, US)": "en-US-AndrewNeural",
|
11 |
+
"Sonia (Female, UK)": "en-GB-SoniaNeural",
|
12 |
+
"Ryan (Male, UK)": "en-GB-RyanNeural"
|
13 |
+
},
|
14 |
+
"Amharic": {
|
15 |
+
"Mekdes (Female)": "am-ET-MekdesNeural",
|
16 |
+
"Ameha (Male)": "am-ET-AmehaNeural"
|
17 |
+
},
|
18 |
+
"Tigrinya": {
|
19 |
+
# WORKAROUND: Using Amharic voices as a fallback for Tigrinya.
|
20 |
+
"Lulia (Female)": "am-ET-MekdesNeural",
|
21 |
+
"Birhane (Male)": "am-ET-AmehaNeural"
|
22 |
+
},
|
23 |
+
"Arabic": {
|
24 |
+
"Zariyah (Female, KSA)": "ar-SA-ZariyahNeural",
|
25 |
+
"Hamed (Male, KSA)": "ar-SA-HamedNeural"
|
26 |
+
},
|
27 |
+
"French": {
|
28 |
+
"Denise (Female)": "fr-FR-DeniseNeural",
|
29 |
+
"Henri (Male)": "fr-FR-HenriNeural"
|
30 |
+
},
|
31 |
+
"German": {
|
32 |
+
"Katja (Female)": "de-DE-KatjaNeural",
|
33 |
+
"Conrad (Male)": "de-DE-ConradNeural"
|
34 |
+
},
|
35 |
+
"Italian": {
|
36 |
+
"Elsa (Female)": "it-IT-ElsaNeural",
|
37 |
+
"Diego (Male)": "it-IT-DiegoNeural"
|
38 |
+
},
|
39 |
+
"Japanese": {
|
40 |
+
"Nanami (Female)": "ja-JP-NanamiNeural",
|
41 |
+
"Keita (Male)": "ja-JP-KeitaNeural"
|
42 |
+
},
|
43 |
+
"Korean": {
|
44 |
+
"Sun-Hi (Female)": "ko-KR-SunHiNeural",
|
45 |
+
"InJoon (Male)": "ko-KR-InJoonNeural"
|
46 |
+
},
|
47 |
+
"Chinese (Simplified)": {
|
48 |
+
"Xiaoxiao (Female)": "zh-CN-XiaoxiaoNeural",
|
49 |
+
"Yunxi (Male)": "zh-CN-YunxiNeural"
|
50 |
+
},
|
51 |
+
"Chinese (Traditional)": {
|
52 |
+
"HsiaoChen (Female)": "zh-TW-HsiaoChenNeural",
|
53 |
+
"YunJhe (Male)": "zh-TW-YunJheNeural"
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
async def text_to_speech_edge(text, language, speaker):
|
58 |
+
try:
|
59 |
+
voice = language_dict[language][speaker]
|
60 |
+
except KeyError:
|
61 |
+
raise gr.Error(f"Error: Voice '{speaker}' not found for {language}.")
|
62 |
+
|
63 |
+
try:
|
64 |
+
communicate = edge_tts.Communicate(text, voice)
|
65 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
|
66 |
+
tmp_path = tmp_file.name
|
67 |
+
await asyncio.wait_for(communicate.save(tmp_path), timeout=60)
|
68 |
+
return tmp_path
|
69 |
+
|
70 |
+
except asyncio.TimeoutError:
|
71 |
+
raise gr.Error("Error: Request timed out. Please try again.")
|
72 |
+
except Exception as e:
|
73 |
+
raise gr.Error(f"An unexpected error occurred: {str(e)}")
|
74 |
+
|
75 |
+
def update_speakers(language):
|
76 |
+
speakers = list(language_dict.get(language, []))
|
77 |
+
return gr.Dropdown(choices=speakers, value=speakers[0] if speakers else None, interactive=True)
|
78 |
+
|
79 |
+
# --- Gradio Interface ---
|
80 |
+
with gr.Blocks(title="SelamGPT TTS", theme=gr.themes.Soft()) as demo:
|
81 |
+
gr.Markdown("# SelamGPT Text-to-Speech")
|
82 |
+
|
83 |
+
with gr.Row():
|
84 |
+
language = gr.Dropdown(
|
85 |
+
choices=list(language_dict.keys()),
|
86 |
+
value="Amharic",
|
87 |
+
label="Language"
|
88 |
+
)
|
89 |
+
speaker = gr.Dropdown(
|
90 |
+
label="Speaker",
|
91 |
+
choices=list(language_dict["Amharic"].keys()),
|
92 |
+
value="Mekdes (Female)"
|
93 |
+
)
|
94 |
+
|
95 |
+
with gr.Column():
|
96 |
+
input_text = gr.Textbox(label="Input Text", placeholder="Enter text here...")
|
97 |
+
generate_btn = gr.Button("Generate Audio", variant="primary")
|
98 |
+
|
99 |
+
output_audio = gr.Audio(label="Output Audio", autoplay=True)
|
100 |
+
|
101 |
+
language.change(fn=update_speakers, inputs=language, outputs=speaker)
|
102 |
+
generate_btn.click(fn=text_to_speech_edge, inputs=[input_text, language, speaker], outputs=output_audio)
|
103 |
+
|
104 |
+
if __name__ == "__main__":
|
105 |
+
demo.launch()
|
assets/demo.png
ADDED
![]() |
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
edge-tts
|
3 |
+
pyarabic
|
4 |
+
gradio-client
|
5 |
+
transformers
|