Vadym Myroshnyk commited on
Commit
edf0091
·
1 Parent(s): 2e3d053
Files changed (3) hide show
  1. app.py +37 -23
  2. audio_files.py +2 -3
  3. check.py +7 -9
app.py CHANGED
@@ -1,10 +1,11 @@
1
  import os
2
  import gradio as gr
 
3
 
4
  from audio_files import get_audio_structure
5
- from check import check_transcription, load_dialogue_lines
6
 
7
- # === Audio structure
8
  audio_structure = get_audio_structure()
9
  week_options = list(audio_structure.keys())
10
  default_week = week_options[0]
@@ -13,55 +14,68 @@ default_file = audio_structure[default_week][0] if audio_structure[default_week]
13
  with gr.Blocks(theme="soft") as demo:
14
  gr.Markdown("## 🎧 Modals & Conditionals Bootcamp")
15
 
16
- # States
17
  current_index = gr.State(0)
18
  dialogue_state = gr.State([])
19
 
20
- # Week + audio
21
  with gr.Row():
22
  week_dropdown = gr.Dropdown(label="Select a week", choices=week_options, value=default_week, scale=1)
23
  audio_player = gr.Audio(label="Audio preview", type="filepath", value=default_file, scale=3)
24
 
25
  gr.Markdown("### ✍️ Your Transcription")
26
 
27
- # === Dynamic dialogue render ===
28
  @gr.render(inputs=[week_dropdown, current_index, dialogue_state])
29
  def render_transcription_inputs(week, index, inputs):
30
  audio_path = audio_structure[week][0]
31
  transcript_path = audio_path.replace(".mp3", ".txt").replace("audio", "transcripts")
32
  lines = load_dialogue_lines(transcript_path) if os.path.exists(transcript_path) else []
33
 
34
- # Add next speaker
35
  if index < len(lines):
36
  next_speaker, _ = lines[index]
37
  inputs = [(next_speaker, "")] + inputs
38
  index += 1
39
 
40
- # === UI Layout ===
41
  button_label = "➕ Add next speaker" if index < len(lines) else "✅ Check"
42
  action_btn = gr.Button(button_label)
43
- textboxes = [gr.Textbox(label=speaker, value=value, lines=1, key=f"{week}-{i}") for i, (speaker, value) in enumerate(inputs)]
44
 
45
- with gr.Accordion("📖 Show Original Text", open=False):
46
- original_output = gr.HTML()
 
47
 
48
- diff_output = gr.HTML(label="Comparison (highlighted)")
49
- feedback_output = gr.HTML(label="Feedback and score")
 
 
 
 
 
 
50
 
51
- # === Logic ===
52
- def on_action_click(*user_inputs):
53
- if index < len(lines):
54
- return index, inputs
55
- else:
56
- user_text = "\n".join(user_inputs)
57
- return check_transcription(audio_path, user_text)
 
 
 
 
 
 
 
 
 
 
58
 
59
- # === Event binding (depending on mode)
60
  if index < len(lines):
61
- action_btn.click(fn=lambda: (index, inputs), outputs=[current_index, dialogue_state])
62
  else:
63
- action_btn.click(fn=on_action_click, inputs=[tb for tb in textboxes],
64
- outputs=[audio_player, original_output, diff_output, feedback_output])
 
 
 
65
 
66
  demo.load(lambda: None)
67
 
 
1
  import os
2
  import gradio as gr
3
+ from rapidfuzz import fuzz
4
 
5
  from audio_files import get_audio_structure
6
+ from check import load_dialogue_lines, highlight_fuzzy_diff # додано highlight_fuzzy_diff
7
 
8
+ # === Audio structure ===
9
  audio_structure = get_audio_structure()
10
  week_options = list(audio_structure.keys())
11
  default_week = week_options[0]
 
14
  with gr.Blocks(theme="soft") as demo:
15
  gr.Markdown("## 🎧 Modals & Conditionals Bootcamp")
16
 
 
17
  current_index = gr.State(0)
18
  dialogue_state = gr.State([])
19
 
 
20
  with gr.Row():
21
  week_dropdown = gr.Dropdown(label="Select a week", choices=week_options, value=default_week, scale=1)
22
  audio_player = gr.Audio(label="Audio preview", type="filepath", value=default_file, scale=3)
