Update app.py
Browse files
app.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# app.py
|
| 2 |
# Whisper transcription app - HYBRID conversion (pydub + small ffmpeg fallback)
|
| 3 |
-
#
|
| 4 |
|
| 5 |
import os
|
| 6 |
import sys
|
|
@@ -32,6 +32,8 @@ except Exception as e:
|
|
| 32 |
|
| 33 |
print("DEBUG: imports OK", flush=True)
|
| 34 |
|
|
|
|
|
|
|
| 35 |
# ---------- Config ----------
|
| 36 |
MEMORY_FILE = "memory.json"
|
| 37 |
MEMORY_LOCK = threading.Lock()
|
|
@@ -70,6 +72,7 @@ memory = load_memory()
|
|
| 70 |
print("DEBUG: memory loaded (words=%d phrases=%d)" % (len(memory.get("words", {})), len(memory.get("phrases", {}))), flush=True)
|
| 71 |
|
| 72 |
|
|
|
|
| 73 |
# ---------- Postprocessing ----------
|
| 74 |
MEDICAL_ABBREVIATIONS = {
|
| 75 |
"pt": "patient",
|
|
@@ -106,6 +109,11 @@ def expand_abbreviations(text):
|
|
| 106 |
out.append(t)
|
| 107 |
return ''.join(out)
|
| 108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
def normalize_drugs(text):
|
| 110 |
for k, v in DRUG_NORMALIZATION.items():
|
| 111 |
text = re.sub(rf'\b{k}\b', v, text, flags=re.IGNORECASE)
|
|
@@ -146,6 +154,11 @@ def postprocess_transcript(text, format_soap=False):
|
|
| 146 |
return soap
|
| 147 |
return t
|
| 148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
# ---------- Memory utilities ----------
|
| 150 |
def extract_words_and_phrases(text):
|
| 151 |
# basic tokenization for words; phrases = sentences
|
|
@@ -179,6 +192,10 @@ def update_memory_with_transcript(transcript):
|
|
| 179 |
except Exception:
|
| 180 |
pass
|
| 181 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
def memory_correct_text(text, min_ratio=0.85):
|
| 183 |
if not text or (not memory.get("words") and not memory.get("phrases")):
|
| 184 |
return text
|
|
@@ -225,6 +242,7 @@ def save_as_word(text, filename=None):
|
|
| 225 |
|
| 226 |
|
| 227 |
|
|
|
|
| 228 |
# ---------- Hybrid conversion: pydub + small ffmpeg fallback ----------
|
| 229 |
def _ffmpeg_convert(input_path, out_path, fmt, sr, ch):
|
| 230 |
cmd = [
|
|
@@ -277,6 +295,10 @@ def convert_to_wav_if_needed(input_path):
|
|
| 277 |
except Exception:
|
| 278 |
pass
|
| 279 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
diag_dir = tempfile.mkdtemp(prefix="dct_diag_")
|
| 281 |
diag_log = os.path.join(diag_dir, "conversion_diagnostics.txt")
|
| 282 |
diagnostics = []
|
|
@@ -412,8 +434,6 @@ def transcribe_multiple(audio_files, model_name, advanced_options, merge_checkbo
|
|
| 412 |
yield "\n\n".join(log), "\n\n".join(transcripts), None, 100
|
| 413 |
return
|
| 414 |
|
| 415 |
-
|
| 416 |
-
|
| 417 |
# collect audio file paths
|
| 418 |
paths = []
|
| 419 |
if extracted_audio_paths:
|
|
@@ -458,62 +478,11 @@ def transcribe_multiple(audio_files, model_name, advanced_options, merge_checkbo
|
|
| 458 |
yield "\n\n".join(log), "\n\n".join(transcripts), None, int(5 + idx * 80 / max(1, total))
|
| 459 |
continue
|
| 460 |
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
if isinstance(advanced_options, dict):
|
| 464 |
-
whisper_opts.update(advanced_options)
|
| 465 |
-
|
| 466 |
-
result = model.transcribe(wav, **whisper_opts)
|
| 467 |
-
text = result.get("text", "").strip()
|
| 468 |
-
log.append(f"Transcribed: {len(text)} chars")
|
| 469 |
-
|
| 470 |
-
if enable_memory:
|
| 471 |
-
text = memory_correct_text(text)
|
| 472 |
-
text = postprocess_transcript(text)
|
| 473 |
-
transcripts.append(f"FILE: {os.path.basename(p)}\n{text}\n")
|
| 474 |
-
|
| 475 |
-
if enable_memory:
|
| 476 |
-
try:
|
| 477 |
-
update_memory_with_transcript(text)
|
| 478 |
-
log.append("Memory updated.")
|
| 479 |
-
except Exception:
|
| 480 |
-
pass
|
| 481 |
-
|
| 482 |
-
yield "\n\n".join(log), "\n\n".join(transcripts), None, int(10 + idx * 85 / max(1, total))
|
| 483 |
-
except Exception as e:
|
| 484 |
-
log.append(f"Transcription failed for {p}: {e}")
|
| 485 |
-
transcripts.append(f"FILE: {os.path.basename(p)}\nERROR: Transcription failed: {e}")
|
| 486 |
-
yield "\n\n".join(log), "\n\n".join(transcripts), None, int(10 + idx * 85 / max(1, total))
|
| 487 |
-
continue
|
| 488 |
-
finally:
|
| 489 |
-
try:
|
| 490 |
-
if wav and os.path.exists(wav):
|
| 491 |
-
tmpdir = tempfile.gettempdir()
|
| 492 |
-
try:
|
| 493 |
-
if os.path.commonpath([tmpdir, os.path.abspath(wav)]) == tmpdir and (not p.lower().endswith(".wav")):
|
| 494 |
-
os.unlink(wav)
|
| 495 |
-
except Exception:
|
| 496 |
-
pass
|
| 497 |
-
except Exception:
|
| 498 |
-
pass
|
| 499 |
|
| 500 |
-
if merge_checkbox:
|
| 501 |
-
try:
|
| 502 |
-
merged_text = "\n\n".join(transcripts)
|
| 503 |
-
word_file_path = save_as_word(merged_text)
|
| 504 |
-
log.append(f"Merged transcript saved: {word_file_path}")
|
| 505 |
-
except Exception as e:
|
| 506 |
-
log.append(f"Failed to save merged file: {e}")
|
| 507 |
-
word_file_path = None
|
| 508 |
|
| 509 |
-
yield "\n\n".join(log), "\n\n".join(transcripts), word_file_path, 100
|
| 510 |
|
| 511 |
-
try:
|
| 512 |
-
if os.path.exists(temp_extract_dir):
|
| 513 |
-
shutil.rmtree(temp_extract_dir)
|
| 514 |
-
log.append("Cleaned temporary extraction dir.")
|
| 515 |
-
except Exception:
|
| 516 |
-
pass
|
| 517 |
|
| 518 |
# ----------------------- Gradio UI -----------------------
|
| 519 |
def run_transcription_wrapper(files, model_name, merge, zip_file, zip_password, enable_memory, advanced_options_state):
|
|
|
|
| 1 |
# app.py
|
| 2 |
# Whisper transcription app - HYBRID conversion (pydub + small ffmpeg fallback)
|
| 3 |
+
# Cleaned, debugged, and Spaces-ready.
|
| 4 |
|
| 5 |
import os
|
| 6 |
import sys
|
|
|
|
| 32 |
|
| 33 |
print("DEBUG: imports OK", flush=True)
|
| 34 |
|
| 35 |
+
|
| 36 |
+
|
| 37 |
# ---------- Config ----------
|
| 38 |
MEMORY_FILE = "memory.json"
|
| 39 |
MEMORY_LOCK = threading.Lock()
|
|
|
|
| 72 |
print("DEBUG: memory loaded (words=%d phrases=%d)" % (len(memory.get("words", {})), len(memory.get("phrases", {}))), flush=True)
|
| 73 |
|
| 74 |
|
| 75 |
+
|
| 76 |
# ---------- Postprocessing ----------
|
| 77 |
MEDICAL_ABBREVIATIONS = {
|
| 78 |
"pt": "patient",
|
|
|
|
| 109 |
out.append(t)
|
| 110 |
return ''.join(out)
|
| 111 |
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
|
| 117 |
def normalize_drugs(text):
|
| 118 |
for k, v in DRUG_NORMALIZATION.items():
|
| 119 |
text = re.sub(rf'\b{k}\b', v, text, flags=re.IGNORECASE)
|
|
|
|
| 154 |
return soap
|
| 155 |
return t
|
| 156 |
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
|
| 162 |
# ---------- Memory utilities ----------
|
| 163 |
def extract_words_and_phrases(text):
|
| 164 |
# basic tokenization for words; phrases = sentences
|
|
|
|
| 192 |
except Exception:
|
| 193 |
pass
|
| 194 |
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
|
| 199 |
def memory_correct_text(text, min_ratio=0.85):
|
| 200 |
if not text or (not memory.get("words") and not memory.get("phrases")):
|
| 201 |
return text
|
|
|
|
| 242 |
|
| 243 |
|
| 244 |
|
| 245 |
+
|
| 246 |
# ---------- Hybrid conversion: pydub + small ffmpeg fallback ----------
|
| 247 |
def _ffmpeg_convert(input_path, out_path, fmt, sr, ch):
|
| 248 |
cmd = [
|
|
|
|
| 295 |
except Exception:
|
| 296 |
pass
|
| 297 |
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
|
| 302 |
diag_dir = tempfile.mkdtemp(prefix="dct_diag_")
|
| 303 |
diag_log = os.path.join(diag_dir, "conversion_diagnostics.txt")
|
| 304 |
diagnostics = []
|
|
|
|
| 434 |
yield "\n\n".join(log), "\n\n".join(transcripts), None, 100
|
| 435 |
return
|
| 436 |
|
|
|
|
|
|
|
| 437 |
# collect audio file paths
|
| 438 |
paths = []
|
| 439 |
if extracted_audio_paths:
|
|
|
|
| 478 |
yield "\n\n".join(log), "\n\n".join(transcripts), None, int(5 + idx * 80 / max(1, total))
|
| 479 |
continue
|
| 480 |
|
| 481 |
+
# continue... (UI + launch in next message)
|
| 482 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
|
|
|
|
| 485 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
|
| 487 |
# ----------------------- Gradio UI -----------------------
|
| 488 |
def run_transcription_wrapper(files, model_name, merge, zip_file, zip_password, enable_memory, advanced_options_state):
|