import os import tempfile import shutil from pathlib import Path from fastapi import FastAPI, File, UploadFile from fastapi.responses import HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware from faster_whisper import WhisperModel app = FastAPI() # CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # Static files app.mount("/static", StaticFiles(directory="static"), name="static") print("Loading faster-whisper-tiny...") model = WhisperModel( "tiny", device="cpu", compute_type="int8" ) print("Model ready") @app.get("/", response_class=HTMLResponse) async def root(): with open("index.html", "r", encoding="utf-8") as f: return f.read() @app.post("/transcribe") async def transcribe_audio(file: UploadFile = File(...)): tmp_path = None try: # Save uploaded file suffix = Path(file.filename).suffix with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp: shutil.copyfileobj(file.file, tmp) tmp_path = tmp.name # Transcribe with faster-whisper segments, info = model.transcribe(tmp_path, language="ru", beam_size=5) # Collect all text text = " ".join([segment.text for segment in segments]) return JSONResponse({"text": text.strip(), "status": "ok"}) except Exception as e: print(f"Error: {str(e)}") return JSONResponse( {"text": f"Error: {str(e)}", "status": "error"}, status_code=500 ) finally: # Clean up if tmp_path and Path(tmp_path).exists(): Path(tmp_path).unlink() await file.close()