ayushkanha commited on
Commit
1c2fdca
Β·
verified Β·
1 Parent(s): 9325662

Upload 8 files

Browse files
Files changed (9) hide show
  1. .gitattributes +2 -0
  2. about.py +39 -0
  3. app1.py +216 -0
  4. css.py +85 -0
  5. fevicon.png +3 -0
  6. logo.png +3 -0
  7. requirements.txt +8 -0
  8. tone.py +95 -0
  9. voice.py +41 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* 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
 
 
 
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
36
+ fevicon.png filter=lfs diff=lfs merge=lfs -text
37
+ logo.png filter=lfs diff=lfs merge=lfs -text
about.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ def about_page():
4
+ st.title("πŸ“Œ About VoiceBridge")
5
+
6
+ st.markdown("""
7
+ **VoiceBridge** is a smart and user-friendly app designed to help you **translate speech or text across multiple languages** and analyze the **emotional tone** of the message.
8
+
9
+ ---
10
+ ### πŸš€ What Can VoiceBridge Do?
11
+ - πŸ—£οΈ Convert **voice to text** using speech recognition
12
+ - 🌐 Translate text or speech into other languages using Deep Translator (Google Translate)
13
+ - πŸ’¬ Detect the **sentiment or tone** of the message using local and cloud-based models
14
+
15
+ ---
16
+ ### πŸ”§ Technologies Used
17
+ - **Speech Recognition**: `speech_recognition` library for converting audio to text
18
+ - **Translation**: `deep_translator` with Google Translate for accurate text translation
19
+ - **Sentiment Analysis**:
20
+ - For text: Hugging Face Transformer models (e.g., BERT-based sentiment classification)
21
+ - For voice: A local emotion detection model to analyze audio tone
22
+
23
+ ---
24
+ ### 🎯 Why VoiceBridge?
25
+ VoiceBridge is created to:
26
+ - Break language barriers in real-time
27
+ - Help understand the emotional intent of communication
28
+ - Enable better interaction in global, multicultural environments
29
+ - Support accessibility and learning
30
+
31
+ ---
32
+ ### πŸ‘¨β€πŸ’» Developer Info
33
+ **Developed by**: Ayush & Manav
34
+ πŸ”— [GitHub](https://github.com/yourusername) | [LinkedIn](https://linkedin.com/in/yourprofile)
35
+
36
+ ---
37
+ 🌐 VoiceBridge is open for collaboration and feedback. Let's bridge the gap between voices and languages! πŸ’¬πŸŒ
38
+ """)
39
+
app1.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from deep_translator import GoogleTranslator
3
+ from gtts import gTTS
4
+ from pydub import AudioSegment
5
+ import tempfile
6
+ import os
7
+ import speech_recognition as sr
8
+ from transformers import pipeline as pl
9
+ from streamlit_option_menu import option_menu
10
+ import css
11
+ from st_audiorec import st_audiorec
12
+ import streamlit.components.v1 as components
13
+ from voice import transcribe,text_to_speech
14
+ from tone import tone
15
+ import about
16
+
17
+ os.environ["STREAMLIT_WATCHER_TYPE"] = "none"
18
+ st.session_state.translate=False
19
+
20
+ st.set_page_config(page_title="VoiceBridge",layout="wide",page_icon="fevicon.png")
21
+ Languages = {'afrikaans':'af','albanian':'sq','amharic':'am','arabic':'ar','armenian':'hy','azerbaijani':'az',
22
+ 'basque':'eu','belarusian':'be','bengali':'bn','bosnian':'bs','bulgarian':'bg','catalan':'ca',
23
+ 'cebuano':'ceb','chichewa':'ny','chinese (simplified)':'zh-cn','chinese (traditional)':'zh-tw',
24
+ 'corsican':'co','croatian':'hr','czech':'cs','danish':'da','dutch':'nl','english':'en','esperanto':'eo',
25
+ 'estonian':'et','filipino':'tl','finnish':'fi','french':'fr','frisian':'fy','galician':'gl','georgian':'ka',
26
+ 'german':'de','greek':'el','gujarati':'gu','haitian creole':'ht','hausa':'ha','hawaiian':'haw','hebrew':'iw',
27
+ 'hebrew':'he','hindi':'hi','hmong':'hmn','hungarian':'hu','icelandic':'is','igbo':'ig','indonesian':'id',
28
+ 'irish':'ga','italian':'it','japanese':'ja','javanese':'jw','kannada':'kn','kazakh':'kk','khmer':'km',
29
+ 'korean':'ko','kurdish (kurmanji)':'ku','kyrgyz':'ky','lao':'lo','latin':'la','latvian':'lv','lithuanian':'lt',
30
+ 'luxembourgish':'lb','macedonian':'mk','malagasy':'mg','malay':'ms','malayalam':'ml','maltese':'mt','maori':'mi',
31
+ 'marathi':'mr','mongolian':'mn','myanmar (burmese)':'my','nepali':'ne','norwegian':'no','odia':'or','pashto':'ps',
32
+ 'persian':'fa','polish':'pl','portuguese':'pt','punjabi':'pa','romanian':'ro','russian':'ru','samoan':'sm',
33
+ 'scots gaelic':'gd','serbian':'sr','sesotho':'st','shona':'sn','sindhi':'sd','sinhala':'si','slovak':'sk',
34
+ 'slovenian':'sl','somali':'so','spanish':'es','sundanese':'su','swahili':'sw','swedish':'sv','tajik':'tg',
35
+ 'tamil':'ta','telugu':'te','thai':'th','turkish':'tr','turkmen':'tk','ukrainian':'uk','urdu':'ur','uyghur':'ug',
36
+ 'uzbek':'uz','vietnamese':'vi','welsh':'cy','xhosa':'xh','yiddish':'yi','yoruba':'yo','zulu':'zu'}
37
+
38
+
39
+
40
+ st.markdown(
41
+ """
42
+ <style>
43
+
44
+ [alt="Logo"] {
45
+ height: 90px;
46
+ width: auto;
47
+
48
+ }
49
+ .block-container {
50
+ padding-top: 0rem;
51
+ }
52
+ header { visibility: hidden; }
53
+ </style>
54
+ """,
55
+ unsafe_allow_html=True
56
+ )
57
+ col1, col2 = st.columns([1, 6])
58
+ with col1:
59
+ st.markdown("""
60
+ <style>
61
+ @media only screen and (max-width: 959px) {
62
+ img {
63
+ max-width: 100px;
64
+ height: auto;
65
+ }
66
+ }
67
+ </style>
68
+ """, unsafe_allow_html=True)
69
+ st.logo("logo.png")
70
+ with col2:
71
+
72
+ css.nev()
73
+ st.markdown('<div class="custom-navbar">', unsafe_allow_html=True)
74
+ selected = option_menu(
75
+ menu_title=None,
76
+ options=["Translate", "Tone", "About"],
77
+ icons=["bi-people-fill", "bi-soundwave", "gear"],
78
+ menu_icon="cast",
79
+ default_index=0,
80
+ orientation="horizontal",
81
+ styles={
82
+ "container": {"padding": "0!important", "background-color": "#0E1117"},
83
+ "icon": {"color": "white"},
84
+ "nav-link": {
85
+ "text-align": "center",
86
+ "margin": "0px",
87
+ "--hover-color": "#204044",
88
+ },
89
+ "nav-link-selected": {"background-color": "#1f6f78"},
90
+ }
91
+ )
92
+ st.markdown('</div>', unsafe_allow_html=True)
93
+ with st.container():
94
+ st.markdown("""
95
+ <style>
96
+ .custom-container {
97
+ margin-top: 70px;
98
+ }
99
+
100
+ @media (max-width: 767px) {
101
+ .custom-container {
102
+ margin-top: 0px;
103
+ }
104
+ }
105
+ </style>
106
+ <style>
107
+ .middle {
108
+ margin-top: 120px;
109
+ }
110
+
111
+ @media (max-width: 767px) {
112
+ .middle {
113
+ margin-top: 0px;
114
+ }
115
+ }
116
+ </style>
117
+ """, unsafe_allow_html=True)
118
+ st.markdown('<div class="custom-container">', unsafe_allow_html=True)
119
+
120
+ left_col, st.session_state.mid_col, st.session_state.right_col = st.columns([3, 2, 3])
121
+ # left user input
122
+ # ------------------------------------------------------------------------------------------------------------------------------------------------
123
+ if (selected == "Translate" or selected == "Tone"):
124
+ with left_col:
125
+ with st.popover("", icon=":material/tune:"):
126
+ inp = st.selectbox('Choose Input Format', ("Text", "Audio_file", "MIC"))
127
+ st.session_state.inp = inp
128
+ with st.form("my_form"):
129
+ st.markdown("### πŸŽ™οΈ Input")
130
+ if st.session_state.inp == "Text":
131
+ st.session_state.text = st.text_area("Enter Text:", help="Type your text here...")
132
+ elif st.session_state.inp == "MIC":
133
+ st.session_state.uploaded_file = st.audio_input("Record a Voice Message")
134
+ else:
135
+ st.session_state.uploaded_file = st.file_uploader("Upload an Audio File", type=["mp3", "wav", "m4a"])
136
+
137
+ submitted = st.form_submit_button("Submit")
138
+
139
+ # ------------------------------------------------------------------------------------------------------------------------------------------------
140
+ if selected == "Translate":
141
+
142
+ # ------------------------------------------------------------------------------------------------------------------------------------------------
143
+ # center button
144
+ st.markdown('<div class="middle">', unsafe_allow_html=True)
145
+ with st.session_state.mid_col:
146
+
147
+ css.cicle_button()
148
+
149
+ if st.button("Translate"):
150
+ st.session_state.translate=False
151
+ st.session_state.translate=True
152
+ st.markdown('</div>', unsafe_allow_html=True)
153
+
154
+
155
+ # ------------------------------------------------------------------------------------------------------------------------------------------------
156
+ # Right Output
157
+ with st.session_state.right_col:
158
+
159
+ with st.popover("", icon=":material/tune:"):
160
+ out_type = st.selectbox('Choose Input Format', ("Text", "Voice", "Both"))
161
+ st.session_state.out_type = out_type
162
+ with st.form("output"):
163
+ st.markdown("### πŸ”‰ Voice Output")
164
+ option2 = st.selectbox('Select Output Language', list(Languages.keys()))
165
+ value2 = Languages[option2]
166
+
167
+ if st.session_state.translate:
168
+ c1,c2=st.columns(2)
169
+ if st.session_state.inp != "Text":
170
+ st.session_state.text = transcribe(st.session_state.uploaded_file)
171
+
172
+ translated_text = GoogleTranslator(target=value2).translate(st.session_state.text)
173
+
174
+ if st.session_state.out_type == "Text":
175
+ st.text_area("Translated Text:", translated_text, height=100)
176
+
177
+ elif st.session_state.out_type == "Voice":
178
+ if translated_text.strip():
179
+ audio_file = text_to_speech(translated_text, value2)
180
+ else:
181
+ c2.warning("Please enter text before converting.")
182
+ st.audio(audio_file, format='audio/mp3', autoplay=True)
183
+
184
+ else:
185
+ if translated_text.strip():
186
+ audio_file = text_to_speech(translated_text, value2)
187
+ else:
188
+ c2.warning("Please enter text before converting.")
189
+ with c1.popover("", icon=":material/library_books:"):
190
+ st.text_area("Translated Text:", translated_text, height=100)
191
+ c2.audio(audio_file, format='audio/mp3', autoplay=True)
192
+
193
+ reset = st.form_submit_button("Reset ↻ ")
194
+ if reset:
195
+ st.session_state.translate= False
196
+ # Optional: Add some styling
197
+ st.markdown("""
198
+
199
+ <style>
200
+ body {
201
+ background-color: #0e1117;
202
+ color: white;
203
+ }
204
+ .stButton>button {
205
+ background-color: teal;
206
+ color: white;
207
+ }
208
+ </style>
209
+ """, unsafe_allow_html=True)
210
+ st.markdown('</div>', unsafe_allow_html=True)
211
+
212
+
213
+ if selected == "Tone":
214
+ tone()
215
+ if selected == "About":
216
+ about.about_page()
css.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ def nev():
4
+ st.markdown("""
5
+ <style>
6
+ /* Responsive icon and text size for option menu */
7
+ @media only screen and (max-width: 768px) {
8
+ .nav-link > span {
9
+ font-size: 14px !important; /* reduce label size */
10
+ }
11
+ .nav-link > i {
12
+ font-size: 16px !important; /* reduce icon size */
13
+ }
14
+ }
15
+
16
+ @media only screen and (max-width: 480px) {
17
+ .nav-link > span {
18
+ font-size: 12px !important;
19
+ }
20
+ .nav-link > i {
21
+ font-size: 14px !important;
22
+ }
23
+ }
24
+
25
+ @media only screen and (min-width: 769px) {
26
+ .nav-link > span {
27
+ font-size: 18px !important;
28
+ }
29
+ .nav-link > i {
30
+ font-size: 20px !important;
31
+ }
32
+ }
33
+
34
+ .custom-navbar {
35
+ margin-top: 0px;
36
+ }
37
+
38
+ @media only screen and (max-width: 768px) {
39
+ .custom-navbar {
40
+ margin-top: 50px !important;
41
+ }
42
+ }
43
+ </style>
44
+ """, unsafe_allow_html=True)
45
+
46
+ def cicle_button():
47
+ st.markdown("""
48
+ <style>
49
+ /* Target the button using Streamlit's internal structure */
50
+ div[class^="stButton"] > button {
51
+ width: 80px;
52
+ height: 80px;
53
+ border-radius: 50%;
54
+ background-color: #008080;
55
+ color: white;
56
+ font-weight: bold;
57
+ font-size: 16px;
58
+ padding: 0;
59
+ border: none;
60
+ margin-left: 37%;
61
+ margin-top: 70px;
62
+ }
63
+
64
+ @media (max-width: 640px) {
65
+ div[class^="stButton"] > button {
66
+ margin-top: 0px;
67
+ margin-left:43%;
68
+
69
+ }
70
+ div[class^="stButton"] > button:hover {
71
+ background-color: #009999;
72
+ margin-left: 90px;
73
+ }
74
+ @media (max-width: 767px) {
75
+ div[class^="stButton"] > button:hover{
76
+ margin-top: 0px;
77
+ margin-left:60px;
78
+ }
79
+ @media (max-width: 640px) {
80
+ div[class^="stButton"] > button:hover{
81
+ margin-top: 0px;
82
+ margin-left:43%;
83
+ }
84
+ </style>
85
+ """, unsafe_allow_html=True)
fevicon.png ADDED

