hunterschep commited on
Commit
40d6177
·
verified ·
1 Parent(s): b422101

fix chinese

Browse files
Files changed (1) hide show
  1. app.py +102 -143
app.py CHANGED
@@ -12,7 +12,7 @@ import tempfile
12
 
13
  # Initialize Firebase
14
  firebase_config = json.loads(os.environ.get('firebase_creds'))
15
- cred = credentials.Certificate(firebase_config)
16
  firebase_admin.initialize_app(cred)
17
  db = firestore.client()
18
 
@@ -21,61 +21,18 @@ MODEL_NAME = "eleferrand/xlsr53_Amis"
21
  processor = Wav2Vec2Processor.from_pretrained(MODEL_NAME)
22
  model = AutoModelForCTC.from_pretrained(MODEL_NAME)
23
 
24
- # Language configuration
25
- LANGUAGE = {
26
- "en": {
27
- "title": "ASR Demo with Editable Transcription",
28
- "step1": "Step 1: Audio Upload & Transcription",
29
- "audio_input": "Audio Input",
30
- "transcribe_btn": "Transcribe Audio",
31
- "step2": "Step 2: Review & Edit Transcription",
32
- "original_text": "Original Transcription",
33
- "corrected_text": "Corrected Transcription",
34
- "transcription_placeholder": "Transcription will appear here...",
35
- "step3": "Step 3: User Information",
36
- "age_label": "Age",
37
- "native_speaker": "Native Amis Speaker",
38
- "step4": "Step 4: Save & Download",
39
- "save_btn": "Save Correction to Database",
40
- "save_status": "Save Status",
41
- "download_btn": "Download Results (ZIP)",
42
- "status_placeholder": "Status messages will appear here...",
43
- "toggle_lang": "中文/English"
44
- },
45
- "zh": {
46
- "title": "可編輯轉寫的語音辨識演示",
47
- "step1": "步驟一: 音頻上傳與轉寫",
48
- "audio_input": "音頻輸入",
49
- "transcribe_btn": "開始轉寫",
50
- "step2": "步驟二: 校對與編輯轉寫結果",
51
- "original_text": "原始轉寫結果",
52
- "corrected_text": "校正後文本",
53
- "transcription_placeholder": "轉寫結果將顯示在此處...",
54
- "step3": "步驟三: 用戶資訊",
55
- "age_label": "年齡",
56
- "native_speaker": "阿美族母語者",
57
- "step4": "步驟四: 保存與下載",
58
- "save_btn": "保存校正結果至數據庫",
59
- "save_status": "保存狀態",
60
- "download_btn": "下載結果(ZIP壓縮檔)",
61
- "status_placeholder": "狀態訊息將顯示在此處...",
62
- "toggle_lang": "English/中文"
63
- }
64
- }
65
-
66
- current_lang = gr.State(value="en")
67
-
68
  def transcribe(audio_file):
69
  try:
70
  audio, rate = librosa.load(audio_file, sr=16000)
71
  input_values = processor(audio, sampling_rate=16000, return_tensors="pt").input_values
 
72
  with torch.no_grad():
73
  logits = model(input_values).logits
74
  predicted_ids = torch.argmax(logits, dim=-1)
75
  transcription = processor.batch_decode(predicted_ids)[0]
76
  return transcription.replace("[UNK]", "")
77
  except Exception as e:
78
- return f"Error processing file: {e}"
79
 
80
  def transcribe_both(audio_file):
81
  start_time = datetime.now()
@@ -105,23 +62,26 @@ def store_correction(original_transcription, corrected_transcription, audio_file
105
  }
106
  }
107
  db.collection('transcriptions').add(combined_data)
108
- return "Correction saved successfully!"
109
  except Exception as e:
110
- return f"Error saving correction: {e}"
111
 
112
  def prepare_download(audio_file, original_transcription, corrected_transcription):
113
  if audio_file is None:
114
  return None
 
115
  tmp_zip = tempfile.NamedTemporaryFile(delete=False, suffix=".zip")
116
  tmp_zip.close()
117
  with zipfile.ZipFile(tmp_zip.name, "w") as zf:
118
  if os.path.exists(audio_file):
119
  zf.write(audio_file, arcname="audio.wav")
 
120
  orig_txt = "original_transcription.txt"
