MusicMind for Plex v2 is live!

MusicMind for Plex v2 is out — real audio analysis, not just AI guesses

Hi everyone — quick update since the original post. v2 shipped, and the
headline feature is a direct answer to something that came up in this
thread: wanting to know exactly what the software is doing to your
library.

Synapse — local audio analysis. MusicMind now analyzes the actual
audio of every track on your own hardware: real BPM, musical key, and
danceability, measured from the waveform using Essentia (the open-source
audio analysis library from the Music Technology Group at Universitat
Pompeu Fabra). No cloud calls, no guessing from titles — deterministic
signal processing on your files. It runs as a background job you kick
off from the admin page, it’s resumable, and it gives you a time
estimate based on your own hardware before you commit.

What that unlocks:

  • BPM and danceability filters in playlist generation — “upbeat
    running mix around 170 BPM” now means literally that

  • DJ-ify — reorders a playlist for flow, using measured BPM and key
    for smoother transitions

  • Last.fm date searchlastfm: prompts plus an “On This Day”
    picker to rebuild what you were listening to on any date in your
    scrobble history

  • The Collection — a stats dashboard for your library and listening
    history (by era, country, genre, and more)

Also new: a proper CHANGELOG and SECURITY policy in the repo, and the
project rename to MusicMind for Plex is fully complete (thanks again to
tom80H for the trademark heads-up).

What’s next — and a confession. v1’s instrumental tagging asked an
AI to judge from artist + title text alone. I recently audited that
against actual audio analysis, and the results were humbling: roughly
half the “instrumental” tags were wrong. (A track called “Wordless”
turns out to have vocals. The AI never stood a chance.) So I’m
currently re-verifying my entire 17,000-track library with a local
voice/instrumental model that listens to the actual audio — same
philosophy as Synapse: measure, don’t guess. That lands in the next
release, and text-based instrumental guessing is being retired for
good.

GitHub: https://github.com/earthmonkey419/musicmindforplex

Site: https://musicmind.vp-fun.com

Feedback very welcome — especially from anyone who tries Synapse on a
big library. Curious how the analysis times compare across hardware.

— Louis (Earthmonkey)

Gave this a crack this morning with pyenv and it appeared to pickup my tracks in the initial `python3.12 plex_music_brain_ingest.py python3.12 plex_tag_tracks.py python3.12 mb_enrich_artists.py python3.12 enrich_artists.py sudo python3.12 enrich_compilations.py python3.12 lastfm_sync.py python3.12 lastfm_gaps.py python3.12 listening_context.py` ingest.

Synapse and many web-app related admin functions gave connection failures and other sorts of errors:
0|plex-music-brain | [2026-07-11 10:04:55,088] ERROR in app: Exception on /run/mbenrich [GET] 0|plex-music-brain | Traceback (most recent call last): 0|plex-music-brain | File “/home/mark/musicmindforplex/venv/lib/python3.12/site-packages/flask/app.py”, line 1511, in wsgi_app 0|plex-music-brain | response = self.full_dispatch_request() 0|plex-music-brain | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0|plex-music-brain | File “/home/mark/musicmindforplex/venv/lib/python3.12/site-packages/flask/app.py”, line 919, in full_dispatch_request 0|plex-music-brain | rv = self.handle_user_exception(e) 0|plex-music-brain | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0|plex-music-brain | File “/home/mark/musicmindforplex/venv/lib/python3.12/site-packages/flask/app.py”, line 917, in full_dispatch_request 0|plex-music-brain | rv = self.dispatch_request() 0|plex-music-brain | ^^^^^^^^^^^^^^^^^^^^^^^ 0|plex-music-brain | File “/home/mark/musicmindforplex/venv/lib/python3.12/site-packages/flask/app.py”, line 902, in dispatch_request 0|plex-music-brain | return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] 0|plex-music-brain | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0|plex-music-brain | TypeError: run_synapse_full() got an unexpected keyword argument ‘script’ 0|plex-music-brain | 127.0.0.1 - - [11/Jul/2026 10:04:55] “GET /run/mbenrich HTTP/1.1” 500 -

