Anupam007 commited on
Commit
738e954
Β·
verified Β·
1 Parent(s): 5d6d0b9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +190 -0
app.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # !pip install gradio==5.21.0 gTTS speechrecognition pydub deep_translator httpx==0.28.1 webrtcvad noisereduce --quiet
2
+
3
+ import gradio as gr
4
+ from gtts import gTTS
5
+ import speech_recognition as sr
6
+ from pydub import AudioSegment
7
+ import os
8
+ import tempfile
9
+ import logging
10
+ from deep_translator import GoogleTranslator
11
+ import webrtcvad
12
+ import noisereduce as nr
13
+ import numpy as np
14
+ from typing import Optional, Tuple
15
+ import queue
16
+ import threading
17
+
18
+ # Set up logging
19
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Supported languages (expanded globally)
23
+ SUPPORTED_LANGUAGES = {
24
+ "English": "en",
25
+ "Hindi": "hi",
26
+ "Tamil": "ta",
27
+ "Telugu": "te",
28
+ "Bengali": "bn",
29
+ "Marathi": "mr",
30
+ "Gujarati": "gu",
31
+ "Kannada": "kn",
32
+ "Malayalam": "ml",
33
+ "Punjabi": "pa",
34
+ "Spanish": "es",
35
+ "French": "fr",
36
+ "German": "de",
37
+ "Chinese (Simplified)": "zh-CN",
38
+ "Japanese": "ja",
39
+ "Arabic": "ar"
40
+ }
41
+
42
+ # Thread-safe queue for processing chunks
43
+ task_queue = queue.Queue()
44
+
45
+ # VAD setup
46
+ vad = webrtcvad.Vad(1) # Aggressiveness level 1 (0-3)
47
+
48
+ # TTS Function with chunked support
49
+ def text_to_speech(text: str, lang: str) -> Optional[str]:
50
+ try:
51
+ if not text or not text.strip():
52
+ raise ValueError("Text input cannot be empty.")
53
+
54
+ target_lang_code = SUPPORTED_LANGUAGES.get(lang, "en")
55
+ logger.info(f"TTS: Text='{text}', Language='{lang}' ({target_lang_code})")
56
+
57
+ translated_text = text if target_lang_code == "en" else GoogleTranslator(source="en", target=target_lang_code).translate(text)
58
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:
59
+ tts = gTTS(text=translated_text, lang=target_lang_code, slow=False)
60
+ tts.save(temp_file.name)
61
+ logger.info(f"TTS generated: {temp_file.name}")
62
+ return temp_file.name
63
+
64
+ except ValueError as e:
65
+ logger.error(f"Input validation failed: {str(e)}")
66
+ return None
67
+ except Exception as e:
68
+ logger.error(f"TTS failed: {str(e)}")
69
+ return None
70
+
71
+ # STT Function with chunking, VAD, and noise reduction
72
+ def speech_to_text(audio_input: str, chunk_duration_ms: int = 2000) -> Tuple[str, Optional[str]]:
73
+ recognizer = sr.Recognizer()
74
+ try:
75
+ if not audio_input:
76
+ raise ValueError("No audio provided.")
77
+
78
+ logger.info(f"Processing STT: Audio file='{audio_input}'")
79
+ audio_segment = AudioSegment.from_file(audio_input)
80
+
81
+ # Noise reduction
82
+ audio_np = np.array(audio_segment.get_array_of_samples(), dtype=np.float32)
83
+ reduced_noise = nr.reduce_noise(y=audio_np, sr=audio_segment.frame_rate)
84
+ audio_segment = AudioSegment(
85
+ reduced_noise.tobytes(),
86
+ frame_rate=audio_segment.frame_rate,
87
+ sample_width=audio_segment.sample_width,
88
+ channels=audio_segment.channels
89
+ )
90
+
91
+ # Chunk audio
92
+ chunk_length = chunk_duration_ms # 2 seconds
93
+ chunks = [audio_segment[i:i + chunk_length] for i in range(0, len(audio_segment), chunk_length)]
94
+ full_text = ""
95
+ dubbed_audio = None
96
+
97
+ for i, chunk in enumerate(chunks):
98
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_wav:
99
+ chunk.export(temp_wav.name, format="wav")
100
+ with open(temp_wav.name, "rb") as f:
101
+ audio_bytes = f.read()
102
+
103
+ # VAD to detect speech
104
+ is_speech = vad.is_speech(audio_bytes[:30], sample_rate=chunk.frame_rate) # Check first 30ms
105
+ if is_speech:
106
+ with sr.AudioFile(temp_wav.name) as source:
107
+ audio_data = recognizer.record(source)
108
+ text = recognizer.recognize_google(audio_data, language="auto")
109
+ full_text += text + " "
110
+ logger.info(f"Chunk {i+1} transcribed: {text}")
111
+ os.remove(temp_wav.name)
112
+
113
+ return full_text.strip(), dubbed_audio
114
+
115
+ except ValueError as e:
116
+ logger.error(f"Input validation failed: {str(e)}")
117
+ return f"Error: {str(e)}", None
118
+ except sr.UnknownValueError:
119
+ logger.warning("Speech not recognized.")
120
+ return "Could not understand the audio.", None
121
+ except sr.RequestError as e:
122
+ logger.error(f"STT API error: {str(e)}")
123
+ return f"STT error: {str(e)}", None
124
+ except Exception as e:
125
+ logger.error(f"STT failed: {str(e)}")
126
+ return f"Error in STT: {str(e)}", None
127
+
128
+ # Real-time dubbing handler
129
+ def handle_dubbing(audio_input: str, target_lang: str) -> Tuple[str, Optional[str]]:
130
+ text, _ = speech_to_text(audio_input)
131
+ if not text.startswith("Error"):
132
+ dubbed_audio = text_to_speech(text, target_lang)
133
+ return text, dubbed_audio
134
+ return text, None
135
+
136
+ # Professional Gradio UI
137
+ with gr.Blocks(
138
+ title="World-Class Real-Time Dubbing Translator",
139
+ theme=gr.themes.Soft(),
140
+ css="""
141
+ .gradio-container { max-width: 900px; margin: auto; }
142
+ .title { font-size: 2em; text-align: center; }
143
+ .description { text-align: center; color: #666; }
144
+ .button { background-color: #4CAF50; color: white; }
145
+ """
146
+ ) as demo:
147
+ # Header
148
+ gr.Markdown("<h1 class='title'>Real-Time Multilingual Dubbing</h1>")
149
+ gr.Markdown("<p class='description'>Record your voice and hear it dubbed in another language instantly.</p>")
150
+
151
+ # Dubbing Section
152
+ with gr.Row():
153
+ audio_input = gr.Audio(
154
+ sources=["microphone", "upload"],
155
+ type="filepath",
156
+ label="Record or Upload Audio",
157
+ interactive=True
158
+ )
159
+ lang_dropdown = gr.Dropdown(
160
+ choices=list(SUPPORTED_LANGUAGES.keys()),
161
+ label="Target Language for Dubbing",
162
+ value="English",
163
+ interactive=True,
164
+ allow_custom_value=False,
165
+ filterable=True # Adds search functionality
166
+ )
167
+
168
+ dub_button = gr.Button("Dub Audio", variant="primary")
169
+ with gr.Row():
170
+ stt_output = gr.Textbox(label="Transcription", placeholder="Your audio transcription will appear here", lines=3)
171
+ dub_output = gr.Audio(label="Dubbed Audio", type="filepath", interactive=False)
172
+
173
+ # Event handler
174
+ dub_button.click(
175
+ fn=handle_dubbing,
176
+ inputs=[audio_input, lang_dropdown],
177
+ outputs=[stt_output, dub_output]
178
+ )
179
+
180
+ # Footer
181
+ gr.Markdown("<footer style='text-align: center; padding: 20px;'>Β© 2025 xAI - Powered by Advanced AI Technologies</footer>")
182
+
183
+ # Launch with flexible port settings
184
+ demo.launch(
185
+ share=True,
186
+ server_name="0.0.0.0",
187
+ server_port=None,
188
+ debug=False,
189
+ show_error=True
190
+ )