sudhanm commited on
Commit
ffea970
·
verified ·
1 Parent(s): eecaaa5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -106
app.py CHANGED
@@ -163,25 +163,51 @@ def transliterate_to_hk(text, lang_choice):
163
  print(f"Transliteration error: {e}")
164
  return text
165
 
166
- def transliterate_to_roman(text, lang_choice):
167
- """Transliterate to more readable Roman script"""
168
  if not text or not text.strip():
169
  return ""
170
 
171
- mapping = {
172
- "Tamil": sanscript.TAMIL,
173
- "Malayalam": sanscript.MALAYALAM,
174
- "English": None
175
- }
176
-
177
- if mapping[lang_choice] is None:
178
  return text # Return as-is for English
179
 
180
  try:
181
- # Clean the text and transliterate to IAST (more readable)
182
- cleaned_text = text.strip()
183
- transliterated = transliterate(cleaned_text, mapping[lang_choice], sanscript.IAST)
184
- return transliterated if transliterated else text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  except Exception as e:
186
  print(f"Transliteration error: {e}")
187
  return text
@@ -222,11 +248,11 @@ def transcribe_once(audio_path, language_choice, beam_size, temperature):
222
  return transcription.strip()
223
 
224
  def create_tabular_feedback(intended, actual, lang_choice):
225
- """Create comprehensive tabular feedback with transliteration"""
226
 
227
- # Get transliterations
228
- intended_roman = transliterate_to_roman(intended, lang_choice)
229
- actual_roman = transliterate_to_roman(actual, lang_choice)
230
  intended_hk = transliterate_to_hk(intended, lang_choice)
231
  actual_hk = transliterate_to_hk(actual, lang_choice)
232
 
@@ -242,49 +268,49 @@ def create_tabular_feedback(intended, actual, lang_choice):
242
 
243
  # Create word-by-word comparison table
244
  feedback_html = """
245
- <div style='font-family: Arial, sans-serif; padding: 20px; background: #f8f9fa; border-radius: 12px; margin: 10px 0;'>
246
  <h3 style='color: #2c3e50; margin-bottom: 20px; text-align: center;'>📊 Pronunciation Analysis</h3>
247
  """
248
 
249
- # Overview table
250
  feedback_html += """
251
  <div style='margin-bottom: 25px;'>
252
  <h4 style='color: #34495e; margin-bottom: 15px;'>📝 Text Comparison</h4>
253
- <table style='width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.1);'>
254
  <thead>
255
- <tr style='background: #3498db; color: white;'>
256
- <th style='padding: 12px; text-align: left; font-weight: bold;'>Type</th>
257
- <th style='padding: 12px; text-align: left; font-weight: bold;'>Original Script</th>
258
- <th style='padding: 12px; text-align: left; font-weight: bold;'>Roman/IAST</th>
259
  </tr>
260
  </thead>
261
  <tbody>
262
- <tr style='background: #e8f5e8;'>
263
- <td style='padding: 12px; font-weight: bold; color: #27ae60;'>🎯 Target</td>
264
- <td style='padding: 12px; font-family: monospace;'>{}</td>
265
- <td style='padding: 12px; font-family: monospace; font-style: italic;'>{}</td>
266
  </tr>
267
- <tr style='background: #fff3e0;'>
268
- <td style='padding: 12px; font-weight: bold; color: #e67e22;'>🗣️ You Said</td>
269
- <td style='padding: 12px; font-family: monospace;'>{}</td>
270
- <td style='padding: 12px; font-family: monospace; font-style: italic;'>{}</td>
271
  </tr>
272
  </tbody>
273
  </table>
274
  </div>
275
  """.format(intended, intended_roman, actual, actual_roman)
276
 