121
  with open(orig_txt, "w", encoding="utf-8") as f:
122
  f.write(original_transcription)
123
  zf.write(orig_txt, arcname="original_transcription.txt")
124
  os.remove(orig_txt)
 
125
  corr_txt = "corrected_transcription.txt"
126
  with open(corr_txt, "w", encoding="utf-8") as f:
127
  f.write(corrected_transcription)
@@ -129,117 +89,116 @@ def prepare_download(audio_file, original_transcription, corrected_transcription
129
  os.remove(corr_txt)
130
  return tmp_zip.name
131
 
132
- def toggle_language(lang):
133
- new_lang = "zh" if lang == "en" else "en"
134
- lang_dict = LANGUAGE[new_lang]
135
- return [
136
- gr.Markdown.update(value=f"<h1 class='header'>{lang_dict['title']}</h1>"),
137
- gr.Markdown.update(value=f"### {lang_dict['step1']}"),
138
- gr.Audio.update(label=lang_dict['audio_input']),
139
- gr.Button.update(value=lang_dict['transcribe_btn']),
140
- gr.Markdown.update(value=f"### {lang_dict['step2']}"),
141
- gr.Textbox.update(label=lang_dict['original_text'], placeholder=lang_dict['transcription_placeholder']),
142
- gr.Textbox.update(label=lang_dict['corrected_text'], placeholder=lang_dict['transcription_placeholder']),
143
- gr.Markdown.update(value=f"### {lang_dict['step3']}"),
144
- gr.Slider.update(label=lang_dict['age_label']),
145
- gr.Checkbox.update(label=lang_dict['native_speaker']),
146
- gr.Markdown.update(value=f"### {lang_dict['step4']}"),
147
- gr.Button.update(value=lang_dict['save_btn']),
148
- gr.Textbox.update(label=lang_dict['save_status'], placeholder=lang_dict['status_placeholder']),
149
- gr.Button.update(value=lang_dict['download_btn']),
150
- gr.File.update(label=lang_dict['download_btn']),
151
- gr.Button.update(value=lang_dict['toggle_lang']),
152
- new_lang
153
- ]
154
-
155
  with gr.Blocks(css="""
156
- .container { max-width: 800px; margin: auto; padding: 20px; font-family: Arial, sans-serif; }
157
- .header { text-align: center; margin-bottom: 30px; }
158
- .section { margin-bottom: 30px; padding: 15px; border: 1px solid #ddd; border-radius: 8px; background-color: #f9f9f9; }
159
- .section h3 { margin-top: 0; margin-bottom: 15px; text-align: center; }
160
- .button-row { display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; }
161
- .lang-toggle { position: absolute; top: 20px; right: 20px; }
162
- @media (max-width: 600px) { .gradio-row { flex-direction: column; } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  """) as demo:
164
- current_lang.render()
165
-
166
  with gr.Column(elem_classes="container"):
167
- with gr.Row():
168
- title_md = gr.Markdown(elem_classes="header")
169
- lang_btn = gr.Button(LANGUAGE['en']['toggle_lang'], elem_classes="lang-toggle")
170
 
171
- # Step 1
172
  with gr.Column(elem_classes="section"):
173
- step1_md = gr.Markdown()
174
  with gr.Row():
175
- audio_input = gr.Audio(sources=["upload", "microphone"], type="filepath")
176
- transcribe_button = gr.Button(variant="primary")
 
 
 
 
177
  proc_time_state = gr.State()
178
 
179
- # Step 2
180
  with gr.Column(elem_classes="section"):
181
- step2_md = gr.Markdown()
182
  with gr.Row():
183
- original_text = gr.Textbox(interactive=False, lines=5)
184
- corrected_text = gr.Textbox(interactive=True, lines=5)
 
 
 
 
 
 
 
 
 
 
185
 
186
- # Step 3
187
  with gr.Column(elem_classes="section"):
188
- step3_md = gr.Markdown()
189
  with gr.Row():
190
- age_input = gr.Slider(minimum=0, maximum=100, step=1, value=25)
191
- native_speaker_input = gr.Checkbox(value=True)
 
 
 
 
 
 
 
 
 
192
 
193
- # Step 4
194
  with gr.Column(elem_classes="section"):
195
- step4_md = gr.Markdown()
196
  with gr.Row(elem_classes="button-row"):
197
- save_button = gr.Button(variant="primary")
198
- save_status = gr.Textbox(interactive=False)
 
 
 
 
199
  with gr.Row(elem_classes="button-row"):
200
- download_button = gr.Button()
201
- download_output = gr.File()
202
-
203
- lang_btn.click(
204
- toggle_language,
205
- inputs=current_lang,
206
- outputs=[
207
- title_md, step1_md, audio_input, transcribe_button,
208
- step2_md, original_text, corrected_text, step3_md,
209
- age_input, native_speaker_input, step4_md, save_button,
210
- save_status, download_button, download_output, lang_btn,
211
- current_lang
212
- ]
213
- )
214
-
215
- transcribe_button.click(
216
- transcribe_both,
217
- inputs=audio_input,
218
- outputs=[original_text, corrected_text, proc_time_state]
219
- )
220
-
221
- save_button.click(
222
- store_correction,
223
- inputs=[original_text, corrected_text, audio_input, proc_time_state, age_input, native_speaker_input],
224
- outputs=save_status
225
- )
226
-
227
- download_button.click(
228
- prepare_download,
229
- inputs=[audio_input, original_text, corrected_text],
230
- outputs=download_output
231
- )
232
-
233
- demo.load(
234
- toggle_language,
235
- inputs=current_lang,
236
- outputs=[
237
- title_md, step1_md, audio_input, transcribe_button,
238
- step2_md, original_text, corrected_text, step3_md,
239
- age_input, native_speaker_input, step4_md, save_button,
240
- save_status, download_button, download_output, lang_btn,
241
- current_lang
242
- ]
243
- )
244
 
245
  demo.launch(share=True)
 
12
 
13
  # Initialize Firebase
14
  firebase_config = json.loads(os.environ.get('firebase_creds'))
15
+ cred = credentials.Certificate(firebase_config) # Your Firebase JSON key file
16
  firebase_admin.initialize_app(cred)
17
  db = firestore.client()
18
 
 
21
  processor = Wav2Vec2Processor.from_pretrained(MODEL_NAME)
22
  model = AutoModelForCTC.from_pretrained(MODEL_NAME)
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  def transcribe(audio_file):
25
  try:
26
  audio, rate = librosa.load(audio_file, sr=16000)
27
  input_values = processor(audio, sampling_rate=16000, return_tensors="pt").input_values
28
+
29
  with torch.no_grad():
30
  logits = model(input_values).logits
31
  predicted_ids = torch.argmax(logits, dim=-1)
32
  transcription = processor.batch_decode(predicted_ids)[0]
33
  return transcription.replace("[UNK]", "")
34
  except Exception as e:
35
+ return f"处理文件错误: {e}"
36
 
37
  def transcribe_both(audio_file):
38
  start_time = datetime.now()
 
62
  }
