Fill a portable music player with a curated, DJ-balanced random selection from your music library
Project description
fill-music-player
Fill a portable music player with a curated, DJ-balanced random selection from your music library.
Point it at a music folder (NAS, ~/Music, external drive) and a destination (Walkman, iPod, USB stick). It scans for audio files, reads ID3/MP4/WMA tags, balances by artist and genre, and copies a shuffled selection that fits your player's capacity.
Install
# Option 1: run directly with uv (no install needed)
uvx fill-music-player --help
# Option 2: install from PyPI
pip install fill-music-player
# Option 3: run the script directly
uv run fill_music_player.py --help
Usage
# Always dry-run first to preview the selection
fill-music-player --source /Volumes/music --dest /Volumes/WALKMAN/MUSIC --dry-run
# Then copy for real
fill-music-player --source /Volumes/music --dest /Volumes/WALKMAN/MUSIC
Common examples
# Fill a Sony Walkman from a Synology NAS
fill-music-player -s /Volumes/music -d /Volumes/WALKMAN/MUSIC
# Target exactly 2 GB, MP3 only
fill-music-player -s ~/Music -d /media/usb/MUSIC --target-gb 2 --formats mp3
# Skip radio recordings and jingles folders
fill-music-player -s /Volumes/music -d /Volumes/PLAYER \
--skip-dirs "jingles,!recordings,!restored"
# Reproducible selection (same seed = same tracks every time)
fill-music-player -s /Volumes/music -d /Volumes/PLAYER --seed 42
# Tighter artist diversity (max 2 tracks per artist)
fill-music-player -s /Volumes/music -d /Volumes/PLAYER --max-per-artist 2
How it works
- Scan — walks your music library for supported audio files (MP3, M4A, WMA, AAC by default)
- Filter — skips files that are too large (radio shows/mixes) or too small (jingles/corrupt)
- Read tags — extracts artist/album from ID3, MP4, or WMA metadata; falls back to folder name parsing (
Genre/Artist - Album/track.mp3) - Curate — allocates a proportional byte budget per genre directory, then picks tracks while enforcing artist and album diversity caps
- Shuffle — globally randomizes the final selection so genres are interleaved
- Copy — writes files to the destination preserving the
genre/artist/album/trackstructure, with FAT32-safe filenames
Options
| Flag | Default | Description |
|---|---|---|
-s, --source |
required | Source music root directory |
-d, --dest |
required | Destination directory on the player |
--target-gb |
95% of free space | How many GB to fill |
--max-file-mb |
20 | Skip files larger than this (filters mixes/shows) |
--min-file-kb |
300 | Skip files smaller than this (filters jingles) |
--max-per-artist |
4 | Max tracks from any single artist |
--max-per-album |
3 | Max tracks from any single album |
--formats |
mp3,m4a,wma,aac | Comma-separated allowed extensions |
--skip-dirs |
(none) | Comma-separated top-level dirs to skip |
--seed |
(random) | Random seed for reproducible selection |
--dry-run |
false | Preview without copying |
Device format cheat sheet
| Device | Recommended --formats |
|---|---|
| Sony Walkman (NWZ series) | mp3,m4a,wma |
| iPod classic/nano | mp3,m4a,aac |
| Generic USB player | mp3 |
| Modern player (FiiO, etc.) | mp3,m4a,wma,aac,ogg,flac |
Expected folder structure
The tool expects your source music to be organized as:
/Volumes/music/
blues/
Muddy Waters - Electric Mud/
01 - Tom Cat.mp3
ZZ Top/
1983 - Eliminator/
01 Gimme All Your Lovin.mp3
funk/
Fela Kuti/
...
hiphop/
Dr.Dre - The Chronic/
...
Top-level directories are treated as genre categories. Artist/album info comes from metadata tags first, folder names second.
AI agent skill
This tool also works as a Claude Code / pi.dev skill. Copy the SKILL.md to your skills directory and the agent will know when and how to use it.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fill_music_player-0.1.0.tar.gz.
File metadata
- Download URL: fill_music_player-0.1.0.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e42df52bb619437e7ffaf3b03d744e4793b05ded593bdcb8c7ad676bed2b59fc
|
|
| MD5 |
ec64a628d87b26dd20e2fea34a589dca
|
|
| BLAKE2b-256 |
0f5d384188cd4f9e412b67ce5da3c5cd487c2c383a102ff9adcdb77219cef42a
|
File details
Details for the file fill_music_player-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fill_music_player-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ae6b9548eceb4f694737660e24831aa16688c0f9feaae44e9fb6a64b968b8c7
|
|
| MD5 |
d7b203173b122a7329c2425f2ebdc0c2
|
|
| BLAKE2b-256 |
fec02ef7be88bbd8ce40129ae8df6ed290b6de6bd9acac3c3108a2fc65770868
|