Transcript / app.py
maylinejix's picture
Update app.py
103f09f verified
import whisper
import tempfile
import os
import httpx
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
app = FastAPI(title="Whisper Transcription API")
print("Loading Whisper model...")
model = whisper.load_model("base")
print("Model loaded.")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/", response_class=HTMLResponse)
async def root():
return """
<!DOCTYPE html>
<html>
<head>
<title>Whisper Transcription API</title>
<style>
body { font-family: monospace; background: #0d0d0d; color: #e0e0e0; padding: 40px; }
h1 { color: #7fff7f; }
a { color: #7fbfff; }
code { background: #1a1a1a; padding: 2px 6px; border-radius: 4px; }
</style>
</head>
<body>
<h1>πŸŽ™οΈ Whisper Transcription API</h1>
<p>Status: <strong style="color:#7fff7f">Running</strong></p>
<p>Endpoints:</p>
<ul>
<li><code>POST /transcribe</code> β€” Upload audio file</li>
<li><code>POST /transcribe-url</code> β€” Transcribe from URL</li>
<li><code>GET /health</code> β€” Health check</li>
<li><a href="/docs">πŸ“– Swagger Docs</a></li>
</ul>
</body>
</html>
"""
@app.post("/transcribe")
async def transcribe(
file: UploadFile = File(...),
language: str = Form(default="auto")
):
suffix = os.path.splitext(file.filename)[-1] if file.filename else ".wav"
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
content = await file.read()
tmp.write(content)
tmp_path = tmp.name
try:
lang = language if language != "auto" else None
result = model.transcribe(tmp_path, language=lang)
return JSONResponse({
"text": result["text"].strip(),
"language": result.get("language", "unknown"),
"segments": [
{
"start": round(s["start"], 2),
"end": round(s["end"], 2),
"text": s["text"].strip()
}
for s in result.get("segments", [])
]
})
except Exception as e:
return JSONResponse({"error": str(e)}, status_code=500)
finally:
os.unlink(tmp_path)
@app.post("/transcribe-url")
async def transcribe_url(
url: str = Form(...),
language: str = Form(default="auto")
):
try:
async with httpx.AsyncClient(timeout=60, follow_redirects=True) as client:
r = await client.get(url, headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.9",
"Referer": "https://www.google.com/"
})
r.raise_for_status()
except Exception as e:
return JSONResponse({"error": f"Failed to download: {str(e)}"}, status_code=400)
ext = os.path.splitext(url.split("?")[0])[-1] or ".mp3"
with tempfile.NamedTemporaryFile(suffix=ext, delete=False) as tmp:
tmp.write(r.content)
tmp_path = tmp.name
try:
lang = language if language != "auto" else None
result = model.transcribe(tmp_path, language=lang)
return JSONResponse({
"text": result["text"].strip(),
"language": result.get("language", "unknown"),
"segments": [
{
"start": round(s["start"], 2),
"end": round(s["end"], 2),
"text": s["text"].strip()
}
for s in result.get("segments", [])
]
})
except Exception as e:
return JSONResponse({"error": str(e)}, status_code=500)
finally:
os.unlink(tmp_path)
@app.get("/health")
async def health():
return {"status": "ok", "model": "whisper-base"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)