Git LFS Details

  • SHA256: bdefa0cc6e5440be484e440a79e095a2f2fc5e5930275013cccdb1527258f4fe
  • Pointer size: 131 Bytes
  • Size of remote file: 396 kB
logo.png ADDED

Git LFS Details

  • SHA256: 1e295ea6585ce002334225a6497d2d462ac00512643e3fa9b399c3cb2789b877
  • Pointer size: 131 Bytes
  • Size of remote file: 545 kB
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ deep-translator
3
+ gTTS
4
+ pydub
5
+ speechrecognition
6
+ transformers
7
+ streamlit-option-menu
8
+ st-audiorec
tone.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from deep_translator import GoogleTranslator
3
+ from gtts import gTTS
4
+ from pydub import AudioSegment
5
+ import tempfile
6
+ import os
7
+ import speech_recognition as sr
8
+ import css
9
+ from voice import transcribe
10
+ from transformers import pipeline as pl
11
+ # from speechbrain.pretrained import EncoderClassifier
12
+
13
+ # @st.cache_resource
14
+ # def load_emotion_model():
15
+ # return EncoderClassifier.from_hparams(
16
+ # source="emotion_model_local",
17
+ # savedir="tmp_emotion_model"
18
+ # )
19
+
20
+ # emotion_model = load_emotion_model()
21
+
22
+ # def detect_emotion(uploaded_file):
23
+ # # Save the uploaded file temporarily
24
+ # # Use a more robust way to handle the temporary file lifecycle
25
+ # with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file:
26
+ # tmp_file.write(uploaded_file.getvalue())
27
+ # raw_path = tmp_file.name
28
+
29
+ # try:
30
+ # audio = AudioSegment.from_file(raw_path)
31
+ # audio = audio.set_frame_rate(16000).set_channels(1)
32
+ # audio.export(raw_path, format="wav")
33
+
34
+ # # Predict emotion using the cleaned file
35
+ # # Ensure the path is passed as a standard string
36
+ # result = emotion_model.classify_file(str(raw_path))
37
+ # predicted_emotion = result[3][0]
38
+ # return predicted_emotion
39
+ # finally:
40
+ # # Clean up the temporary file
41
+ # if os.path.exists(raw_path):
42
+ # os.remove(raw_path)
43
+ def tone():
44
+
45
+ st.session_state.analyse=False
46
+ st.markdown('<div class="middle">', unsafe_allow_html=True)
47
+ with st.session_state.mid_col:
48
+
49
+ css.cicle_button()
50
+
51
+ if st.button("Translate"):
52
+ st.session_state.analyse=True
53
+
54
+ st.markdown('</div>', unsafe_allow_html=True)
55
+ with st.session_state.right_col:
56
+ if st.session_state.analyse:
57
+ if st.session_state.inp != "Text":
58
+ st.session_state.text = transcribe(st.session_state.uploaded_file)
59
+ st.write(" ")
60
+ st.write(" ")
61
+ st.write(" ")
62
+ with st.form("Tone_form"):
63
+ if st.session_state.text !="" and st.session_state.text != " ":
64
+ pipe = pl("text-classification", model="tabularisai/multilingual-sentiment-analysis")
65
+ sentence = st.session_state.text
66
+ result = pipe(sentence)[0]
67
+
68
+ sentiment = result['label']
69
+
70
+ if sentiment == "Very Negative":
71
+ st.error('This is Very Negative', icon="🚨")
72
+ elif sentiment == "Negative":
73
+ st.error('This is Negative', icon="😭")
74
+ elif sentiment == "Neutral":
75
+ st.warning('This is Neutral', icon="😐")
76
+ elif sentiment == "Positive":
77
+ st.success('This is Positive', icon="😊")
78
+ else:
79
+ st.success('This is Very Positive', icon="πŸ˜ƒ")
80
+ else:
81
+ st.warning("write something first")
82
+ reset = st.form_submit_button("Reset ↻ ")
83
+ if reset:
84
+ st.session_state.analyse= False
85
+
86
+
87
+
88
+
89
+
90
+
91
+ # if st.session_state.inp != "Text":
92
+ # text = transcribe(st.session_state.uploaded_file)
93
+ # if text !="" and text != " ":
94
+ # emotion = detect_emotion(st.session_state.uploaded_file)
95
+ # st.write(f"🎭 Detected Emotion: `{emotion}`")
voice.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from gtts import gTTS
3
+ from pydub import AudioSegment
4
+ import tempfile
5
+ import os
6
+ import speech_recognition as sr
7
+
8
+
9
+
10
+ def text_to_speech(text, lang='en', c=0):
11
+ tts = gTTS(text=text, lang=lang)
12
+ audio_file = f"output{c}.mp3"
13
+ tts.save(audio_file)
14
+ return audio_file
15
+
16
+ def transcribe(uploaded_file):
17
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmpfile:
18
+ file_path = tmpfile.name
19
+ tmpfile.write(uploaded_file.read())
20
+
21
+ audio = AudioSegment.from_file(file_path)
22
+ audio = audio.set_frame_rate(16000).set_channels(1)
23
+ audio.export(file_path, format="wav")
24
+
25
+ recognizer = sr.Recognizer()
26
+ with sr.AudioFile(file_path) as source:
27
+ trans=True
28
+ with st.spinner("Transcribing... Please wait!", show_time=True):
29
+ if trans:
30
+ audio_data = recognizer.record(source)
31
+ try:
32
+ text = recognizer.recognize_google(audio_data)
33
+ trans=False
34
+ return text
35
+ except sr.UnknownValueError:
36
+ st.error("❌ Could not understand the audio.")
37
+ except sr.RequestError:
38
+ st.error("❌ API error. Check internet connection.")
39
+
40
+ os.remove(file_path)
41
+ return ""