Lyrics pipeline (Whisper + Demucs + description alignment):
- New GenerateLyricsJob runs WhisperX with VAD filtering and forced word
alignment, writes per-track JSON to NAS.
- New DecorateLyricsJob calls the active LLM provider to bake one to
several emojis into each line (heavy decoration prompt).
- LyricsDescriptionParser strips heading content, section markers, and
emoji-decoration from a song's description while preserving every
language verbatim.
- correct_whisper_with_description aligner: strong-match anchors only,
vocal-region-aware gap-fill so missing verses land on actual singing.
- Owner UI for generate/regenerate/edit/delete in the player gear.
Admin pages:
- /admin/lyrics toggles for VAD, vocal gap-fill, Demucs, master
- /admin/gpu extracted GPU section, encoder picker, FFmpeg path
- /admin/backup extracted users-and-settings export/import
- /admin/settings now AI/LLM only with provider list and Test button
- /admin/nas-storage hosts NAS settings, repair, disable flow, browser
- Shared partials/settings-styles for a uniform look across pages.
Playlist view tracking:
- Migration adds playlists.view_count and playlist_views dedup table.
- Playlist::bumpViewIfNew increments per device with a one-hour window.
- Tracked from /playlists/{id}, /playlists/share/{token}, /ps/{token},
and /videos/{id}?playlist={token}. Dispatched after-response so it
never blocks the page render.
- Loading a playlist on the video page now runs one query instead of
the four the old getNextVideo/getPreviousVideo path triggered.
- View counts shown on every playlist card and the playlist hero.
Player polish:
- Floating mini-player is draggable, persists its position in
localStorage, clamps to viewport on resize.
- Mini disabled entirely on mobile (less than 768px).
- New gear-menu Mini Player toggle (persists in localStorage) lets the
user disable both scroll-activation and SPA-nav-activation.
- Close button keeps media playing when used on the player's own page.
- SPA navigator now swaps a #page-scripts container so per-page JS
(channel tabs, etc.) gets re-executed after content swaps.
Storage layout:
- Runtime data moved from /storage/* to /data/* and gitignored.
- /ml/venv, /ml/cache, /ml/__pycache__ excluded.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Storage structure
- All audio tracks (primary + per-language) now live in one folder per song with
unique lowercase names ({slug}-{lang}-{id}); no more tracks/ subfolder.
- Generated renders (download video + HLS) moved into the song's local-only cache/
subfolder, separated from source files (never synced to NAS, safe to wipe).
- tracks:reorganize artisan command (dry-run default) consolidates legacy files,
updates DB paths, and deletes orphans + empty folders.
- CLAUDE.md documents the canonical layout as a global rule (identical local + NAS).
Version-aware download & share
- Download MP3/Video and Share now act on the version being played; ?track={id}
is carried through share links and auto-selects audio + title + flag + about +
OG/meta on open.
GPU + visualizer
- Setting::gpuUsable() runs a cached health probe (nvidia-smi + nvenc smoke test,
256x144) before sending any encode to the GPU; falls back to CPU otherwise.
- Visualizer "Download Video" bakes in equal-width, cover-coloured, translucent
frequency bars; loop-filter rebuild makes generation ~25x faster.
Image cropper
- result-callback mode + per-song cover-slide cropper in upload/edit (modal + mobile).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduce per-video language support and multiple audio tracks
(VideoAudioTrack model + migrations for language, description, title),
a reusable language-select component, and a track-editor form. Bundle
the self-hosted flag-icons v7.2.3 library and a NAS auto-sync command.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On mobile, entering fullscreen now also locks the screen orientation to
landscape via the Screen Orientation API. Exiting fullscreen unlocks it,
allowing the device to return to portrait. Applied to both the video
player and audio player. Gracefully ignored on browsers that don't
support screen.orientation.lock (e.g. iOS Safari).
Also includes the playlist auto-scroll fix (committed separately).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three bugs in the Up Next / playlist SPA transition for music-type videos:
1. Title selector was '.audio-title' (doesn't exist) instead of '.video-title span'
2. Cover image only updated #audioCoverImg — missed when video has a slideshow
3. Slideshow SLIDE_URLS lived in a closed IIFE and couldn't be updated cross-video
Fix: always render both #audioCoverImg and #slideshowWrap in the DOM (toggle
display via inline style), hoist slideshow state variables outside the if-block,
and expose window._audioPlayerUpdate(d) that both recTransitionTo and
plTransitionTo call. The hook handles all cases: cover-to-cover, cover-to-slideshow,
slideshow-to-cover, slideshow-to-slideshow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Controls were only added to show.blade.php, but music/generic/match videos
render their own complete layouts with their own sidebars. Added the
pl-controls-bar to all three type views and the global CSS to app.blade.php.
- music: full standalone JS with shuffle/loop/autoplay + _plOnTrackEnd hook
- generic/match: syncs with video-player's existing ytpShuffleRow/ytpAutoplayRow toggles
- audio-player: ended handler now calls window._plOnTrackEnd if defined
- video-player: exposes window._ytpNav.next/prev for sidebar prev/next buttons
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- video-player: add userSeeking flag so mid-seek pause events are
suppressed; force-resume on 'seeked' if video was playing before seek;
guard player click handler against progCont clicks; e.preventDefault()
on touchend to stop synthetic click toggling play
- audio-player: apply identical seek fixes (same four changes)
- app layout: add floating mini-player that saves video state to
sessionStorage when bottom nav is tapped while a video is playing,
then restores playback on the next page via a floating overlay
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Installed p7h/nas-file-manager package via private VCS repo
- Published config/nas-file-manager.php with super_admin middleware restriction
- Added NAS env vars to .env.example
- Created admin/nas-storage page with connection info panel and file browser widget
- Added NAS Storage link to admin sidebar (super_admin only)
- Added SuperAdminController@nasStorage method and admin.nas-storage route
- Includes all accumulated branch changes: profile wall, 2FA, audit logs,
settings panel, country/phone/timezone components, posts, slideshow,
playlist shares, video downloads/shares, comment likes, notifications,
social links, and more
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>