277
- # Word-by-word analysis
278
  feedback_html += """
279
  <div style='margin-bottom: 25px;'>
280
- <h4 style='color: #34495e; margin-bottom: 15px;'>🔍 Word-by-Word Analysis</h4>
281
- <table style='width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.1);'>
282
  <thead>
283
- <tr style='background: #9b59b6; color: white;'>
284
- <th style='padding: 12px; text-align: center; font-weight: bold;'>#</th>
285
- <th style='padding: 12px; text-align: left; font-weight: bold;'>Expected</th>
286
- <th style='padding: 12px; text-align: left; font-weight: bold;'>You Said</th>
287
- <th style='padding: 12px; text-align: center; font-weight: bold;'>Status</th>
288
  </tr>
289
  </thead>
290
  <tbody>
@@ -296,7 +322,7 @@ def create_tabular_feedback(intended, actual, lang_choice):
296
 
297
  for tag, i1, i2, j1, j2 in sm.get_opcodes():
298
  if tag == 'equal':
299
- # Correct words
300
  for idx, word in enumerate(intended_words[i1:i2]):
301
  word_index += 1
302
  correct_words += 1
@@ -305,24 +331,25 @@ def create_tabular_feedback(intended, actual, lang_choice):
305
  actual_roman_word = actual_roman_words[j1 + idx] if (j1 + idx) < len(actual_roman_words) else ""
306
 
307
  feedback_html += f"""
308
- <tr style='background: #d4f6d4;'>
309
- <td style='padding: 10px; text-align: center; font-weight: bold;'>{word_index}</td>
310
- <td style='padding: 10px;'>
311
- <div style='font-family: monospace; font-size: 16px;'>{word}</div>
312
- <div style='font-size: 12px; color: #666; font-style: italic;'>{roman_word}</div>
313
  </td>
314
- <td style='padding: 10px;'>
315
- <div style='font-family: monospace; font-size: 16px; color: #27ae60;'>{actual_word}</div>
316
- <div style='font-size: 12px; color: #666; font-style: italic;'>{actual_roman_word}</div>
317
  </td>
318
- <td style='padding: 10px; text-align: center;'>
319
- <span style='background: #27ae60; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px;'>✓ Correct</span>
 
320
  </td>
321
  </tr>
322
  """
323
 
324
  elif tag == 'replace':
325
- # Incorrect words
326
  max_words = max(i2-i1, j2-j1)
327
  for idx in range(max_words):
328
  word_index += 1
@@ -332,18 +359,19 @@ def create_tabular_feedback(intended, actual, lang_choice):
332
  actual_roman_word = actual_roman_words[j1 + idx] if (j1 + idx) < len(actual_roman_words) else ""
333
 
334
  feedback_html += f"""
335
- <tr style='background: #ffebee;'>
336
- <td style='padding: 10px; text-align: center; font-weight: bold;'>{word_index}</td>
337
- <td style='padding: 10px;'>
338
- <div style='font-family: monospace; font-size: 16px;'>{expected_word}</div>
339
- <div style='font-size: 12px; color: #666; font-style: italic;'>{expected_roman}</div>
340
  </td>
341
- <td style='padding: 10px;'>
342
- <div style='font-family: monospace; font-size: 16px; color: #e74c3c;'>{actual_word}</div>
343
- <div style='font-size: 12px; color: #666; font-style: italic;'>{actual_roman_word}</div>
344
  </td>
345
- <td style='padding: 10px; text-align: center;'>
346
- <span style='background: #e74c3c; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px;'>✗ Different</span>
 
347
  </td>
348
  </tr>
349
  """
@@ -354,17 +382,18 @@ def create_tabular_feedback(intended, actual, lang_choice):
354
  word_index += 1
355
  roman_word = intended_roman_words[i1 + idx] if (i1 + idx) < len(intended_roman_words) else ""
356
  feedback_html += f"""
357
- <tr style='background: #ffeaa7;'>
358
- <td style='padding: 10px; text-align: center; font-weight: bold;'>{word_index}</td>
359
- <td style='padding: 10px;'>
360
- <div style='font-family: monospace; font-size: 16px;'>{word}</div>
361
- <div style='font-size: 12px; color: #666; font-style: italic;'>{roman_word}</div>
362
  </td>
