David-Chew-HL commited on
Commit
a47e964
·
verified ·
1 Parent(s): 93122f4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +9 -63
app.py CHANGED
@@ -1,6 +1,5 @@
1
  import json
2
  import os
3
- import re
4
  import shutil
5
  import subprocess
6
  import tempfile
@@ -17,7 +16,6 @@ LANGUAGE_MAP = {
17
  "Bilingual": None, # auto-detect
18
  }
19
 
20
- # Download the ONNX repo into the Space at startup.
21
  MODEL_DIR = snapshot_download(repo_id=REPO_ID)
22
 
23
 
@@ -54,43 +52,6 @@ def normalize_audio(input_path: str, progress: gr.Progress | None = None) -> str
54
  return str(out_path)
55
 
56
 
57
- def paragraphize_text(text: str, max_chars: int = 180, max_sentences: int = 3) -> str:
58
- """Lightweight paragraphing that preserves the original wording."""
59
- text = (text or "").strip()
60
- if not text:
61
- return ""
62
-
63
- # Split on end-of-sentence punctuation for English and Chinese.
64
- sentences = re.split(r"(?<=[\.\!\?\。\!?])\s+", text)
65
- sentences = [s.strip() for s in sentences if s.strip()]
66
-
67
- # Fallback: if no sentence punctuation exists, split by commas / Chinese commas
68
- if len(sentences) <= 1:
69
- chunks = re.split(r"(?<=[,,;;])\s*", text)
70
- chunks = [c.strip() for c in chunks if c.strip()]
71
- if len(chunks) > 1:
72
- sentences = chunks
73
-
74
- paragraphs = []
75
- current = []
76
- current_len = 0
77
-
78
- for s in sentences:
79
- proposed_len = current_len + (1 if current else 0) + len(s)
80
- if current and (proposed_len > max_chars or len(current) >= max_sentences):
81
- paragraphs.append(" ".join(current))
82
- current = [s]
83
- current_len = len(s)
84
- else:
85
- current.append(s)
86
- current_len = proposed_len
87
-
88
- if current:
89
- paragraphs.append(" ".join(current))
90
-
91
- return "\n\n".join(paragraphs)
92
-
93
-
94
  def run_onnx_asr(audio_path: str, mode: str, progress: gr.Progress | None = None) -> dict:
95
  if mode not in LANGUAGE_MAP:
96
  raise gr.Error("Invalid mode selected.")
