jpandeinge commited on
Commit
2598cef
1 Parent(s): 2f4793a

initial commit

Browse files
app.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .infoPoint h1 {
3
+ font-size: 30px;
4
+ text-decoration: bold;
5
+
6
+ }
7
+
8
+ a {
9
+ text-decoration: underline;
10
+ color: #1f3b54 ;
11
+ }
12
+
13
+ .finished {
14
+ color:rgb(9, 102, 169);
15
+ font-size:13px
16
+ }
17
+
18
+ table {
19
+
20
+ margin: 25px 0;
21
+ font-size: 0.9em;
22
+ font-family: sans-serif;
23
+ min-width: 400px;
24
+ max-width: 400px;
25
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
26
+ }
27
+
28
+ table th,
29
+ table td {
30
+ padding: 12px 15px;
31
+ }
32
+
33
+ tr {
34
+ text-align: left;
35
+ }
36
+ thead tr {
37
+ text-align: left;
38
+ }
app.py ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import csv
3
+ import random
4
+ import pandas as pd
5
+ import numpy as np
6
+ import gradio as gr
7
+ from collections import Counter
8
+ from utils import *
9
+ import matplotlib.pyplot as plt
10
+ import scipy.io.wavfile as wavf
11
+ from huggingface_hub import Repository, upload_file
12
+
13
+
14
+
15
+ HF_TOKEN = os.environ.get("HF_TOKEN")
16
+
17
+
18
+ GREETINGS_DIR = './greetings'
19
+ greeting_files = [f.name for f in os.scandir(GREETINGS_DIR)]
20
+
21
+
22
+ DATASET_REPO_URL = "https://huggingface.co/datasets/meyabase/crowd-oshiwambo-speech-greetings"
23
+ REPOSITORY_DIR = "data"
24
+ LOCAL_DIR = 'data_local'
25
+ os.makedirs(LOCAL_DIR,exist_ok=True)
26
+
27
+
28
+ GENDER = ['Choose Gender','Male','Female','Other','Prefer not to say']
29
+
30
+ #------------------Work on Languages--------------------
31
+
32
+ languages = ["oshindonga", "oshikwanyama"]
33
+ language_id = ["ng","kj"]
34
+
35
+
36
+ #------------------Work on Languages--------------------
37
+
38
+ repo = Repository(
39
+ local_dir="data", clone_from=DATASET_REPO_URL, use_auth_token=HF_TOKEN
40
+ )
41
+ repo.git_pull()
42
+
43
+
44
+
45
+ with open('app.css','r') as f:
46
+ BLOCK_CSS = f.read()
47
+
48
+ def save_record(language,record,greeting,gender,accent,greeting_history,current_greeting,done_recording):
49
+ # set default
50
+ greeting_history = greeting_history if greeting_history is not None else [0]
51
+ current_greeting = current_greeting if current_greeting is not None else 0 # 0 is the default greeting
52
+ done_recording = done_recording if done_recording is not None else False
53
+ #----
54
+
55
+ # Save text and its corresponding record to flag
56
+ speaker_metadata={}
57
+ speaker_metadata['gender'] = gender if gender!=GENDER[0] else ''
58
+ speaker_metadata['accent'] = accent if accent!='' else ''
59
+ default_record = None
60
+ if not done_recording:
61
+ if language!=None and language!='Choose language' and record is not None and greeting is not None: #
62
+ language = language.lower()
63
+ lang_id = language_id[languages.index(language)]
64
+
65
+ # Write audio to file
66
+ audio_name = get_unique_name()
67
+ SAVE_FILE_DIR = os.path.join(LOCAL_DIR,audio_name)
68
+ os.makedirs(SAVE_FILE_DIR,exist_ok=True)
69
+ audio_output_filename = os.path.join(SAVE_FILE_DIR,'audio.wav')
70
+ wavf.write(audio_output_filename,record[0],record[1])
71
+
72
+ # Write metadata.json to file
73
+ json_file_path = os.path.join(SAVE_FILE_DIR,'metadata.jsonl')
74
+ metadata= {
75
+ 'id':audio_name,
76
+ 'file_name':'audio.wav',
77
+ 'language_name':language,
78
+ 'language_id':lang_id,
79
+ 'greeting':current_greeting,
80
+ 'frequency':record[0],
81
+ 'gender': speaker_metadata['gender'],
82
+ 'accent': speaker_metadata['accent'],
83
+ }
84
+
85
+ dump_json(metadata,json_file_path)
86
+
87
+ # Upload the audio
88
+ repo_audio_path = os.path.join(REPOSITORY_DIR,os.path.join(audio_name,'audio.wav'))
89
+
90
+ _ = upload_file(path_or_fileobj = audio_output_filename,
91
+ path_in_repo =repo_audio_path,
92
+ repo_id='meyabase/crowd-oshiwambo-speech-greetings',
93
+ repo_type='dataset',
94
+ token=HF_TOKEN
95
+ )
96
+
97
+ # Upload the metadata
98
+ repo_json_path = os.path.join(REPOSITORY_DIR,os.path.join(audio_name,'metadata.jsonl'))
99
+ _ = upload_file(path_or_fileobj = json_file_path,
100
+ path_in_repo =repo_json_path,
101
+ repo_id='meyabase/crowd-oshiwambo-speech-greetings',
102
+ repo_type='dataset',
103
+ token=HF_TOKEN
104
+ )
105
+
106
+ output = f'Recording successfully saved! On to the next one...'
107
+
108
+ # Choose the next greeting
109
+ greeting_history.append(current_greeting)
110
+
111
+ # check the language selected and choose the next greeting based on the images available
112
+ if language=='oshindonga':
113
+ greeting_choices = [greet for greet in [i for i in range(3)] if greet not in greeting_history]
114
+ if greeting_choices!=[]:
115
+ next_greeting = random.choice(greeting_choices)
116
+ next_greeting_image = f'greetings/{language}/{next_greeting}.png'
117
+ else:
118
+ done_recording=True
119
+ next_greeting = 0
120
+ next_greeting_image = 'greetings/best.gif'
121
+ output = "You have finished all recording! You can reload to start again."
122
+
123
+ elif language=='oshikwanyama':
124
+ greeting_choices = [greet for greet in [i for i in range(3)] if greet not in greeting_history]
125
+ if greeting_choices!=[]:
126
+ next_greeting = random.choice(greeting_choices)
127
+ next_greeting_image = f'greetings/{language}/{next_greeting}.png'
128
+ else:
129
+ done_recording=True
130
+ next_greeting = 0
131
+ next_greeting_image = 'greetings/best.gif'
132
+ output = "You have finished all recording! You can reload to start again."
133
+
134
+ output_string = "<html> <body> <div class='output' style='color:green; font-size:13px'>"+output+"</div> </body> </html>"
135
+ return output_string,next_greeting_image,greeting_history,next_greeting,done_recording,default_record
136
+
137
+ if greeting is None:
138
+ output = "greeting must be specified!"
139
+ if record is None:
140
+ output="No recording found!"
141
+ if language is None or language=='Choose language':
142
+ output = 'Language must be specified!'
143
+ output_string = "<html> <body> <div class='output' style='color:green; font-size:13px'>"+output+"</div> </body> </html>"
144
+
145
+ # return output_string, previous image and state
146
+ return output_string, greeting,greeting_history,current_greeting,done_recording,default_record
147
+ else:
148
+
149
+ # Stop submitting recording (best.gif is displaying)
150
+ output = '🙌 You have finished all recording! Thank You. You can reload to start again.'
151
+ output_string = "<div class='finished'>"+output+"</div>"
152
+ next_greeting = 0 # the default greeting
153
+ next_greeting_image = 'greetings/best.gif'
154
+ return output_string,next_greeting_image,greeting_history,next_greeting,done_recording,default_record
155
+
156
+
157
+ def get_metadata_json(path):
158
+ try:
159
+ return read_json_lines(path)[0]
160
+ except Exception:
161
+ return []
162
+
163
+ def get_metadata_of_dataset():
164
+ repo.git_pull()
165
+ REPOSITORY_DATA_DIR = os.path.join(REPOSITORY_DIR,'data')
166
+ repo_recordings = [os.path.join(REPOSITORY_DATA_DIR,f.name) for f in os.scandir(REPOSITORY_DATA_DIR)] if os.path.isdir(REPOSITORY_DATA_DIR) else []
167
+
168
+ audio_repo = [os.path.join(f,'audio.wav') for f in repo_recordings]
169
+ audio_repo = [a.replace('data/data/','https://huggingface.co/datasets/meyabase/crowd-oshiwambo-speech-greetings/resolve/main/data/') for a in audio_repo]
170
+ metadata_all = [get_metadata_json(os.path.join(f,'metadata.jsonl')) for f in repo_recordings]
171
+ metadata_all = [m for m in metadata_all if m!=[]]
172
+ return metadata_all
173
+
174
+ def display_records():
175
+ repo.git_pull()
176
+ REPOSITORY_DATA_DIR = os.path.join(REPOSITORY_DIR,'data')
177
+ repo_recordings = [os.path.join(REPOSITORY_DATA_DIR,f.name) for f in os.scandir(REPOSITORY_DATA_DIR)] if os.path.isdir(REPOSITORY_DATA_DIR) else []
178
+
179
+ audio_repo = [os.path.join(f,'audio.wav') for f in repo_recordings]
180
+ audio_repo = [a.replace('data/data/','https://huggingface.co/datasets/meyabase/crowd-oshiwambo-speech-greetings/resolve/main/data/') for a in audio_repo]
181
+ metadata_repo = [read_json_lines(os.path.join(f,'metadata.jsonl'))[0] for f in repo_recordings]
182
+ audios_all = audio_repo
183
+ metadata_all = metadata_repo
184
+
185
+
186
+ langs=[m['language_name'] for m in metadata_all]
187
+ audios = [a for a in audios_all]
188
+ texts = [m['text'] for m in metadata_all]
189
+ greetings = [m['greeting'] for m in metadata_all]
190
+
191
+
192
+ html = f"""<div class="infoPoint">
193
+ <h1> Hooray! We have collected {len(metadata_all)} samples!</h1>
194
+ <table style="width:100%; text-align:center">
195
+ <tr>
196
+ <th>language</th>
197
+ <th>audio</th>
198
+ <th>greeting</th>
199
+ <th>text</th>
200
+ </tr>"""
201
+ for lang, audio, text,greet_ in zip(langs,audios,texts,greetings):
202
+ html+= f"""<tr>
203
+ <td>{lang}</td>
204
+ <td><audio controls><source src="{audio}" type="audio/wav"> </audio></td>
205
+ <td>{greet_}</td>
206
+ <td>{text}</td>
207
+ </tr>"""
208
+ html+="</table></div>"
209
+ return html
210
+
211
+ markdown = """<div style="text-align: center"><p style="font-size: 40px"> 🔊 <b>Oshiwambo Speech Greetings</b></p> <br>
212
+ This is a platform to contribute to your Oshiwambo greeting for the speech recognition task. <br> </div>"""
213
+
214
+ record_markdown = """
215
+ <br> Record greetings in your language and help us build a dataset for speech recognition in Oshiwambo. <br>
216
+ """
217
+
218
+ # # Interface design begins
219
+ block = gr.Blocks(css=BLOCK_CSS)
220
+ with block:
221
+ gr.Markdown(markdown)
222
+ with gr.Tabs():
223
+
224
+ with gr.TabItem('Record'):
225
+ gr.Markdown(record_markdown)
226
+
227
+ with gr.Row():
228
+ language = gr.inputs.Dropdown(choices = sorted([lang_.title() for lang_ in list(languages)]), label="Choose language", default=languages[0].title())
229
+ gender = gr.inputs.Dropdown(choices=GENDER, type="value", default=None, label="Gender (optional)")
230
+ accent = gr.inputs.Textbox(label="Accent (optional)", default='', placeholder="e.g. oshikwanyama, oshindonga, oshimbadja, oshingadjera, etc.")
231
+
232
+ # define a default greeting first for each language
233
+ greeting = gr.Image(f'greetings/{languages[0].lower()}/0.png', image_mode="L")
234
+
235
+ greeting_history = gr.Variable() # stores the history of greetings
236
+
237
+ record = gr.Audio(source="microphone", label='Record your voice')
238
+ output_result = gr.outputs.HTML()
239
+ state = gr.Variable()
240
+ current_greeting = gr.Variable()
241
+ done_recording = gr.Variable() # Signifies when to stop submitting records even if `submit`` is clicked
242
+ save = gr.Button("Submit")
243
+
244
+ save.click(save_record, inputs=[language,record,greeting,gender,accent,state,current_greeting,done_recording],outputs=[output_result,greeting,state,current_greeting,done_recording,record])
245
+
246
+ block.launch()
247
+
248
+
greetings/.DS_Store ADDED
Binary file (6.15 kB). View file
 