363
- <td style='padding: 10px; color: #e17055; font-style: italic;'>
364
  <em>Not spoken</em>
365
  </td>
366
- <td style='padding: 10px; text-align: center;'>
367
- <span style='background: #fdcb6e; color: #2d3436; padding: 4px 8px; border-radius: 12px; font-size: 12px;'>⚠ Missing</span>
 
368
  </td>
369
  </tr>
370
  """
@@ -374,17 +403,18 @@ def create_tabular_feedback(intended, actual, lang_choice):
374
  for idx, word in enumerate(actual_words[j1:j2]):
375
  actual_roman_word = actual_roman_words[j1 + idx] if (j1 + idx) < len(actual_roman_words) else ""
376
  feedback_html += f"""
377
- <tr style='background: #fab1a0;'>
378
- <td style='padding: 10px; text-align: center; font-weight: bold;'>+</td>
379
- <td style='padding: 10px; color: #636e72; font-style: italic;'>
380
  <em>Not expected</em>
381
  </td>
382
- <td style='padding: 10px;'>
383
- <div style='font-family: monospace; font-size: 16px; color: #e17055;'>{word}</div>
384
- <div style='font-size: 12px; color: #666; font-style: italic;'>{actual_roman_word}</div>
385
  </td>
386
- <td style='padding: 10px; text-align: center;'>
387
- <span style='background: #fd79a8; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px;'>+ Extra</span>
 
388
  </td>
389
  </tr>
390
  """
@@ -398,32 +428,32 @@ def create_tabular_feedback(intended, actual, lang_choice):
398
  # Calculate accuracy
399
  accuracy = (correct_words / total_words * 100) if total_words > 0 else 0
400
 
401
- # Summary section
402
  feedback_html += f"""
403
- <div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 12px; text-align: center;'>
404
- <h4 style='margin: 0 0 15px 0; font-size: 24px;'>🎯 Performance Summary</h4>
405
- <div style='display: flex; justify-content: space-around; flex-wrap: wrap; gap: 15px;'>
406
- <div style='background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px; min-width: 150px;'>
407
- <div style='font-size: 32px; font-weight: bold;'>{accuracy:.1f}%</div>
408
- <div style='font-size: 14px; opacity: 0.9;'>Word Accuracy</div>
409
  </div>
410
- <div style='background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px; min-width: 150px;'>
411
- <div style='font-size: 32px; font-weight: bold;'>{correct_words}/{total_words}</div>
412
- <div style='font-size: 14px; opacity: 0.9;'>Correct Words</div>
413
  </div>
414
  </div>
415
- <div style='margin-top: 15px; font-size: 18px;'>
416
  """
417
 
418
- # Motivational message
419
  if accuracy >= 95:
420
- feedback_html += "<span>🎉 Outstanding! Perfect pronunciation!</span>"
421
  elif accuracy >= 85:
422
- feedback_html += "<span>🌟 Excellent work! Very clear pronunciation!</span>"
423
  elif accuracy >= 70:
424
- feedback_html += "<span>👍 Good job! Keep practicing those tricky words!</span>"
425
  elif accuracy >= 50:
426
- feedback_html += "<span>📚 Making progress! Focus on the highlighted words!</span>"
427
  else:
428
  feedback_html += "<span>💪 Keep going! Practice makes perfect!</span>"
429
 
@@ -432,22 +462,22 @@ def create_tabular_feedback(intended, actual, lang_choice):
432
  </div>
433
  """
434
 
435
- # Add HK transliteration section for reference
436
  if lang_choice in ["Tamil", "Malayalam"]:
437
  feedback_html += f"""
438
- <div style='margin-top: 20px; padding: 15px; background: #ecf0f1; border-radius: 8px;'>
439
- <h4 style='color: #2c3e50; margin-bottom: 10px;'>🔤 Harvard-Kyoto Transliteration (for reference)</h4>
440
- <div style='display: grid; grid-template-columns: 1fr 1fr; gap: 15px;'>
441
  <div>
442
- <strong>Expected:</strong><br>
443
- <span style='font-family: monospace; background: white; padding: 8px; border-radius: 4px; display: block; margin-top: 5px;'>{intended_hk}</span>
444
  </div>
445
  <div>
446
- <strong>You said:</strong><br>
447
- <span style='font-family: monospace; background: white; padding: 8px; border-radius: 4px; display: block; margin-top: 5px;'>{actual_hk}</span>
448
  </div>
449
  </div>
450
- </div>
451
  """
452
 
453
  feedback_html += "</div>"
@@ -474,8 +504,8 @@ def compare_pronunciation(audio, lang_choice, intended_sentence, pass1_beam, pas
474
  cer_val = jiwer.cer(intended_sentence, actual_text)
475
 
476
  # Get transliterations for both texts
477
- intended_roman = transliterate_to_roman(intended_sentence, lang_choice)
478
- actual_roman = transliterate_to_roman(actual_text, lang_choice)
479
 
480
  # Create comprehensive tabular feedback
481
  feedback_html, accuracy = create_tabular_feedback(intended_sentence, actual_text, lang_choice)
@@ -539,7 +569,7 @@ with gr.Blocks(title="Pronunciation Comparator", theme=gr.themes.Soft()) as demo
539
  with gr.Row():
540
  with gr.Column():
541
  pass1_out = gr.Textbox(label="🗣️ What You Said", interactive=False)
542
- actual_roman_out = gr.Textbox(label="🔤 Your Pronunciation (Roman)", interactive=False)
543
  with gr.Column():
544
  wer_out = gr.Textbox(label="📊 Word Error Rate", interactive=False)
545
  cer_out = gr.Textbox(label="📈 Character Error Rate", interactive=False)
 
163
  print(f"Transliteration error: {e}")
164
  return text
165
 
166
+ def transliterate_to_simple_roman(text, lang_choice):
167
+ """Transliterate to very simple, easy-to-read Roman letters"""
168
  if not text or not text.strip():
169
  return ""
170
 
171
+ if lang_choice == "English":
 
 
 
 
 
 
172
  return text # Return as-is for English
173
 
174
  try:
175
+ # Direct character mapping to simple Roman letters
176
+ if lang_choice == "Tamil":
177
+ # Tamil to simple Roman mapping
178
+ tamil_map = {
179
+ 'அ': 'a', 'ஆ': 'aa', 'இ': 'i', 'ஈ': 'ee', 'உ': 'u', 'ஊ': 'oo',
180
+ 'எ': 'e', 'ஏ': 'e', 'ஐ': 'ai', 'ஒ': 'o', 'ஓ': 'o', 'ஔ': 'au',
181
+ 'க': 'ka', 'ங': 'nga', 'ச': 'cha', 'ஞ': 'nya', 'ட': 'ta', 'ண': 'na',
182
+ 'த': 'tha', 'ந': 'na', 'ப': 'pa', 'ம': 'ma', 'ய': 'ya', 'ர': 'ra',
183
+ 'ல': 'la', 'வ': 'va', 'ழ': 'zha', 'ள': 'la', 'ற': 'ra', 'ன': 'na',
184
+ '்': '', 'ா': 'aa', 'ி': 'i', 'ீ': 'ee', 'ு': 'u', 'ூ': 'oo',
185
+ 'ெ': 'e', 'ே': 'e', 'ை': 'ai', 'ொ': 'o', 'ோ': 'o', 'ௌ': 'au'
186
+ }
187
+ simple_text = ""
188
+ for char in text:
189
+ simple_text += tamil_map.get(char, char)
190
+ return simple_text
191
+
192
+ elif lang_choice == "Malayalam":
193
+ # Malayalam to simple Roman mapping
194
+ malayalam_map = {
195
+ 'അ': 'a', 'ആ': 'aa', 'ഇ': 'i', 'ഈ': 'ee', 'ഉ': 'u', 'ഊ': 'oo',
196
+ 'എ': 'e', 'ഏ': 'e', 'ഐ': 'ai', 'ഒ': 'o', 'ഓ': 'o', 'ഔ': 'au',
197
+ 'ക': 'ka', 'ഗ': 'ga', 'ങ': 'nga', 'ച': 'cha', 'ജ': 'ja', 'ഞ': 'nya',
198
+ 'ട': 'ta', 'ഡ': 'da', 'ണ': 'na', 'ത': 'tha', 'ദ': 'da', 'ന': 'na',
199
+ 'പ': 'pa', 'ബ': 'ba', 'മ': 'ma', 'യ': 'ya', 'ര': 'ra', 'ല': 'la',
200
+ 'വ': 'va', 'ശ': 'sha', 'ഷ': 'sha', 'സ': 'sa', 'ഹ': 'ha', 'ള': 'la',
201
+ '്': '', 'ാ': 'aa', 'ി': 'i', 'ീ': 'ee', 'ു': 'u', 'ൂ': 'oo',
202
+ 'െ': 'e', 'േ': 'e', 'ൈ': 'ai', 'ൊ': 'o', 'ോ': 'o', 'ൌ': 'au'
203
+ }
204
+ simple_text = ""
205
+ for char in text:
206
+ simple_text += malayalam_map.get(char, char)
207
+ return simple_text
208
+
209
+ return text
210
+
211
  except Exception as e:
212
  print(f"Transliteration error: {e}")
213
  return text
 
248
  return transcription.strip()
249
 
250
  def create_tabular_feedback(intended, actual, lang_choice):
251
+ """Create clean, readable tabular feedback without background colors"""
252
 
253
+ # Get simple transliterations
254
+ intended_roman = transliterate_to_simple_roman(intended, lang_choice)
255
+ actual_roman = transliterate_to_simple_roman(actual, lang_choice)
256
  intended_hk = transliterate_to_hk(intended, lang_choice)
257
  actual_hk = transliterate_to_hk(actual, lang_choice)
258
 
 
268
 
269
  # Create word-by-word comparison table
270
  feedback_html = """
271
+ <div style='font-family: Arial, sans-serif; padding: 20px; margin: 10px 0;'>
272
  <h3 style='color: #2c3e50; margin-bottom: 20px; text-align: center;'>📊 Pronunciation Analysis</h3>
273
  """
274
 
275
+ # Overview table - completely clean
276
  feedback_html += """
277
  <div style='margin-bottom: 25px;'>
278
  <h4 style='color: #34495e; margin-bottom: 15px;'>📝 Text Comparison</h4>
279
+ <table style='width: 100%; border-collapse: collapse; border: 2px solid #ddd;'>
280
  <thead>
281
+ <tr style='border-bottom: 2px solid #ddd;'>
282
+ <th style='padding: 15px; text-align: left; font-weight: bold; color: #2c3e50; border-right: 1px solid #ddd;'>Type</th>
283
+ <th style='padding: 15px; text-align: left; font-weight: bold; color: #2c3e50; border-right: 1px solid #ddd;'>Original Text</th>
284
+ <th style='padding: 15px; text-align: left; font-weight: bold; color: #2c3e50;'>Simple English Sounds</th>
285
  </tr>
286
  </thead>
287
  <tbody>
288
+ <tr style='border-bottom: 1px solid #ddd;'>
289
+ <td style='padding: 15px; font-weight: bold; color: #27ae60; border-right: 1px solid #ddd;'>🎯 Target</td>
290
+ <td style='padding: 15px; font-family: monospace; font-size: 18px; border-right: 1px solid #ddd;'>{}</td>
291
+ <td style='padding: 15px; font-family: monospace; font-size: 16px; color: #555;'>{}</td>
292
  </tr>
293
+ <tr>
294
+ <td style='padding: 15px; font-weight: bold; color: #e67e22; border-right: 1px solid #ddd;'>🗣️ You Said</td>
295
+ <td style='padding: 15px; font-family: monospace; font-size: 18px; border-right: 1px solid #ddd;'>{}</td>
296
+ <td style='padding: 15px; font-family: monospace; font-size: 16px; color: #555;'>{}</td>
297
  </tr>
298
  </tbody>
299
  </table>
300
  </div>
301
  """.format(intended, intended_roman, actual, actual_roman)
302
 
303
+ # Word-by-word analysis - clean table
304
  feedback_html += """
305
  <div style='margin-bottom: 25px;'>
306
+ <h4 style='color: #34495e; margin-bottom: 15px;'>🔍 Word-by-Word Check</h4>
307
+ <table style='width: 100%; border-collapse: collapse; border: 2px solid #ddd;'>
308
  <thead>
309
+ <tr style='border-bottom: 2px solid #ddd;'>
310
+ <th style='padding: 12px; text-align: center; font-weight: bold; color: #2c3e50; border-right: 1px solid #ddd;'>#</th>
311
+ <th style='padding: 12px; text-align: left; font-weight: bold; color: #2c3e50; border-right: 1px solid #ddd;'>Expected Word</th>
312
+ <th style='padding: 12px; text-align: left; font-weight: bold; color: #2c3e50; border-right: 1px solid #ddd;'>What You Said</th>
313
+ <th style='padding: 12px; text-align: center; font-weight: bold; color: #2c3e50;'>Result</th>
314
  </tr>
315
  </thead>
316
  <tbody>
 
322
 
323
  for tag, i1, i2, j1, j2 in sm.get_opcodes():
324
  if tag == 'equal':
325
+ # Correct words - clean white background
326
  for idx, word in enumerate(intended_words[i1:i2]):
327
  word_index += 1
328
  correct_words += 1
 
331
  actual_roman_word = actual_roman_words[j1 + idx] if (j1 + idx) < len(actual_roman_words) else ""
332
 
333
  feedback_html += f"""
334
+ <tr style='border-bottom: 1px solid #eee;'>
335
+ <td style='padding: 12px; text-align: center; font-weight: bold; color: #666; border-right: 1px solid #ddd;'>{word_index}</td>
336
+ <td style='padding: 12px; border-right: 1px solid #ddd;'>
337
+ <div style='font-family: monospace; font-size: 16px; margin-bottom: 4px;'>{word}</div>
338
+ <div style='font-size: 13px; color: #888;'>({roman_word})</div>
339
  </td>
340
+ <td style='padding: 12px; border-right: 1px solid #ddd;'>
341
+ <div style='font-family: monospace; font-size: 16px; margin-bottom: 4px; color: #27ae60;'>{actual_word}</div>
342
+ <div style='font-size: 13px; color: #888;'>({actual_roman_word})</div>
343
  </td>
344
+ <td style='padding: 12px; text-align: center;'>
345
+ <span style='color: #27ae60; font-weight: bold; font-size: 20px;'>✓</span>
346
+ <div style='font-size: 12px; color: #27ae60; margin-top: 2px;'>Correct</div>
347
  </td>
348
  </tr>
349
  """
350
 
351
  elif tag == 'replace':
352
+ # Incorrect words - clean white with colored text only
353
  max_words = max(i2-i1, j2-j1)
354
  for idx in range(max_words):
355
  word_index += 1
 
359
  actual_roman_word = actual_roman_words[j1 + idx] if (j1 + idx) < len(actual_roman_words) else ""
360
 
361
  feedback_html += f"""
362
+ <tr style='border-bottom: 1px solid #eee;'>
363
+ <td style='padding: 12px; text-align: center; font-weight: bold; color: #666; border-right: 1px solid #ddd;'>{word_index}</td>
364
+ <td style='padding: 12px; border-right: 1px solid #ddd;'>
365
+ <div style='font-family: monospace; font-size: 16px; margin-bottom: 4px;'>{expected_word}</div>
366
+ <div style='font-size: 13px; color: #888;'>({expected_roman})</div>
367
  </td>
368
+ <td style='padding: 12px; border-right: 1px solid #ddd;'>
369
+ <div style='font-family: monospace; font-size: 16px; margin-bottom: 4px; color: #e74c3c;'>{actual_word}</div>
370
+ <div style='font-size: 13px; color: #888;'>({actual_roman_word})</div>
371
  </td>
372
+ <td style='padding: 12px; text-align: center;'>
373
+ <span style='color: #e74c3c; font-weight: bold; font-size: 20px;'>✗</span>
374
+ <div style='font-size: 12px; color: #e74c3c; margin-top: 2px;'>Different</div>
375
  </td>
376
  </tr>
377
  """
 
382
  word_index += 1
383
  roman_word = intended_roman_words[i1 + idx] if (i1 + idx) < len(intended_roman_words) else ""
384
  feedback_html += f"""
385
+ <tr style='border-bottom: 1px solid #eee;'>
386
+ <td style='padding: 12px; text-align: center; font-weight: bold; color: #666; border-right: 1px solid #ddd;'>{word_index}</td>
387
+ <td style='padding: 12px; border-right: 1px solid #ddd;'>
388
+ <div style='font-family: monospace; font-size: 16px; margin-bottom: 4px;'>{word}</div>
389
+ <div style='font-size: 13px; color: #888;'>({roman_word})</div>
390
  </td>
391
+ <td style='padding: 12px; color: #f39c12; font-style: italic; border-right: 1px solid #ddd;'>
392
  <em>Not spoken</em>
393
  </td>
394
+ <td style='padding: 12px; text-align: center;'>
395
+ <span style='color: #f39c12; font-weight: bold; font-size: 20px;'>⚠</span>
396
+ <div style='font-size: 12px; color: #f39c12; margin-top: 2px;'>Missing</div>
397
  </td>
398
  </tr>
399
  """
 
403
  for idx, word in enumerate(actual_words[j1:j2]):
404
  actual_roman_word = actual_roman_words[j1 + idx] if (j1 + idx) < len(actual_roman_words) else ""
405
  feedback_html += f"""
406
+ <tr style='border-bottom: 1px solid #eee;'>
407
+ <td style='padding: 12px; text-align: center; font-weight: bold; color: #666; border-right: 1px solid #ddd;'>+</td>
408
+ <td style='padding: 12px; color: #9b59b6; font-style: italic; border-right: 1px solid #ddd;'>
409
  <em>Not expected</em>
410
  </td>
411
+ <td style='padding: 12px; border-right: 1px solid #ddd;'>
412
+ <div style='font-family: monospace; font-size: 16px; margin-bottom: 4px; color: #9b59b6;'>{word}</div>
413
+ <div style='font-size: 13px; color: #888;'>({actual_roman_word})</div>
414
  </td>
415
+ <td style='padding: 12px; text-align: center;'>
416
+ <span style='color: #9b59b6; font-weight: bold; font-size: 20px;'>+</span>
417
+ <div style='font-size: 12px; color: #9b59b6; margin-top: 2px;'>Extra</div>
418
  </td>
419
  </tr>
420
  """
 
428
  # Calculate accuracy
429
  accuracy = (correct_words / total_words * 100) if total_words > 0 else 0
430
 
431
+ # Clean summary section
432
  feedback_html += f"""
433
+ <div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 25px; border-radius: 12px; text-align: center; margin-top: 20px;'>
434
+ <h4 style='margin: 0 0 20px 0; font-size: 24px;'>🎯 Your Score</h4>
435
+ <div style='display: flex; justify-content: space-around; flex-wrap: wrap; gap: 20px;'>
436
+ <div style='background: rgba(255,255,255,0.15); padding: 20px; border-radius: 12px; min-width: 160px;'>
437
+ <div style='font-size: 40px; font-weight: bold; margin-bottom: 8px;'>{accuracy:.0f}%</div>
438
+ <div style='font-size: 16px; opacity: 0.9;'>Accuracy</div>
439
  </div>
440
+ <div style='background: rgba(255,255,255,0.15); padding: 20px; border-radius: 12px; min-width: 160px;'>
441
+ <div style='font-size: 40px; font-weight: bold; margin-bottom: 8px;'>{correct_words}/{total_words}</div>
442
+ <div style='font-size: 16px; opacity: 0.9;'>Words Correct</div>
443
  </div>
444
  </div>
445
+ <div style='margin-top: 20px; font-size: 18px;'>
446
  """
447
 
448
+ # Simple motivational message
449
  if accuracy >= 95:
450
+ feedback_html += "<span>🎉 Perfect! Outstanding pronunciation!</span>"
451
  elif accuracy >= 85:
452
+ feedback_html += "<span>🌟 Excellent! Very clear speaking!</span>"
453
  elif accuracy >= 70:
454
+ feedback_html += "<span>👍 Good job! Keep practicing!</span>"
455
  elif accuracy >= 50:
456
+ feedback_html += "<span>📚 Getting better! Focus on the red words!</span>"
457
  else:
458
  feedback_html += "<span>💪 Keep going! Practice makes perfect!</span>"
459
 
 
462
  </div>
463
  """
464
 
465
+ # Optional technical section (collapsed)
466
  if lang_choice in ["Tamil", "Malayalam"]:
467
  feedback_html += f"""
468
+ <details style='margin-top: 20px; padding: 15px; border: 1px solid #ddd; border-radius: 8px;'>
469
+ <summary style='cursor: pointer; font-weight: bold; color: #2c3e50; padding: 5px;'>🔧 Technical Details (for experts)</summary>
470
+ <div style='margin-top: 15px; display: grid; grid-template-columns: 1fr 1fr; gap: 15px;'>
471
  <div>
472
+ <strong>Expected (Harvard-Kyoto):</strong><br>
473
+ <span style='font-family: monospace; background: #f5f5f5; padding: 8px; border-radius: 4px; display: block; margin-top: 5px;'>{intended_hk}</span>
474
  </div>
475
  <div>
476
+ <strong>You said (Harvard-Kyoto):</strong><br>
477
+ <span style='font-family: monospace; background: #f5f5f5; padding: 8px; border-radius: 4px; display: block; margin-top: 5px;'>{actual_hk}</span>
478
  </div>
479
  </div>
480
+ </details>
481
  """
482
 
483
  feedback_html += "</div>"
 
504
  cer_val = jiwer.cer(intended_sentence, actual_text)
505
 
506
  # Get transliterations for both texts
507
+ intended_roman = transliterate_to_simple_roman(intended_sentence, lang_choice)
508
+ actual_roman = transliterate_to_simple_roman(actual_text, lang_choice)
509
 
510
  # Create comprehensive tabular feedback
511
  feedback_html, accuracy = create_tabular_feedback(intended_sentence, actual_text, lang_choice)
 
569
  with gr.Row():
570
  with gr.Column():
571
  pass1_out = gr.Textbox(label="🗣️ What You Said", interactive=False)
572
+ actual_roman_out = gr.Textbox(label="🔤 Your Pronunciation (Simple Sounds)", interactive=False)
573
  with gr.Column():
574
  wer_out = gr.Textbox(label="📊 Word Error Rate", interactive=False)
575
  cer_out = gr.Textbox(label="📈 Character Error Rate", interactive=False)