63
  }
64
  db.collection('transcriptions').add(combined_data)
65
+ return "校正保存成功! (Correction saved successfully!)"
66
  except Exception as e:
67
+ return f"保存失败: {e} (Error saving correction: {e})"
68
 
69
  def prepare_download(audio_file, original_transcription, corrected_transcription):
70
  if audio_file is None:
71
  return None
72
+
73
  tmp_zip = tempfile.NamedTemporaryFile(delete=False, suffix=".zip")
74
  tmp_zip.close()
75
  with zipfile.ZipFile(tmp_zip.name, "w") as zf:
76
  if os.path.exists(audio_file):
77
  zf.write(audio_file, arcname="audio.wav")
78
+
79
  orig_txt = "original_transcription.txt"
80
  with open(orig_txt, "w", encoding="utf-8") as f:
81
  f.write(original_transcription)
82
  zf.write(orig_txt, arcname="original_transcription.txt")
83
  os.remove(orig_txt)
84
+
85
  corr_txt = "corrected_transcription.txt"
86
  with open(corr_txt, "w", encoding="utf-8") as f:
87
  f.write(corrected_transcription)
 
89
  os.remove(corr_txt)
90
  return tmp_zip.name
91
 
92
+ # 界面设计
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  with gr.Blocks(css="""
94
+ .container {
95
+ max-width: 800px;
96
+ margin: auto;
97
+ padding: 20px;
98
+ font-family: Arial, sans-serif;
99
+ }
100
+ .header {
101
+ text-align: center;
102
+ margin-bottom: 30px;
103
+ }
104
+ .section {
105
+ margin-bottom: 30px;
106
+ padding: 15px;
107
+ border: 1px solid #ddd;
108
+ border-radius: 8px;
109
+ background-color: #f9f9f9;
110
+ }
111
+ .section h3 {
112
+ margin-top: 0;
113
+ margin-bottom: 15px;
114
+ text-align: center;
115
+ }
116
+ .button-row {
117
+ display: flex;
118
+ justify-content: center;
119
+ gap: 10px;
120
+ flex-wrap: wrap;
121
+ }
122
+ @media (max-width: 600px) {
123
+ .gradio-row {
124
+ flex-direction: column;
125
+ }
126
+ }
127
  """) as demo:
 
 
