| import base64 |
| import io |
| import torch |
| from fastapi import FastAPI, HTTPException, Request |
| from transformers import pipeline |
|
|
| app = FastAPI() |
|
|
| |
| print("正在載入 Whisper 模型...") |
| asr = pipeline( |
| "automatic-speech-recognition", |
| model="openai/whisper-large-v3-turbo", |
| torch_dtype=torch.float16, |
| device="cuda:0", |
| ) |
| print("模型載入完成!") |
|
|
|
|
| @app.post("/v1/audio/transcriptions") |
| async def transcribe_audio(request: Request): |
| try: |
| content_type = request.headers.get("content-type", "") |
| if "multipart/form-data" in content_type: |
| |
| form = await request.form() |
| if "file" not in form: |
| raise HTTPException(status_code=400, detail="表單資料中缺少 'file' 欄位") |
| file_item = form["file"] |
| audio_bytes = await file_item.read() |
| else: |
| |
| data = await request.json() |
| try: |
| messages = data["messages"] |
| audio_content = messages[0]["content"][0] |
| base64_data = audio_content["audio_url"]["url"].split(",")[1] |
| audio_bytes = base64.b64decode(base64_data) |
| except Exception as e: |
| raise HTTPException(status_code=400, detail=f"解析自訂 JSON 失敗: {str(e)}") |
|
|
| |
| result = asr( |
| audio_bytes, |
| chunk_length_s=30, |
| batch_size=8, |
| return_timestamps=True, |
| generate_kwargs={"language": "english", "task": "transcribe"}, |
| ) |
|
|
| return {"text": result["text"]} |
|
|
| except HTTPException as he: |
| raise he |
| except Exception as e: |
| raise HTTPException(status_code=500, detail=str(e)) |
|
|
|
|
| if __name__ == "__main__": |
| import uvicorn |
|
|
| |
| uvicorn.run(app, host="0.0.0.0", port=4002) |
|
|