greetings/best.gif ADDED
greetings/oshikwanyama/0.png ADDED
greetings/oshikwanyama/1.png ADDED
greetings/oshikwanyama/2.png ADDED
greetings/oshindonga/0.png ADDED
greetings/oshindonga/1.png ADDED
greetings/oshindonga/2.png ADDED
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ pandas
2
+ scipy
3
+ pycountry
4
+ numpy
5
+ matplotlib
6
+ datasets
7
+ transformers
8
+ librosa
9
+ torch
10
+ huggingface-hub>=0.9.1
11
+ torchaudio
utils.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import hashlib
3
+ import random
4
+ import string
5
+
6
+
7
+
8
+ def get_unique_name():
9
+ return ''.join([random.choice(string.ascii_letters
10
+ + string.digits) for n in range(32)])
11
+
12
+
13
+ def read_json_lines(file):
14
+ with open(file,'r',encoding="utf8") as f:
15
+ lines = f.readlines()
16
+ data=[]
17
+ for l in lines:
18
+ data.append(json.loads(l))
19
+ return data
20
+
21
+
22
+ def json_dump(thing):
23
+ return json.dumps(thing,
24
+ ensure_ascii=False,
25
+ sort_keys=True,
26
+ indent=None,
27
+ separators=(',', ':'))
28
+
29
+ def get_hash(thing): # stable-hashing
30
+ return str(hashlib.md5(json_dump(thing).encode('utf-8')).hexdigest())
31
+
32
+
33
+ def dump_json(thing,file):
34
+ with open(file,'w+',encoding="utf8") as f:
35
+ json.dump(thing,f)
36
+
37
+ def read_json_lines(file):
38
+ with open(file,'r',encoding="utf8") as f:
39
+ lines = f.readlines()
40
+ data=[]
41
+ for l in lines:
42
+ data.append(json.loads(l))
43
+ return data