128
  with gr.Column(elem_classes="container"):
129
+ gr.Markdown("<h1 class='header'>阿美語轉錄與修正系統 (ASR Correction System)</h1>")
 
 
130
 
 
131
  with gr.Column(elem_classes="section"):
132
+ gr.Markdown("### 步驟 1:音訊上傳與轉錄(Audio Upload & Transcription)")
133
  with gr.Row():
134
+ audio_input = gr.Audio(
135
+ sources=["upload", "microphone"],
136
+ type="filepath",
137
+ label="音訊輸入 (Audio Input)"
138
+ )
139
+ transcribe_button = gr.Button("轉錄音訊 (Transcribe Audio)", variant="primary")
140
  proc_time_state = gr.State()
141
 
 
142
  with gr.Column(elem_classes="section"):
143
+ gr.Markdown("### 步驟 2:審閱與編輯轉錄 (Review & Edit Transcription)")
144
  with gr.Row():
145
+ original_text = gr.Textbox(
146
+ label="原始轉錄 (Original Transcription)",
147
+ interactive=False,
148
+ lines=5,
149
+ placeholder="謄本將在此出現... (Transcription will appear here...)"
150
+ )
151
+ corrected_text = gr.Textbox(
152
+ label="更正轉錄 (Corrected Transcription)",
153
+ interactive=True,
154
+ lines=5,
155
+ placeholder="在此編輯轉錄... (Edit transcription here...)"
156
+ )
157
 
 
158
  with gr.Column(elem_classes="section"):
159
+ gr.Markdown("### 步驟 3:使用者資訊 (User Information)")
160
  with gr.Row():
161
+ age_input = gr.Slider(
162
+ minimum=0,
163
+ maximum=100,
164
+ step=1,
165
+ label="年齡 (Age)",
166
+ value=25
167
+ )
168
+ native_speaker_input = gr.Checkbox(
169
+ label="以阿美語為母語? (Native Amis Speaker?)",
170
+ value=True
171
+ )
172
 
 
173
  with gr.Column(elem_classes="section"):
174
+ gr.Markdown("### 步驟 4:儲存與下載 (Save & Download)")
175
  with gr.Row(elem_classes="button-row"):
176
+ save_button = gr.Button("儲存更正 (Save Correction)", variant="primary")
177
+ save_status = gr.Textbox(
178
+ label="儲存狀態 (Save Status)",
179
+ interactive=False,
180
+ placeholder="狀態訊息會出現在這裡... (Status messages will appear here...)"
181
+ )
182
  with gr.Row(elem_classes="button-row"):
183
+ download_button = gr.Button("下載 ZIP 檔案 (Download ZIP)")
184
+ download_output = gr.File(label="下載 ZIP 檔案 (Download ZIP)")
185
+
186
+ transcribe_button.click(
187
+ fn=transcribe_both,
188
+ inputs=audio_input,
189
+ outputs=[original_text, corrected_text, proc_time_state]
190
+ )
191
+
192
+ save_button.click(
193
+ fn=store_correction,
194
+ inputs=[original_text, corrected_text, audio_input, proc_time_state, age_input, native_speaker_input],
195
+ outputs=save_status
196
+ )
197
+
198
+ download_button.click(
199
+ fn=prepare_download,
200
+ inputs=[audio_input, original_text, corrected_text],
201
+ outputs=download_output
202
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
  demo.launch(share=True)