Files
Audio-Classifier/backend/src/api/routes/tracks.py
2025-12-22 15:53:26 +01:00

137 lines
3.7 KiB
Python

"""Track management endpoints."""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from uuid import UUID
from ...models.database import get_db
from ...models import crud
from ...models.schema import AudioTrack
router = APIRouter()
@router.get("", response_model=dict)
async def get_tracks(
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=500),
genre: Optional[str] = None,
mood: Optional[str] = None,
bpm_min: Optional[float] = Query(None, ge=0, le=300),
bpm_max: Optional[float] = Query(None, ge=0, le=300),
energy_min: Optional[float] = Query(None, ge=0, le=1),
energy_max: Optional[float] = Query(None, ge=0, le=1),
has_vocals: Optional[bool] = None,
key: Optional[str] = None,
instrument: Optional[str] = None,
tempo_range: Optional[str] = Query(None, regex="^(slow|medium|fast)$"),
sort_by: str = Query("analyzed_at", regex="^(analyzed_at|tempo_bpm|duration_seconds|filename|energy)$"),
sort_desc: bool = True,
db: Session = Depends(get_db),
):
"""Get tracks with filters and pagination.
Args:
skip: Number of records to skip
limit: Maximum number of records
genre: Filter by genre
mood: Filter by mood
bpm_min: Minimum BPM
bpm_max: Maximum BPM
energy_min: Minimum energy
energy_max: Maximum energy
has_vocals: Filter by vocal presence
key: Filter by musical key
instrument: Filter by instrument
tempo_range: Filter by tempo range (slow: <100, medium: 100-140, fast: >140)
sort_by: Field to sort by
sort_desc: Sort descending
db: Database session
Returns:
Paginated list of tracks with total count
"""
# Convert tempo_range to bpm_min/bpm_max
if tempo_range:
if tempo_range == "slow":
bpm_max = 100.0 if bpm_max is None else min(bpm_max, 100.0)
elif tempo_range == "medium":
bpm_min = 100.0 if bpm_min is None else max(bpm_min, 100.0)
bpm_max = 140.0 if bpm_max is None else min(bpm_max, 140.0)
elif tempo_range == "fast":
bpm_min = 140.0 if bpm_min is None else max(bpm_min, 140.0)
tracks, total = crud.get_tracks(
db=db,
skip=skip,
limit=limit,
genre=genre,
mood=mood,
bpm_min=bpm_min,
bpm_max=bpm_max,
energy_min=energy_min,
energy_max=energy_max,
has_vocals=has_vocals,
key=key,
instrument=instrument,
sort_by=sort_by,
sort_desc=sort_desc,
)
return {
"tracks": [track.to_dict() for track in tracks],
"total": total,
"skip": skip,
"limit": limit,
}
@router.get("/{track_id}")
async def get_track(
track_id: UUID,
db: Session = Depends(get_db),
):
"""Get track by ID.
Args:
track_id: Track UUID
db: Database session
Returns:
Track details
Raises:
HTTPException: 404 if track not found
"""
track = crud.get_track_by_id(db, track_id)
if not track:
raise HTTPException(status_code=404, detail="Track not found")
return track.to_dict()
@router.delete("/{track_id}")
async def delete_track(
track_id: UUID,
db: Session = Depends(get_db),
):
"""Delete track by ID.
Args:
track_id: Track UUID
db: Database session
Returns:
Success message
Raises:
HTTPException: 404 if track not found
"""
success = crud.delete_track(db, track_id)
if not success:
raise HTTPException(status_code=404, detail="Track not found")
return {"message": "Track deleted successfully", "track_id": str(track_id)}