23
 
24
  gr.Markdown("### ✍️ Your Transcription")
25
 
 
26
  @gr.render(inputs=[week_dropdown, current_index, dialogue_state])
27
  def render_transcription_inputs(week, index, inputs):
28
  audio_path = audio_structure[week][0]
29
  transcript_path = audio_path.replace(".mp3", ".txt").replace("audio", "transcripts")
30
  lines = load_dialogue_lines(transcript_path) if os.path.exists(transcript_path) else []
31
 
 
32
  if index < len(lines):
33
  next_speaker, _ = lines[index]
34
  inputs = [(next_speaker, "")] + inputs
35
  index += 1
36
 
 
37
  button_label = "➕ Add next speaker" if index < len(lines) else "✅ Check"
38
  action_btn = gr.Button(button_label)
 
39
 
40
+ textboxes = []
41
+ feedback_outputs = []
42
+ diff_outputs = []
43
 
44
+ for i, (speaker, value) in enumerate(inputs):
45
+ with gr.Column():
46
+ tb = gr.Textbox(label=speaker, value=value, lines=1, key=f"{week}-{i}")
47
+ diff = gr.HTML()
48
+ fb = gr.HTML()
49
+ textboxes.append(tb)
50
+ diff_outputs.append(diff)
51
+ feedback_outputs.append(fb)
52
 
53
+ def on_add():
54
+ return index, inputs
55
+
56
+ def per_line_check(*user_inputs):
57
+ feedback = []
58
+ highlights = []
59
+ for user_input, (_, expected) in zip(user_inputs, reversed(lines[:len(user_inputs)])):
60
+ score = fuzz.ratio(user_input.strip(), expected.strip())
61
+ if score > 90:
62
+ emoji, msg = "✅", f"<b>{score}%</b> Excellent!"
63
+ elif score > 70:
64
+ emoji, msg = "⚠️", f"<b>{score}%</b> Some mistakes"
65
+ else:
66
+ emoji, msg = "❌", f"<b>{score}%</b> Try again"
67
+ feedback.append(f"<div style='margin-top: 4px;'>{emoji} {msg}</div>")
68
+ highlights.append(highlight_fuzzy_diff(user_input, expected))
69
+ return highlights + feedback # concatenate results
70
 
 
71
  if index < len(lines):
72
+ action_btn.click(fn=on_add, outputs=[current_index, dialogue_state])
73
  else:
74
+ action_btn.click(
75
+ fn=per_line_check,
76
+ inputs=textboxes,
77
+ outputs=diff_outputs + feedback_outputs
78
+ )
79
 
80
  demo.load(lambda: None)
81
 
audio_files.py CHANGED
@@ -4,8 +4,7 @@ import os
4
  def get_audio_structure(audio_dir="audio"):
5
  structure = {}
6
  for file in sorted(os.listdir(audio_dir)):
7
- if file.lower().endswith(".mp3") and file.lower().startswith("week"):
8
- label = file.replace(".mp3", "").replace("_", " ").title() # e.g., "week1" -> "Week1"
9
  structure[label] = [os.path.join(audio_dir, file)]
10
  return structure
11
-
 
4
  def get_audio_structure(audio_dir="audio"):
5
  structure = {}
6
  for file in sorted(os.listdir(audio_dir)):
7
+ if file.endswith(".mp3"):
8
+ label = os.path.splitext(file)[0].replace("_", " ").title()
9
  structure[label] = [os.path.join(audio_dir, file)]
10
  return structure
 
check.py CHANGED
@@ -60,12 +60,10 @@ def check_transcription(audio_path, user_text):
60
 
61
 
62
  def load_dialogue_lines(path):
63
- with open(path, "r") as f:
64
- lines = f.readlines()
65
-
66
- dialogue = []
67
- for line in lines:
68
- if ":" in line:
69
- speaker, text = line.split(":", 1)
70
- dialogue.append((speaker.strip(), text.strip()))
71
- return dialogue
 
60
 
61
 
62
  def load_dialogue_lines(path):
63
+ with open(path, "r", encoding="utf-8") as f:
64
+ lines = []
65
+ for line in f:
66
+ if ":" in line:
67
+ speaker, text = line.strip().split(":", 1)
68
+ lines.append((speaker.strip(), text.strip()))
69
+ return lines