1+ import os
2+ import tempfile
3+ import json
4+ import threading
5+ import glob
6+ from queue import Queue
7+ from threading import Lock
8+ from fastapi import FastAPI , UploadFile , File , Form
9+ from fastapi .responses import StreamingResponse , JSONResponse
10+ from whisper_code import transcribe_and_summarize , load_whisper_model_faster
11+
12+ app = FastAPI ()
13+
14+ # Global model cache and lock
15+ model_cache = {}
16+ model_lock = Lock ()
17+
18+ @app .post ("/transcribe" )
19+ async def transcribe_audio_api (
20+ audio_file : UploadFile = File (...),
21+ model : str = Form ("base" ),
22+ summarized_model : str = Form ("mistralai/Mistral-7B-Instruct-v0.1" ),
23+ denoise : bool = Form (False ),
24+ prop_decrease : float = Form (0.7 ),
25+ summary : bool = Form (True ),
26+ speaker : bool = Form (False ),
27+ hf_token : str = Form (None ),
28+ max_speakers : int = Form (None ),
29+ streaming : bool = Form (False )
30+ ):
31+ temp_audio_path = tempfile .mktemp (suffix = f"_{ audio_file .filename } " )
32+ with open (temp_audio_path , "wb" ) as f :
33+ f .write (await audio_file .read ())
34+
35+ output_dir = tempfile .mkdtemp ()
36+
37+ # Ensure model is loaded once
38+ if model not in model_cache :
39+ model_cache [model ] = load_whisper_model_faster (model )
40+
41+ whisper_model = model_cache [model ]
42+
43+ if streaming :
44+ def generator ():
45+ q = Queue ()
46+
47+ def api_callback (result ):
48+ q .put (json .dumps (result ) + "\n " )
49+
50+ def run_pipeline ():
51+ try :
52+ with model_lock :
53+ transcribe_and_summarize (
54+ path = temp_audio_path ,
55+ model_name = model ,
56+ output_dir = output_dir ,
57+ summarized_model_id = summarized_model ,
58+ denoise = denoise ,
59+ prop_decrease = prop_decrease ,
60+ summary = summary ,
61+ speaker = speaker ,
62+ hf_token = hf_token ,
63+ max_speakers = max_speakers ,
64+ streaming = True ,
65+ api_callback = api_callback ,
66+ model_instance = whisper_model
67+ )
68+ except Exception as e :
69+ import traceback
70+ traceback .print_exc ()
71+ q .put (json .dumps ({"error" : f"Streaming transcription failed: { str (e )} " }))
72+ finally :
73+ q .put (None )
74+
75+ threading .Thread (target = run_pipeline ).start ()
76+
77+ while True :
78+ chunk = q .get ()
79+ if chunk is None :
80+ break
81+ yield chunk
82+
83+ return StreamingResponse (generator (), media_type = "application/json" )
84+
85+ else :
86+ try :
87+ with model_lock :
88+ transcribe_and_summarize (
89+ path = temp_audio_path ,
90+ model_name = model ,
91+ output_dir = output_dir ,
92+ summarized_model_id = summarized_model ,
93+ denoise = denoise ,
94+ prop_decrease = prop_decrease ,
95+ summary = summary ,
96+ speaker = speaker ,
97+ hf_token = hf_token ,
98+ max_speakers = max_speakers ,
99+ streaming = False ,
100+ api_callback = None ,
101+ model_instance = whisper_model
102+ )
103+ except Exception as e :
104+ import traceback
105+ traceback .print_exc ()
106+ return JSONResponse (
107+ content = {"error" : f"Transcription failed: { str (e )} " },
108+ status_code = 500
109+ )
110+
111+ try :
112+ json_files = sorted (
113+ glob .glob (os .path .join (output_dir , "*.json" )),
114+ key = os .path .getmtime ,
115+ reverse = True
116+ )
117+ if not json_files :
118+ raise FileNotFoundError ("No output JSON file found." )
119+
120+ with open (json_files [0 ]) as f :
121+ return JSONResponse (content = json .load (f ))
122+
123+ except Exception as e :
124+ import traceback
125+ traceback .print_exc ()
126+ return JSONResponse (
127+ content = {"error" : f"Failed to read output JSON: { str (e )} " },
128+ status_code = 500
129+ )
0 commit comments