🎧 Open source · Linux CLI

Load albums onto your
Zune HD from Linux

Point it at an album folder and it does the whole job in one command: canonical metadata, cover art, FLAC→MP3, clean tags, USB upload — and it never leaves a duplicate artist behind.

⬇ Get it on GitHub Read the docs
$ python3 zune_add.py "/music/Artist - Album (2026)"
🎵 MusicBrainz metadata 🖼 Cover Art Archive 🔄 FLAC → MP3 320 🔌 USB upload over MTP 🐍 Python 3
Everything's Falling
The Warning
Everything's Falling · 2026
one command · tagged, art-embedded, on the device

The whole pipeline, one command

No desktop Zune software, no Windows, no manual tagging — just a folder in, an album on the device out.

🎵

Canonical metadata

Looks the album up on MusicBrainz and fixes the artist, album, year, and track titles — preferring the standard edition so a deluxe or live release never overwrites your tracklist.

🖼

Real cover art

Pulls the front cover from the Cover Art Archive, rescales it to a Zune-friendly 500 px baseline JPEG, and embeds it on every track. Falls back to a local cover.jpg when offline.

🔄

FLAC → MP3, automatically

The Zune HD can't play FLAC or OGG. Anything it can't play is transcoded to MP3 320 kbps with ffmpeg; files it can play (MP3/WMA/AAC) are copied untouched.

🏷️

Clean ID3v2.3 tags

Writes exactly the tags the Zune HD reads — title, artist, album, track/total, year, genre, the embedded cover, and the MusicBrainz Artist Id — in the ID3 version the device expects.

🔌

Handles the finicky USB

Resets the USB port and stops the gvfs auto-mounter before uploading, so the Zune HD connects reliably on Linux instead of wedging mid-transfer.

🧹

No duplicate artists

Adding an album to an artist already on the device would normally make a second "Artist" heading. A safe merge re-points the new album to the original and removes the empty duplicate — never deleting music.

🔎

Preview before you commit

--dry-run shows the exact plan — matched release, track order, what gets transcoded — and stages the files without touching the device, so you can inspect before uploading.

📀

Batch a whole shelf

zune_batch.py runs several album folders in a row and prints an OK / FAIL summary at the end — load a stack of albums unattended.

🎚️

You stay in control

Override the detected artist or album, skip the online lookup to trust your own tags, or use --replace to cleanly re-add an artist from scratch.

From folder to device in one run

No project to manage and no settings to configure — the defaults are the common case.

1

Point at a folder

Give it an album directory. It reads the tags to detect the artist and album, then looks up the canonical release on MusicBrainz.

2

Stage & tag

It fetches the cover, transcodes anything the Zune can't play, and writes clean ID3v2.3 tags with the art embedded — all in a temp folder.

3

Confirm the plan

It prints the proposed upload — artist, album, year, track order — and waits for your OK (or skip the prompt with --yes).

4

Upload & tidy

It preps the USB, uploads over MTP, then merges any duplicate artist so the album lands under one clean heading on the device.

Built around what the Zune HD actually reads

The Zune HD is picky about formats, tag versions, and cover art. zune-manager produces exactly what it expects.

ConcernWhat the tool does
Plays nativelyMP3 · WMA · AAC/M4A · MP4
TranscodedFLAC · OGG · OPUS · WAV · ALAC → MP3 320k
TagsID3v2.3 (title/artist/album/track-total/year/genre)
Cover art500 px baseline JPEG, embedded (APIC)
Artist groupingone artist object, duplicates merged
TransportMTP over USB (MTPZ-authenticated)

zune-manager drives the compiled XuneSyncLibrary tools for the actual MTP transfer and the artist merge, and uses ffmpeg/mutagen for transcoding and tagging. See docs/architecture.md for the full module map.

Up and running on Linux

Python 3, ffmpeg, mutagen, the compiled XuneSyncLibrary tools, and your Zune HD's MTPZ keys.

1

Build XuneSyncLibrary

zune-manager drives its upload_test_cli, delete_artist, and merge_artist tools. Point XUNE_BUILD at the build dir.

2

Install deps

ffmpeg/ffprobe plus Python mutagen. On PEP-668 systems use the system package or a local venv (see the install doc).

3

Add the album

Connect the Zune HD (with ~/.mtpz-data present), then point zune_add.py at a folder.

# Clone
git clone https://github.com/mnavas/zune-manager.git
cd zune-manager

# mutagen — a local venv works on externally-managed Python (PEP 668)
python3 -m venv --system-site-packages .venv
.venv/bin/pip install mutagen

# Point at the compiled XuneSyncLibrary tools (if not the default)
export XUNE_BUILD=~/Code/XuneSyncLibrary/build

# Add an album (shows the plan, asks before uploading)
.venv/bin/python zune_add.py "/music/The Warning - Everything's Falling (2026)"

Full setup — XuneSyncLibrary, the MTPZ keys, the USB-connection recipe, and mutagen on Debian/Ubuntu — is in docs/installation.md.

Help make it better

zune-manager is open source and welcomes contributions of any size.

🐛

Report a bug

An album import go wrong, or the device not connect? Open an issue with the command, the output, and your distro.

Open an issue →
💡

Suggest a feature

Playlists, background images, other Zune models? Open a feature request and describe what you'd like.

Request a feature →
🔧

Submit a pull request

Fork, branch, and send a PR. Read docs/architecture.md first — it maps the pipeline and the device-safety rules.

Fork on GitHub →
📖

Improve the docs

Docs are plain Markdown in the docs/ folder — easy to edit and submit.

Browse the docs →

Keep old Zunes playing new music

zune-manager is built and maintained as a side project — a way to keep a discontinued device genuinely useful. It's free and open source.

If it saved you an afternoon of fighting MTP and tag editors, consider chipping in. Every bit helps keep it maintained and improving.

All contributions go directly to the developer. No company, no VC behind this.

📄 Open source

Free and open source

zune-manager is free to use, fork, and modify. No telemetry, no accounts, no cloud — everything runs on your own machine against your own device.

View on GitHub →