feat(wave): implement Phase 1 Smart Wave recommendations and buffer rotation
This commit is contained in:
1 parent
aa6c605d14
commit
9fbe372fab
10 files changed
+879
No files matched your search
+39
@@ -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()
|
||||
}
|
||||
Reference in new issue
Block a user