@@ -122,7 +83,6 @@ def run_onnx_asr(audio_path: str, mode: str, progress: gr.Progress | None = None
122
  detail = stderr or stdout or "Unknown ASR error."
123
  raise gr.Error(detail[:1500]) from e
124
 
125
- # Be resilient: find the last JSON object in stdout.
126
  output = (proc.stdout or "").strip().splitlines()
127
  parsed = None
128
  for line in reversed(output):
@@ -136,7 +96,6 @@ def run_onnx_asr(audio_path: str, mode: str, progress: gr.Progress | None = None
136
  continue
137
 
138
  if not isinstance(parsed, dict):
139
- # Fallback: return raw text if the script prints plain text instead.
140
  return {
141
  "text": (proc.stdout or "").strip(),
142
  "language": None,
@@ -145,15 +104,15 @@ def run_onnx_asr(audio_path: str, mode: str, progress: gr.Progress | None = None
145
  return parsed
146
 
147
 
148
- def make_txt_file(text: str, original_audio_path: str, suffix: str) -> str:
149
  out_dir = Path(tempfile.mkdtemp())
150
  stem = Path(original_audio_path).stem or "transcript"
151
- out_path = out_dir / f"{stem}_{suffix}.txt"
152
  out_path.write_text(text, encoding="utf-8")
153
  return str(out_path)
154
 
155
 
156
- def transcribe(audio_file: str, mode: str, paragraphing: bool, progress=gr.Progress()):
157
  if not audio_file:
158
  raise gr.Error("Please upload an audio file.")
159
 
@@ -164,14 +123,8 @@ def transcribe(audio_file: str, mode: str, paragraphing: bool, progress=gr.Progr
164
  normalized_path = normalize_audio(audio_file, progress=progress)
165
  result = run_onnx_asr(normalized_path, mode=mode, progress=progress)
166
 
167
- raw_text = (result.get("text") or result.get("transcript") or "").strip()
168
- if not raw_text:
169
- raw_text = ""
170
-
171
- final_text = paragraphize_text(raw_text) if paragraphing else raw_text
172
-
173
- raw_txt = make_txt_file(raw_text, audio_file, "raw")
174
- final_txt = make_txt_file(final_text, audio_file, "paragraphs" if paragraphing else "transcript")
175
 
176
  detected_language = result.get("language") or result.get("detected_language")
177
  info = f"Mode: {mode}"
@@ -179,7 +132,7 @@ def transcribe(audio_file: str, mode: str, paragraphing: bool, progress=gr.Progr
179
  info += f"\nDetected language: {detected_language}"
180
 
181
  progress(1.0, desc="Done")
182
- return raw_text, final_text, final_txt, info
183
 
184
  finally:
185
  if normalized_path and os.path.exists(normalized_path):
@@ -208,23 +161,16 @@ with gr.Blocks(title="Qwen3 ASR ONNX CPU") as demo:
208
  info="Bilingual means auto-detect.",
209
  )
210
 
211
- paragraphing = gr.Checkbox(
212
- value=True,
213
- label="Auto paragraphing",
214
- info="Preserves wording and only inserts paragraph breaks.",
215
- )
216
-
217
  transcribe_btn = gr.Button("Transcribe")
218
 
219
- raw_transcript = gr.Textbox(label="Raw transcript", lines=10)
220
- formatted_transcript = gr.Textbox(label="Formatted transcript", lines=14)
221
  download_file = gr.File(label="Download transcript")
222
  metadata = gr.Textbox(label="Info", lines=2, interactive=False)
223
 
224
  transcribe_btn.click(
225
  fn=transcribe,
226
- inputs=[audio, mode, paragraphing],
227
- outputs=[raw_transcript, formatted_transcript, download_file, metadata],
228
  )
229
 
230
  if __name__ == "__main__":
 
1
  import json
2
  import os
 
3
  import shutil
4
  import subprocess
5
  import tempfile
 
16
  "Bilingual": None, # auto-detect
17
  }
18
 
 
19
  MODEL_DIR = snapshot_download(repo_id=REPO_ID)
20
 
21
 
 
52
  return str(out_path)
53
 
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  def run_onnx_asr(audio_path: str, mode: str, progress: gr.Progress | None = None) -> dict:
56
  if mode not in LANGUAGE_MAP:
57
  raise gr.Error("Invalid mode selected.")
 
83
  detail = stderr or stdout or "Unknown ASR error."
84
  raise gr.Error(detail[:1500]) from e
85
 
 
86
  output = (proc.stdout or "").strip().splitlines()
87
  parsed = None
88
  for line in reversed(output):
 
96
  continue
97
 
98
  if not isinstance(parsed, dict):
 
99
  return {
100
  "text": (proc.stdout or "").strip(),
101
  "language": None,
 
104
  return parsed
105
 
106
 
107
+ def make_txt_file(text: str, original_audio_path: str) -> str:
108
  out_dir = Path(tempfile.mkdtemp())
109
  stem = Path(original_audio_path).stem or "transcript"
110
+ out_path = out_dir / f"{stem}.txt"
111
  out_path.write_text(text, encoding="utf-8")
112
  return str(out_path)
113
 
114
 
115
+ def transcribe(audio_file: str, mode: str, progress=gr.Progress()):
116
  if not audio_file:
117
  raise gr.Error("Please upload an audio file.")
118
 
 
123
  normalized_path = normalize_audio(audio_file, progress=progress)
124
  result = run_onnx_asr(normalized_path, mode=mode, progress=progress)
125
 
126
+ text = (result.get("text") or result.get("transcript") or "").strip()
127
+ txt_file = make_txt_file(text, audio_file)
 
 
 
 
 
 
128
 
129
  detected_language = result.get("language") or result.get("detected_language")
130
  info = f"Mode: {mode}"
 
132
  info += f"\nDetected language: {detected_language}"
133
 
134
  progress(1.0, desc="Done")
135
+ return text, txt_file, info
136
 
137
  finally:
138
  if normalized_path and os.path.exists(normalized_path):
 
161
  info="Bilingual means auto-detect.",
162
  )
163
 
 
 
 
 
 
 
164
  transcribe_btn = gr.Button("Transcribe")
165
 
166
+ transcript = gr.Textbox(label="Transcript", lines=14)
 
167
  download_file = gr.File(label="Download transcript")
168
  metadata = gr.Textbox(label="Info", lines=2, interactive=False)
169
 
170
  transcribe_btn.click(
171
  fn=transcribe,
172
+ inputs=[audio, mode],
173
+ outputs=[transcript, download_file, metadata],
174
  )
175
 
176
  if __name__ == "__main__":