Will try again eventually (:

I tried different plex baseURLS. Just odd it would add tracks to the db, but not run the synapse or any other web-app related options

Hi Mark, thanks for the info!
The /run/<script> route lost its function binding in a v2 refactor, which broke every generic admin run button (the “connection failures” are the same bug — the admin page streams those jobs, and the stream dies on the 500). Fix is pushed to main. git pull in your musicmindforplex directory and restart the app (pm2 restart plex-music-brain or however you’re running it), and the admin buttons should come to life. The command-line scripts you already ran are unaffected — your ingest and enrichment data is all good. Let me know how Synapse goes on your library — genuinely curious about analysis times on other hardware.

I appreciate you trying it and reporting the bug!

Thanks,

Louis

When trying to run :musical_score: Enrich Artists (MusicBrainz):

Traceback (most recent call last): File “/home/blah/musicmindforplex/mb_enrich_artists.py”, line 247, in main() File “/home/blah/musicmindforplex/mb_enrich_artists.py”, line 242, in main enrich(conn, test_mode=test_mode, limit=limit) File “/home/blah/musicmindforplex/mb_enrich_artists.py”, line 130, in enrich artists = get_unenriched_artists(conn) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File “/home/blah/musicmindforplex/mb_enrich_artists.py”, line 57, in get_unenriched_artists return [row[0] for row in conn.execute(f"“” ^^^^^^^^^^^^^^^^^ sqlite3.OperationalError: no such table: artist_meta :cross_mark: Error (exit code 1)

When trying to run script - python3.12 synapse_analyze.py --estimate python3.12 synapse_analyze.py:

((venv) ) blah@blah-pc:~/musicmindforplex$ python3.12 synapse_analyze.py --estimate python3.12 synapse_analyze.py
Connecting to blah…
Connected to: blah

Running live estimate — analyzing real sample tracks on this hardware…

Walking library to count file formats…

2000 files counted…
4000 files counted…
6000 files counted…
8000 files counted…
10000 files counted…
12000 files counted…
14000 files counted…
16000 files counted…
18000 files counted…

========================================
Total files: 19243

mp3: 18280 (95.0%)
flac: 520 (2.7%)
m4a: 349 (1.8%)
ogg: 66 (0.3%)
wav: 27 (0.1%)
aif: 1 (0.0%)

Timing mp3 samples…
[[[[ALL SONGS FAIL HERE]]]
mp3: all 8 candidate samples failed — no timing available for this format

Timing flac samples…
[[[[ALL SONGS FAIL HERE]]]
flac: all 8 candidate samples failed — no timing available for this format

Timing m4a samples…
[[[[ALL SONGS FAIL HERE]]]
m4a: all 8 candidate samples failed — no timing available for this format

All sample analyses failed for every format. Cannot estimate.

Thoughts?

Hi Mavproductions,
Two more real finds — thank you. Both fixed on main, so git pull first.

Enrich Artists crash: the artist_meta table was only created by a script that runs later in the setup order, and its schema was missing a column newer code expects — worked on my install only because my database predates the code. Fixed: both enrichment scripts now create/upgrade the table themselves, in any order. After pulling, just rerun python3.12 mb_enrich_artists.py.

Synapse samples all failing: the estimate was unhelpfully hiding why each sample failed — that’s fixed too, so after pulling, rerun python3.12 synapse_analyze.py --estimate and it’ll print the actual error. My strong suspicion for the root cause: a numpy version clash — essentia’s prebuilt wheels don’t work with numpy 2.x, and a fresh pip install essentia in a new venv usually pulls numpy 2. Quick check: pip show numpy | grep Version — if it says 2.x, run pip install "numpy<2" and try the estimate again. Post whatever error the estimate prints either way and we’ll get you analyzing.

(Also, small thing: --estimate and the full run are two separate commands run one after the other — looks like they got pasted as one line. The estimate ignores the extra arguments so no harm done.)

Again, thanks for your feedback. V3 will not be shipped with these install issues!

Louis

So I think the problem actually is my Plex server runs on Windows, and I’m running musicmind in WSL.


Plex is returning file paths in Windows format (J:\Music\...) — meaning your Plex server (blah-plexserver) runs on Windows and sees that music library on its J: drive. But synapse_analyze.py is running inside WSL (Linux), and essentia’s audio loader (built on ffmpeg) tries to parse J: as a protocol prefix — like it would parse http: or file: — and fails with “Protocol not found” because J: isn’t a real protocol. It’s not a filesystem-not-found issue, it’s a path-format mismatch between the two OSes.

For this to work, WSL needs to translate Plex’s Windows paths into paths it can actually read — either:

  • Windows J:\ needs to map to a WSL mount point (e.g. /mnt/j/) if that drive is accessible from WSL, or
  • the script needs a path-translation step that isn’t in it yet.

Nailed it — that’s exactly the problem, and you diagnosed it better than my error message did. Plex reports paths as its host sees them, and until now MusicMind assumed it lived on the same filesystem view. That assumption is now gone: git pull, then add this to your config.py:

python

PATH_MAP = {
    "J:\\Music": "/mnt/j/Music",
}

(Adjust to your actual paths — longest matching prefix wins, and backslashes get converted automatically.) One WSL wrinkle to check first: if J: is a network drive, WSL doesn’t auto-mount it like it does fixed drives — ls /mnt/j will tell you. If it’s missing: sudo mkdir -p /mnt/j && sudo mount -t drvfs J: /mnt/j.

Then rerun python3.12 synapse_analyze.py --estimate and it should start timing real samples. Also run sudo python3.12 enrich_compilations.py again after configuring — it reads files directly too and was silently failing on the same paths. Your setup (Windows Plex + WSL) is genuinely useful territory for the project — thanks for pushing through the rough edges.

Louis

enrich_compilations.py:

((venv) ) blah@blah:~/musicmindforplex$ python3.12 enrich_compilations.py
MusicMind for Plex - Compilation Enrichment

Traceback (most recent call last):
File “/home/blah/musicmindforplex/enrich_compilations.py”, line 128, in
main()
File “/home/blah/musicmindforplex/enrich_compilations.py”, line 71, in main
rows = conn.execute(“”"
^^^^^^^^^^^^^^^^
sqlite3.OperationalError: no such column: real_artist

Still getting enrichment error. Path_Map + sudo mount command seems to clear up a few errors.

As it stands right now is this thing gonna break if I try to make any playlists or is synapse required?

Sorry about that!

Pull again — you found the last (I believe) of a whole family of these: three columns (real_artist, is_instrumental, genres_written) that were added to my database over months of development but never made it into the table-creation code, so fresh databases were missing all of them. The ingest script now creates the full schema and auto-upgrades existing databases. After pulling, run python3.12 plex_music_brain_ingest.py once — it adds the missing columns to your existing DB in the first second, then refreshes your library data — then sudo python3.12 enrich_compilations.py should finally behave.

Straight answer on your question: Synapse is not required for playlists. Prompt-based generation needs only ingest + the AI tagger, which you’ve run. Synapse powers the extras — BPM/danceability filters and DJ-ify — which will just be unavailable until it runs. But honest disclosure: before this fix, playlist generation would have crashed on your database anyway (the missing real_artist column sits in the core search query). After the pull + ingest rerun, generate away — and I’d genuinely like to hear what the playlists are like on your library.

Thanks for your help -
Louis

Getting this error when running plex_music_brain_ingest.py:

((venv) ) blah@blah:~/musicmindforplex$ python3.12 plex_music_brain_ingest.py
MusicMind for Plex - Library Ingest

Connecting to Plex…
Connected to: blah-plex

Database ready: /home/blah/musicmindforplex/plex_music_brain.db

Incremental ingest since 2026-07-11T18:56:10.436089

Found 1455 artists. Starting ingest…

Done. 1 tracks ingested, 19242 skipped.
Traceback (most recent call last):
File “/home/blah/musicmindforplex/plex_music_brain_ingest.py”, line 188, in
main()
File “/home/blah/musicmindforplex/plex_music_brain_ingest.py”, line 184, in main
ingest(conn, plex)
File “/home/blah/musicmindforplex/plex_music_brain_ingest.py”, line 171, in ingest
reconcile_removed_tracks(conn, seen_rating_keys)
File “/home/blah/musicmindforplex/plex_music_brain_ingest.py”, line 78, in reconcile_removed_tracks
conn.execute(f"DELETE FROM track_tags WHERE rating_key IN ({placeholders})", removed_list)
sqlite3.OperationalError: no such table: track_tags

I might wait at this point until this app becomes more mature, this is getting frustrating.

I get that. It is an ambitious project. Unfortunately, from where the concept started to where I am now was a messy road. Sharing it with the world wasn’t even my goal, but I was enjoying so much! As such, I have built upon the app and in the process added tables for new functions that were not created in the original setup. Your help has been very valuable in discovering these bugs. I know it will be a worthwhile app once the kinks are ironed out.
For what it’s worth, the fix for this latest one is already pushed — and having now audited the whole schema, I believe you’re at the end of the setup gauntlet, not the middle. One pull + one ingest rerun and the pipeline should be open.
The ingest script now creates every core table itself, so it works standalone in any order. Rerun python3.12 plex_music_brain_ingest.py and it should complete cleanly this time — including that reconciliation step, which by the way was doing its job: it noticed tracks in your database that are no longer in Plex and was trying to tidy them up when it tripped.

One suggestion given how these early bugs cascaded into each other: after this ingest succeeds, rerun python3.12 plex_tag_tracks.py too — your first run of it may have died early (on a bug fixed two days ago) before tagging much, and tags are what playlist generation runs on. Then you should be fully in business.
I didn’t mean to ‘outsource the pain’. I have created a test silo, so I can test it more fully going forward.

Sincerely,
Louis

I’m getting somewhere now, have my collection page populating quite a bit, besides (currently) “Library by Era/Country” and “Artists by Gender”.

Running Synapse now, ETA 23.4hrs.

Tried playlist generation and “what you were listening to on said date” and those worked. :slight_smile: After synapse, I’m guessing it will be a running of instrumental analysis, then go from there.

Glad to hear it!

On instrumental analysis: honest heads-up before you spend the time. The current tag_instrumentals.py classifies from artist/title text, and I recently audited it against actual audio analysis on my own library — roughly half its calls were wrong. I’m mid-migration to a model that listens to the actual audio (same philosophy as Synapse), which lands in the next release. You can run the text version today if you want the filter populated now, but I’d wait for the real one.

Run python3.12 mb_enrich_artists.py then python3.12 enrich_artists.py — both are fine to run while Synapse works, and the tiles should light up after a page refresh.

Also, your Synapse ETA is a genuinely useful data point — that works out to roughly 4× faster per track than my NAS’s Celeron. Exactly the cross-hardware info I was hoping to gather. Curious what the final wall-clock ends up being.

Louis

I’ll wait for your next release re: instrumentals! Thanks for the heads up! :slight_smile:

I’ll let you know the finalized elapsed time when I have it. If I cancel, and reboot where it left off, will the elapsed time be accurate still?

Also any chance since synapse is a long process, that you could include some sort of usage of the already synapse’d music into the AI playlist generation, along with showing a list or data visualizer of songs/artists that have or have not been synapsed via percentage of completion or something of the like?

I love this, and I hope Plex can see this loud and clear that this is where their OpenAI should moving forward with.

Also:

Could you possibly add more filtering of songs? I kind of like how it has unplayed already, but I’d also like the option of “comfort picks” with songs too. IE. Songs I have 𝑥 amount of plays already of.

Having some sort of filter for “popularity picks” would be nice too, as I’m sure in my library in-particular, that I have songs that have 0 plays, but have the popularity icon(:fire:) that plex uses built-in.

To answer your older question first - if you had to restart the scan, yes, it calculates a new estimate.
Already synapse’d music IS available for playlist generation. But adding a gauge would be helpful - I will work on it for v3!
“Comfort picks” will aslo be added (the logic is there, it’s just not wired), as well as “popularity picks” - I never considered using that data. But now I am intrigued!
Thanks so much for all your feedback! I really do appreciate it. It has been invaluable. Now i have testing silos and a dev branch of the repo, so I don’t present buggy work.
Dig into your stacks!
Louis

MusicMind for Plex v3 is getting close! :tada:

I’ve been hard at work on v3, and it’s shaping up to be the biggest release yet.

Some of the highlights include:

  • :brain: Synapse — real audio analysis (tempo, key, danceability, instrumental detection)
  • :bullseye: Smarter playlist generation with improved search logic
  • :musical_note: “Based On” recommendations for both tracks and artists
  • :radio: Much deeper Last.fm integration
  • :headphone: Acoustic fingerprinting to identify the real artists behind many “Various Artists” tracks
  • :bar_chart: Playlist Audit, Query Logs, and CSV export
  • :rocket: Better performance, reliability, and a much more polished user experience

One of the biggest changes isn’t a feature—it’s the philosophy.

MusicMind now uses the best tool for each job:

  • Measure audio when it can be measured.
  • Use trusted sources like MusicBrainz, AcoustID, and Last.fm when the data already exists.
  • Use AI only where interpretation actually adds value.

The result is a system that’s smarter, more transparent, and much less dependent on AI than previous versions.

I’m putting the finishing touches on v3 now. Thanks again to everyone who’s been testing, suggesting ideas, and helping shape the project. I can’t wait to get this release into your hands.

MusicMind for Plex v3!!!