audio.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. """语音转写端点"""
  2. import os
  3. import uuid
  4. import logging
  5. from fastapi import APIRouter, UploadFile, File, HTTPException
  6. from pydantic import BaseModel
  7. from typing import Optional
  8. from app.audio.transcriber import transcribe_audio
  9. logger = logging.getLogger(__name__)
  10. router = APIRouter(prefix="/api/v1", tags=["audio"])
  11. MAX_FILE_SIZE = 5 * 1024 * 1024
  12. UPLOAD_DIR = "/tmp/stt_uploads"
  13. class TranscribeResponse(BaseModel):
  14. code: int = 200
  15. message: str = "ok"
  16. data: Optional[dict] = None
  17. @router.post("/audio/transcribe", response_model=TranscribeResponse)
  18. async def transcribe(file: UploadFile = File(...)):
  19. if not file.filename or not file.filename.lower().endswith((".mp3", ".wav", ".m4a", ".flac", ".ogg")):
  20. raise HTTPException(status_code=400, detail="不支持的音频格式,仅支持 mp3/wav/m4a/flac/ogg")
  21. content = await file.read()
  22. if len(content) > MAX_FILE_SIZE:
  23. raise HTTPException(status_code=413, detail="音频文件过大(最大 5MB)")
  24. if len(content) < 1000:
  25. raise HTTPException(status_code=400, detail="音频文件为空或过短")
  26. os.makedirs(UPLOAD_DIR, exist_ok=True)
  27. ext = file.filename.rsplit(".", 1)[-1]
  28. tmp_path = os.path.join(UPLOAD_DIR, f"{uuid.uuid4().hex}.{ext}")
  29. try:
  30. with open(tmp_path, "wb") as f:
  31. f.write(content)
  32. result = transcribe_audio(tmp_path)
  33. return TranscribeResponse(data=result)
  34. except Exception as e:
  35. logger.error("转写失败: %s", e, exc_info=True)
  36. return TranscribeResponse(code=500, message="转写失败: " + str(e), data={})
  37. finally:
  38. try:
  39. os.remove(tmp_path)
  40. except OSError:
  41. pass