Spaces:
Building
Building
Update app.py
Browse files
app.py
CHANGED
@@ -3,10 +3,16 @@ from transformers import MarianMTModel, MarianTokenizer
|
|
3 |
from datetime import datetime
|
4 |
import langid
|
5 |
import os
|
6 |
-
import
|
|
|
7 |
import warnings
|
8 |
|
|
|
9 |
warnings.filterwarnings("ignore", message="Recommended: pip install sacremoses.")
|
|
|
|
|
|
|
|
|
10 |
langid.set_languages(['en', 'fr', 'sw'])
|
11 |
|
12 |
MODEL_MAP = {
|
@@ -23,11 +29,6 @@ TONE_MODIFIERS = {
|
|
23 |
"Casual": "Make this sound casual: "
|
24 |
}
|
25 |
|
26 |
-
VOICE_IDS = {
|
27 |
-
"Rachel (Female)": "21m00Tcm4TlvDq8ikWAM",
|
28 |
-
"Adam (Male)": "pNInz6obpgDQGcFmaJgB"
|
29 |
-
}
|
30 |
-
|
31 |
loaded_models = {}
|
32 |
|
33 |
def load_model(model_name):
|
@@ -47,13 +48,15 @@ def detect_language(text):
|
|
47 |
def translate(text, direction, tone):
|
48 |
detected_lang = detect_language(text)
|
49 |
expected_src = direction.split(" β ")[0].lower()
|
50 |
-
|
51 |
if expected_src.startswith("english") and detected_lang != "en":
|
52 |
-
warning = f"
|
53 |
elif expected_src.startswith("french") and detected_lang != "fr":
|
54 |
-
warning = f"
|
55 |
elif expected_src.startswith("swahili") and detected_lang != "sw":
|
56 |
-
warning = f"
|
|
|
|
|
57 |
|
58 |
prompt = TONE_MODIFIERS[tone] + text
|
59 |
model_info = MODEL_MAP[direction]
|
@@ -80,22 +83,40 @@ def translate(text, direction, tone):
|
|
80 |
|
81 |
return f"{warning}\n{translation}" if warning else translation
|
82 |
|
83 |
-
#
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
def transcribe_and_translate(audio_path, direction, tone):
|
|
|
88 |
recognizer = sr.Recognizer()
|
89 |
try:
|
90 |
with sr.AudioFile(audio_path) as source:
|
91 |
audio = recognizer.record(source)
|
92 |
if len(audio.frame_data) < 10000:
|
93 |
-
return "
|
94 |
text = recognizer.recognize_google(audio)
|
95 |
return translate(text, direction, tone)
|
96 |
except Exception as e:
|
97 |
-
return f"
|
98 |
|
|
|
99 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
100 |
gr.Markdown("## π EAC Translator")
|
101 |
gr.Markdown("Supports English, French, and Swahili. Includes tone control, language detection, voice input, and speech playback.")
|
@@ -106,33 +127,23 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
106 |
direction = gr.Dropdown(choices=list(MODEL_MAP.keys()), label="Translation Direction", value="English β Swahili")
|
107 |
tone = gr.Radio(choices=list(TONE_MODIFIERS.keys()), label="Tone", value="Neutral")
|
108 |
output_text = gr.Textbox(label="Translated Text", lines=3)
|
109 |
-
|
|
|
110 |
translate_btn = gr.Button("Translate")
|
111 |
speak_btn = gr.Button("π Speak Translation")
|
112 |
-
|
|
|
113 |
|
114 |
-
with gr.Tab("
|
115 |
audio_input = gr.Audio(sources=["microphone"], type="filepath", label="Speak Now")
|
116 |
direction_voice = gr.Dropdown(choices=list(MODEL_MAP.keys()), label="Translation Direction", value="English β Swahili")
|
117 |
tone_voice = gr.Radio(choices=list(TONE_MODIFIERS.keys()), label="Tone", value="Neutral")
|
118 |
voice_output = gr.Textbox(label="Translated Text")
|
119 |
-
|
|
|
120 |
voice_translate_btn = gr.Button("Transcribe & Translate")
|
121 |
voice_speak_btn = gr.Button("π Speak Translation")
|
122 |
-
|
123 |
-
|
124 |
-
translate_btn.click(fn=translate, inputs=[input_text, direction, tone], outputs=output_text)
|
125 |
-
speak_btn.click(fn=tts_via_api, inputs=[output_text, voice_select], outputs=audio_output)
|
126 |
-
voice_translate_btn.click(fn=transcribe_and_translate, inputs=[audio_input, direction_voice, tone_voice], outputs=voice_output)
|
127 |
-
voice_speak_btn.click(fn=tts_via_api, inputs=[voice_output, voice_select2], outputs=audio_output2)
|
128 |
-
|
129 |
-
gr.Markdown(
|
130 |
-
"""<div style='text-align: center;'>
|
131 |
-
<a href='https://eng-jobbers.vercel.app/' target='_blank' style='text-decoration: none; font-weight: bold;'>
|
132 |
-
Built with β€οΈ by Eng. Jobbers β Qtrinova Inc
|
133 |
-
</a>
|
134 |
-
</div>""",
|
135 |
-
elem_id="footer"
|
136 |
-
)
|
137 |
|
138 |
demo.launch()
|
|
|
3 |
from datetime import datetime
|
4 |
import langid
|
5 |
import os
|
6 |
+
import pyttsx3
|
7 |
+
import time
|
8 |
import warnings
|
9 |
|
10 |
+
# Optional: suppress sacremoses warning
|
11 |
warnings.filterwarnings("ignore", message="Recommended: pip install sacremoses.")
|
12 |
+
|
13 |
+
# Set FFmpeg path explicitly (for pydub and audio playback)
|
14 |
+
os.environ["PATH"] += os.pathsep + r"C:\ffmpeg\bin"
|
15 |
+
|
16 |
langid.set_languages(['en', 'fr', 'sw'])
|
17 |
|
18 |
MODEL_MAP = {
|
|
|
29 |
"Casual": "Make this sound casual: "
|
30 |
}
|
31 |
|
|
|
|
|
|
|
|
|
|
|
32 |
loaded_models = {}
|
33 |
|
34 |
def load_model(model_name):
|
|
|
48 |
def translate(text, direction, tone):
|
49 |
detected_lang = detect_language(text)
|
50 |
expected_src = direction.split(" β ")[0].lower()
|
51 |
+
|
52 |
if expected_src.startswith("english") and detected_lang != "en":
|
53 |
+
warning = f"β Detected language is '{detected_lang}', but you selected English as source."
|
54 |
elif expected_src.startswith("french") and detected_lang != "fr":
|
55 |
+
warning = f"β Detected language is '{detected_lang}', but you selected French as source."
|
56 |
elif expected_src.startswith("swahili") and detected_lang != "sw":
|
57 |
+
warning = f"β Detected language is '{detected_lang}', but you selected Swahili as source."
|
58 |
+
else:
|
59 |
+
warning = ""
|
60 |
|
61 |
prompt = TONE_MODIFIERS[tone] + text
|
62 |
model_info = MODEL_MAP[direction]
|
|
|
83 |
|
84 |
return f"{warning}\n{translation}" if warning else translation
|
85 |
|
86 |
+
# Get available voices
|
87 |
+
engine = pyttsx3.init()
|
88 |
+
voices = engine.getProperty('voices')
|
89 |
+
voice_names = [voice.name for voice in voices]
|
90 |
+
|
91 |
+
def speak_text_to_file(text, voice_name):
|
92 |
+
try:
|
93 |
+
engine = pyttsx3.init()
|
94 |
+
engine.setProperty('rate', 150)
|
95 |
+
for voice in voices:
|
96 |
+
if voice.name == voice_name:
|
97 |
+
engine.setProperty('voice', voice.id)
|
98 |
+
break
|
99 |
+
output_path = "tts_output.wav"
|
100 |
+
engine.save_to_file(text, output_path)
|
101 |
+
engine.runAndWait()
|
102 |
+
return output_path
|
103 |
+
except Exception as e:
|
104 |
+
return None
|
105 |
|
106 |
def transcribe_and_translate(audio_path, direction, tone):
|
107 |
+
import speech_recognition as sr
|
108 |
recognizer = sr.Recognizer()
|
109 |
try:
|
110 |
with sr.AudioFile(audio_path) as source:
|
111 |
audio = recognizer.record(source)
|
112 |
if len(audio.frame_data) < 10000:
|
113 |
+
return "β Audio too short or empty. Please try again."
|
114 |
text = recognizer.recognize_google(audio)
|
115 |
return translate(text, direction, tone)
|
116 |
except Exception as e:
|
117 |
+
return f"β Could not transcribe audio: {e}"
|
118 |
|
119 |
+
# Gradio UI
|
120 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
121 |
gr.Markdown("## π EAC Translator")
|
122 |
gr.Markdown("Supports English, French, and Swahili. Includes tone control, language detection, voice input, and speech playback.")
|
|
|
127 |
direction = gr.Dropdown(choices=list(MODEL_MAP.keys()), label="Translation Direction", value="English β Swahili")
|
128 |
tone = gr.Radio(choices=list(TONE_MODIFIERS.keys()), label="Tone", value="Neutral")
|
129 |
output_text = gr.Textbox(label="Translated Text", lines=3)
|
130 |
+
voice_choice = gr.Dropdown(choices=voice_names, label="Voice for Playback", value=voice_names[0])
|
131 |
+
audio_output = gr.Audio(label="Playback", interactive=False)
|
132 |
translate_btn = gr.Button("Translate")
|
133 |
speak_btn = gr.Button("π Speak Translation")
|
134 |
+
translate_btn.click(fn=translate, inputs=[input_text, direction, tone], outputs=output_text)
|
135 |
+
speak_btn.click(fn=speak_text_to_file, inputs=[output_text, voice_choice], outputs=audio_output)
|
136 |
|
137 |
+
with gr.Tab("π Voice Translation"):
|
138 |
audio_input = gr.Audio(sources=["microphone"], type="filepath", label="Speak Now")
|
139 |
direction_voice = gr.Dropdown(choices=list(MODEL_MAP.keys()), label="Translation Direction", value="English β Swahili")
|
140 |
tone_voice = gr.Radio(choices=list(TONE_MODIFIERS.keys()), label="Tone", value="Neutral")
|
141 |
voice_output = gr.Textbox(label="Translated Text")
|
142 |
+
voice_choice2 = gr.Dropdown(choices=voice_names, label="Voice for Playback", value=voice_names[0])
|
143 |
+
audio_output2 = gr.Audio(label="Playback", interactive=False)
|
144 |
voice_translate_btn = gr.Button("Transcribe & Translate")
|
145 |
voice_speak_btn = gr.Button("π Speak Translation")
|
146 |
+
voice_translate_btn.click(fn=transcribe_and_translate, inputs=[audio_input, direction_voice, tone_voice], outputs=voice_output)
|
147 |
+
voice_speak_btn.click(fn=speak_text_to_file, inputs=[voice_output, voice_choice2], outputs=audio_output2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
|
149 |
demo.launch()
|