voice-notes / app /api /voice.py
osina's picture
Build Voice Notes demo Space
64c1bdf verified
Raw History Blame Contribute Delete
1.94 kB
from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, File, UploadFile, WebSocket
from app.api.deps import (
IntentExtractorDep,
SessionDep,
SettingsDep,
TranscriberDep,
)
from app.domain import Source
from app.errors import AudioProcessingError, InvalidRequestError, PayloadTooLargeError
from app.schemas.notes import NoteProcessResponse
from app.services.audio import transcribe_audio_bytes
from app.services.pipeline import NotePipeline
from app.services.streaming import VoiceStreamSession
router = APIRouter(prefix="/api/voice", tags=["voice"])
AudioFile = Annotated[UploadFile, File()]
@router.post("/transcribe", response_model=NoteProcessResponse, status_code=201)
def transcribe(
file: AudioFile,
settings: SettingsDep,
transcriber: TranscriberDep,
extractor: IntentExtractorDep,
session: SessionDep,
) -> NoteProcessResponse:
max_bytes = settings.max_audio_mb * 1024 * 1024
data = file.file.read(max_bytes + 1)
if not data:
raise InvalidRequestError("Uploaded audio file is empty")
if len(data) > max_bytes:
raise PayloadTooLargeError(f"Audio file exceeds the {settings.max_audio_mb} MB limit")
text = transcribe_audio_bytes(
data,
filename=file.filename or "audio",
settings=settings,
transcriber=transcriber,
)
if not text.strip():
raise AudioProcessingError("No speech was detected in the uploaded audio")
pipeline = NotePipeline(session, extractor)
return pipeline.process(text, Source.VOICE)
@router.websocket("/stream")
async def stream_voice(websocket: WebSocket) -> None:
app = websocket.app
await VoiceStreamSession(
websocket=websocket,
settings=app.state.settings,
transcriber=app.state.transcriber,
extractor=app.state.intent_extractor,
session_factory=app.state.session_factory,
).run()