| """Sample audio listing & download endpoints.""" |
| from __future__ import annotations |
|
|
| import contextlib |
|
|
| import soundfile as sf |
| from fastapi import APIRouter, HTTPException |
| from fastapi.responses import FileResponse |
|
|
| from app.config import settings |
| from app.schemas.response import SampleAudio, SamplesResponse |
| from app.utils.samples import SAMPLES, sample_by_id, sample_path |
|
|
| router = APIRouter() |
|
|
|
|
| def _duration_safe(path) -> float | None: |
| if not path.exists(): |
| return None |
| with contextlib.suppress(Exception): |
| info = sf.info(str(path)) |
| return float(info.frames) / float(info.samplerate) |
| return None |
|
|
|
|
| @router.get("/samples", response_model=SamplesResponse) |
| async def list_samples() -> SamplesResponse: |
| out = [] |
| for s in SAMPLES: |
| path = sample_path(s["filename"]) |
| out.append( |
| SampleAudio( |
| sample_id=s["sample_id"], |
| filename=s["filename"], |
| label=s["label"], |
| description=s["description"], |
| duration_seconds=_duration_safe(path), |
| url=f"{settings.api_prefix}/samples/{s['sample_id']}/download", |
| ) |
| ) |
| return SamplesResponse(samples=out) |
|
|
|
|
| @router.get("/samples/{sample_id}/download") |
| async def download_sample(sample_id: str): |
| s = sample_by_id(sample_id) |
| if s is None: |
| raise HTTPException(status_code=404, detail="Unknown sample.") |
| path = sample_path(s["filename"]) |
| if not path.exists(): |
| raise HTTPException( |
| status_code=404, |
| detail=( |
| f"Sample file '{s['filename']}' not present on the server. " |
| "Add real WAV files under data/sample_audios/ to enable this endpoint." |
| ), |
| ) |
| return FileResponse(str(path), media_type="audio/wav", filename=s["filename"]) |
|
|