Ozellikler: - Playlist toplu indirme (onizle-ve-sec): YouTube playlist URL'si yapistir -> tum parcalar arama sonucu gibi listelenir (SearchThread playlist modu, noplaylist=False + extract_flat), checkbox'la sec, toplu indir. Yeni bridge slotu importPlaylist(url). Indirme pill'i "X/Y" sayaci gosterir (download_total). - Geri/Ileri gezinme: ust bardaki oklar artik gercek gorunum-gecmisi yiginiyla calisir (recordHistory/navBack/navFwd, wireEvents'te baglandi). Duzeltmeler (alt-ajan taramasindan): - Komut paletinden karaoke menusu flash-kapaniyordu -> palet ogesi onclick'i stopPropagation (global tikla-kapat menuyu silmesin). - Arama/akilli-liste gorunumunde surukle-sirala gercek listeyi bozup kaydediyordu -> trackRow(reorderable): yalniz gercek tam-liste suruklenebilir. - dl-pill/sep-pill/mini-klip ayni sag-alt kosede biniyordu -> pill'ler sol-alta, sepPill dl'nin ustune; ayrica sepPill .show sinifi eksikti (gorunmuyordu) -> fix. - trackChanged JSON.parse guard'siz -> try/catch. - repeat_mode trackChanged payload'inda yoktu -> eklendi + okundu (3 durumlu tekrar dugmesi parca degisince dogru). - Eski YouTube sonuclari sorgu degisince temizleniyor. Altyapi: - Dependabot (.github/dependabot.yml): pip + github-actions haftalik. - docs/: ARCHITECTURE, BRIDGE-SIGNALS, KNOWN-ISSUES, DEV (+ TR->EN sozluk) — proje kendini belgeliyor. graphify grafigi guncellendi. - README + GitHub about + Pages: banner (OpenRouter/Nano Banana Pro ile uretildi), rozetler, v1.0.4 notlari.
10 KiB
Just Music Premium — Developer Quickstart
A Windows desktop music player: Python + PyQt6 QtWebEngine. The UI is a local web app
(justmusic/web/, HTML/CSS/JS) served over a custom app:// scheme and wired to Python through
a QWebChannel bridge. Audio DSP is Python (numpy/scipy/sounddevice); downloads use the yt-dlp
Python library; studio karaoke (vocal/instrument separation) uses demucs on CPU.
This is the get-started guide. For design rationale and non-obvious decisions see the companion docs listed in Docs index.
Windows-only project. All commands below are for a Windows shell (PowerShell). Paths use
\.
1. Run from source (dev)
Interpreter. Python 3.13 family (C:\Python313). CI builds on 3.12, so both are fine.
Trap on this machine:
python3is the Microsoft Store stub — usepython(i.e.C:\Python313\python.exe), notpython3.
Create the venv and install deps (from the project root):
python -m venv .venv
.venv\Scripts\python.exe -m pip install --upgrade pip
.venv\Scripts\python.exe -m pip install -r requirements.txt
requirements.txt pulls PyQt6 + PyQt6-WebEngine, numpy/scipy/sounddevice, yt-dlp, demucs
(drags in torch — CPU wheel, ~490 MB), and pyinstaller.
Embedded binaries — bin/ must exist. The app calls three bundled executables that are NOT
in the repo tree by default; CI downloads them fresh each build. For a source run they must be
present in bin/:
| File | Purpose |
|---|---|
bin\ffmpeg.exe |
transcode / decode to mp3 |
bin\yt-dlp.exe |
(the in-process yt-dlp library does the work; exe is the fallback) |
bin\deno.exe |
required for YouTube nsig / JS signature solving — see ARCHITECTURE.md |
justmusic/config.py resolves each from bin/ first, falls back to PATH, and prepends bin/
to the process PATH so the in-process yt-dlp finds deno.exe. Without deno.exe, YouTube
downloads break. (bin/ currently has all three checked in on this machine.)
Launch:
.venv\Scripts\python.exe main.py
main.py registers the app:// URL scheme, spins up the QMainWindow + QWebEngineView,
registers the Bridge on the web channel, and loads app://app/index.html.
User data lives outside the repo — in ~\Music\JustMusic\ (writable even if the app is
installed read-only):
library.json— the library/playlist database (config.DATA_FILE)downloads\— downloaded trackscovers\— cover-art cachestems\— demucs vocal/instrument separation output (studio karaoke)
config.ensure_dirs() creates the base, downloads\, and covers\ on startup. Your own
~\Music is also scanned for the auto playlist.
2. Build the exe locally
python build.py
Output: dist\JustMusic\JustMusic.exe (PyInstaller onedir — fast startup, recommended).
build.py --onefile produces a single dist\JustMusic.exe instead (portable but slow to start).
The build --collect-alls torch + demucs and their friends (julius, einops, lameenc,
safetensors, sphn, huggingface_hub) plus PyQt6 WebEngine, and --add-binarys the three bin/
exes and the web UI. Consequence: the build is large (~1.4 GB dist\) and slow.
Before rebuilding,
dist\andbuild\will be locked if the app is running. Kill any runningJustMusic.exeand itsQtWebEngineProcesschildren, then deletedist\andbuild\:taskkill /IM JustMusic.exe /F 2>$null; taskkill /IM QtWebEngineProcess.exe /F 2>$null Remove-Item -Recurse -Force dist, build -ErrorAction SilentlyContinue
3. Release a new version (the important one)
Shipping is just tag + push — CI builds the .msi and publishes the GitHub Release, and the
app auto-updates itself in the field.
-
Bump the version to match the tag. Edit
APP_VERSIONinjustmusic\config.py(currently"1.0.3") so it equals the tag you're about to push, e.g.1.0.4. -
Tag and push:
git tag v1.0.4 git push origin v1.0.4The
v*tag triggers.github/workflows/build.ymlonwindows-latest, which:- re-stamps
config.APP_VERSIONfrom the tag (so the exe always knows its own version — you still bump it in step 1 so source and tag agree); pip install -r requirements.txt;- downloads fresh
ffmpeg.exe,yt-dlp.exe,deno.exeintobin/; - runs
python build.py; - packages a
.msiwith WiX 3.14 (heat→candle→light,installer\Product.wxs) — perUser install, no UAC / admin; - publishes a GitHub Release on the tag with
JustMusic-Setup.msiattached.
You can also run it without a tag via workflow_dispatch (manual run) with a
versioninput. - re-stamps
-
In-app auto-update —
justmusic\updater.py. On launch, a backgroundUpdateCheckThreadasks the GitHub "latest release" API (config.UPDATE_API). If the release tag is newer thanAPP_VERSION, it downloadsJustMusic-Setup.msisilently to%TEMP%\JustMusic-update\and stages it. On app close (Bridge.shutdown), a detached.cmdwaits for the app to exit, runsmsiexec /i ... /qn(silent, perUser → no UAC), and relaunches the exe.- Only frozen (PyInstaller) builds download; a source run just compares versions and does nothing. No network → it gives up silently.
Net effect: to ship, you only tag + push. Users get it on their next launch/close cycle.
-
GitHub Pages landing page —
.github/workflows/pages.ymldeployssite/to Pages on push tomain(whensite/**or the workflow file changes). Independent of the release flow.
4. Common maintenance
yt-dlp goes stale. YouTube changes its player/signature often; an old yt-dlp starts failing downloads (e.g. HTTP 403). Fix:
- bump the floor in
requirements.txt— theyt-dlp>=YYYY.MM.DDline; - bump
APP_VERSION, tag a patch, push.
CI always fetches the newest yt-dlp, so a fresh release usually clears it. This is exactly what
v1.0.3 was (yt-dlp>=2026.8.19, fixing the 403 that 2026.07.04 caused).
5. The knowledge graph (graphify)
graphify-out/ holds a graphify code graph (god nodes, community structure, cross-file
relationships). Per the repo CLAUDE.md:
- For codebase questions, prefer the scoped subgraph over raw grep:
graphify query "<question>" graphify path "<A>" "<B>" # relationships between two things graphify explain "<concept>" # focused concept graphify-out/wiki/index.md(if present) is good for broad navigation; readgraphify-out/GRAPH_REPORT.mdonly for wide architecture review.- After editing code, refresh the graph (AST-only, no API cost):
graphify update .
6. Docs index
| Doc | What's in it |
|---|---|
docs/ARCHITECTURE.md |
Design overview + non-obvious decisions (why deno, the app:// scheme, DSP pipeline, clip mode) |
docs/BRIDGE-SIGNALS.md |
The QWebChannel contracts — Python Bridge methods and Qt signals the web UI calls/listens to |
docs/KNOWN-ISSUES.md |
Known defects and traps |
docs/DEV.md |
This file |
7. Turkish → English glossary
The code, comments, community/playlist labels, and UI strings are Turkish. Common terms a non-Turkish reader will hit:
| Turkish | English |
|---|---|
| Kütüphanem | My Library (default playlist) |
| Beğenilen Şarkılar | Liked Songs (favorites) |
| İndirilenler | Downloads (playlist) |
| Çalma listesi | Playlist |
| Şarkı | Song / Track |
| Sanatçı | Artist |
| Ara / Arama | Search |
| İndir | Download |
| Efektler | Effects |
| Ekolayzır | Equalizer |
| Kuyruk / Sıradaki | Queue / Up next |
| Sözler / Şarkı Sözleri | Lyrics |
| Karaoke / Vokal | Vocal (karaoke) |
| Enstrümantal | Instrumental |
| Ayır | Separate (stems) |
| Kapak | Cover art |
| Tema | Theme |
| Ayarlar | Settings |
| Sürükle | Drag |
| Klip / Klip izle | Video clip / Watch clip |
| Ses | Volume / Audio |
| Hız | Speed |
| Tara | Scan (music folder) |
| Yedek / Yedek al | Backup / Back up |
| Güncelleme | Update |
| Ruh Hali | Mood |
| Akıllı Listeler | Smart Playlists |
| Ana Sayfa | Home |
| Oynat / Duraklat | Play / Pause |
| Önceki / Sonraki | Previous / Next |
| Karıştır | Shuffle |
| Tekrarla | Repeat |
| Beğen | Like |
| Görselleştirici | Visualizer |
| Uyku zamanlayıcı | Sleep timer |
| Sessize al | Mute |
| Ambiyans ışığı | Ambient light |
| Kompakt mod | Compact mode |
| İstatistikler | Statistics |
| Ekle | Add (import) |
| Tam ekran | Fullscreen |
| Bas / Orta / Tiz | Bass / Mid / Treble (EQ bands) |
| Yankı / Reverb | Reverb / Echo |
| Oda | Room (reverb preset) |
| Düzenle | Edit |
| Sil / Kaldır | Delete / Remove |
| Bilinmeyen | Unknown (missing metadata) |