Spaces:
Running
Running
File size: 4,228 Bytes
451b460 dc559ef 451b460 1ad5db5 451b460 1ad5db5 451b460 1ad5db5 dc559ef 1ad5db5 451b460 1ad5db5 451b460 1ad5db5 451b460 1ad5db5 451b460 dc559ef e7cf803 103f09f e7cf803 451b460 1ad5db5 103f09f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 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)
|