Repository navigation
Local files: serve genre from tags and studio labels - #118
Merged
Merged
Conversation
…trims, hard reload, new albums playlist - The player's analyser no longer classifies anything (style.rs `classify`, off from engine.js): a served genre pins the family, none served means no genre. A client's ask is measured whatever heads exist. - Local files (uploads, library files, YouTube rows) are asked about by their UUID: /api/analyses, /api/analysis/<id>, primeAnalyses and the tag sheet all dropped them, so an upload never had a genre, tagged or not. An upload is measured as it lands, and the genre written in a local file's tags is served (below a studio tag). A label moves the verdict generation, and a device whose queue is all cached checks it on a track change. - Silence trimming only ever touches the edges: at most 10 s at either end, never past a decode that stopped short, and the player drops bounds measured on a file of another length. - Réglages: "Recharger l'application de zéro" (unregisters the service worker, empties the shell cache, forgets device-learnt state, keeps settings, session and downloads); the animation settings say when WebGL was refused. - "Nouveautés pour toi" en vrac: every new album, whole, in one local playlist "Deezer · Nouveautés en vrac" on each sync. - Track rows lay out on their own width: in the full-screen player's side panel a title was left one letter wide. - Nothing starts a background analysis under app.testing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F5yXmv8AwwJ4dbUES2LiEJ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extends the analysis API to serve genres for uploaded/local files using their own tags and studio-applied labels, bringing them to parity with Deezer tracks.
Summary
Local files (uploads, library imports) now have their genre served by the API just like Deezer tracks. The genre comes from three sources in priority order: studio tags (admin-applied), the file's own tags (what the uploader wrote), or nothing. This required changes across the analysis pipeline, the web player, and supporting infrastructure.
Key changes
Backend analysis & API:
supysonic/deezer/analysis.py: Addedfile_genre()to extract and normalize genre from a local file's tags, matching against studio tags and known vocabularies. Updatedpayload_for()to include file-sourced genres. Modified_decide_style()to use file genres as a fallback before heuristics.supysonic/webui/analysis.py: Refactored_key()to handle both Deezer UUIDs and local file UUIDs uniformly. Updated_rows_for()to serve genres for local files with studio tags or file tags, and_queue_missing()to accept local file IDs.supysonic/webui/__init__.py: Queue local file analysis on upload, like Deezer tracks.Web player & analysis:
webapp/src/lib/analysis.js: AddedMISS_TTL(5 min) for negative verdicts vs.VERDICT_TTL(24 hr) for positive ones. Added generation revalidation: when no request has been made for 30s, a track change asks for the generation alone to catch server-side label changes without re-asking cached tracks.webapp/src/lib/audio/engine.js: Removed live classifier (liveRangealways false) — the genre is now only the server's answer or nothing.webapp/rhythm/src/style.rs&webapp/src/lib/audio/rhythm-core.js: Addedclassifyflag to disable live family rules; when off,dominantis -1 and confidence 0.Silence trimming refinement:
supysonic/webui/edges.py: IntroducedMAX_EDGE_TRIM(10s) — quiet stretches longer than this are music, not edges. Silence in the middle of a track never moves bounds. Updated test expectations to reflect the new logic.webapp/src/components/Player.svelte: Added validation that trim bounds don't exceedEDGE_MAXor apply to files of different length (re-archives).UI & settings:
webapp/src/components/HardReload.svelte&webapp/src/lib/hardreload.js: New "reload from scratch" feature for Settings → Diagnostic, clearing device-learnt state (cached analyses, edges, glitch routes, look-ahead) while preserving login, settings, queue, and offline copies. Handles GPU crashes that leave WebGL unavailable.webapp/src/components/VisualizerSettings.svelte: Integrated hard-reload button.webapp/src/components/TrackRow.svelte: Fixed grid layout when album column is absent (phone-narrow side panel on desktop).Deezer integration:
supysonic/deezer/provider.py&supysonic/deezer/importer.py: Addedget_new_release_albums()andsync_new_albums()to import "Nouveautés pour toi" — the new-releases mix plus every new album whole, as one playlist.deezerpy/gw.py: Addedget_module_page()to fetch CMS module pages (e.g., the new-releases grid).Config & tests:
config.sample,config/supysonic.conf.example,supysonic/config.py: Addedimport_new_albumsoption.tests/test_webui.py: Updated upload test to verify analysis is queued; refined silence-trim tests.tests/test_deezer.py: Added tests for new-album import.https://claude.ai/code/session_01F5yXmv8AwwJ4dbUES2LiEJ