feat(wave): implement Phase 1 Smart Wave recommendations and buffer rotation

This commit is contained in:
Antigravity committed 2026-10-12 14:43:29 +03:00
1 parent aa6c605d14
commit 9fbe372fab
10 files changed
+879

No files matched your search

+39
View File
@@ -12,6 +12,8 @@ from app.db import init_db, get_recent_tracks, get_tracks_count, get_db
from app.queue import sync_manager
from app.core.search import search_all
from app.core.tagger import get_track_dest_path
from app.wave.rotator import wave_rotator
from app.wave.playlist import ensure_smart_playlist
app = FastAPI(title="Navidrome Music Sync", version="1.0.0")
@@ -26,6 +28,10 @@ class DownloadRequest(BaseModel):
@app.on_event("startup")
def on_startup():
init_db()
try:
ensure_smart_playlist()
except Exception as e:
print(f"Warning: Failed to ensure smart playlist: {e}")
@app.get("/")
def read_root(request: Request):
@@ -82,6 +88,13 @@ async def direct_download(url: str = Query(...)):
@app.get("/api/stream")
async def stream_audio(url: str = Query(...)):
"""Stream audio track for in-browser playback and seeking with HTTP Range support."""
if url.startswith("/") and os.path.exists(url) and os.path.realpath(url).startswith(os.path.realpath(settings.MUSIC_DIR)):
return FileResponse(
url,
media_type="audio/mpeg",
headers={"Accept-Ranges": "bytes", "Content-Disposition": "inline"}
)
provider = sync_manager.get_provider(url)
tracks = await provider.resolve(url)
if not tracks:
@@ -140,3 +153,29 @@ def get_history(limit: int = 50):
@app.get("/api/health")
def healthcheck():
return {"status": "ok", "yandex_configured": bool(settings.YANDEX_MUSIC_TOKEN)}
# --- Smart Wave Endpoints ---
@app.get("/api/wave/status")
def get_wave_status():
"""Return status of Smart Wave buffer."""
return wave_rotator.get_status()
@app.post("/api/wave/generate")
async def generate_wave():
"""Discover candidates and fill Smart Wave buffer up to capacity."""
result = await wave_rotator.fill_buffer()
return result
@app.post("/api/wave/rotate")
def rotate_wave():
"""Promote starred tracks and purge expired tracks in Smart Wave buffer."""
promoted = wave_rotator.promote_starred_tracks()
purged = wave_rotator.purge_expired_tracks()
ensure_smart_playlist()
return {
"promoted_count": len(promoted),
"promoted_tracks": promoted,
"purged_count": len(purged),
"purged_tracks": purged,
"current_status": wave_rotator.get_status()
}