Mappings Feature¶
It's very difficult to use unreliable metadata in your random assortment of audio files (well, sorry, just pointing it out) and map that to whatever the streaming services are using right this moment.
What makes this even more challenging is that some artists changed names over the years or are known under different names depending on the region. Or there can be legal trouble when a band is not allowed to use its original name for a while, but then the rights revert to the band after some lawsuit. Depending on when you bought their music, they might no longer be known under that name to Spotify and YouTube Music.
The mappings feature allows you to manually specify how certain albums and tracks should be matched when they can't be found automatically via the title-based matching system.
Usage¶
Add the --mappings-file option to any pushtunes push command:
# For albums
pushtunes push albums --from subsonic --to spotify --mappings-file mappings.csv
# For tracks
pushtunes push tracks --from subsonic --to spotify --mappings-file mappings.csv
# For playlists
pushtunes push playlist --from subsonic --to spotify --playlist-name "My Playlist" --mappings-file mappings.csv
Incremental Export¶
When you use --export-csv mappings-file to export failed items to a mappings file, the export is incremental rather than destructive. This means:
Preserves Existing Data¶
- If the target CSV file already exists, all existing rows are preserved
- Any data you've manually added (spotify_id, ytm_id, spotify_artist, etc.) is never deleted or modified
- This allows you to gradually build up a mappings file over multiple export runs
Only Adds New Items¶
- The export checks which items are already in the file (by comparing type, artist, and title)
- Only items that don't already exist in the file are added as new rows
- Items are compared case-insensitively, so "Volkor X" matches "volkor x"
Example Workflow¶
This incremental behavior enables an iterative workflow:
# First push attempt: export failures to mappings file
pushtunes push albums --from subsonic --to spotify \
--export-csv mappings-file \
--export-csv-file my_mappings.csv \
--mappings-file my_mappings.csv
# Output: "Exported 25 albums to my_mappings.csv"
# Manually edit my_mappings.csv to fill in some spotify_id values
# Second push attempt: export new failures to the same file
pushtunes push albums --from subsonic --to spotify \
--export-csv mappings-file \
--export-csv-file my_mappings.csv \
--mappings-file my_mappings.csv
# Output: "Exported 15 NEW albums to my_mappings.csv (preserving 25 existing rows)"
# Your manual edits to the first 25 albums are preserved.
# Only 15 new albums were added (items that weren't in the original 25)
push command and also write failures to it. But think of it this way: The push operation tries its best to succeed for every track and album, and it needs the mappings file for that so it can map to the correct stuff. If even after mapping it doesn't succeed, it writes those failures to the CSV file for you to fix.
Benefits¶
Gradual mapping building: You don't need to map everything at once. Export failures, map a few items, run again, map a few more.
Safe to re-export: You can safely export to the same file multiple times without losing your work. Your manual IDs and title corrections are never overwritten.
Combine multiple sources: Export failures from different push attempts (different filters, different sources) to the same mappings file to build a comprehensive mapping database.
No manual CSV merging: You don't need to manually merge multiple CSV files or worry about duplicates.
CSV Format¶
See mappings_complete_example.csv for a comprehensive example file with all columns and common use cases.
The mappings CSV file should have the following columns:
type: Eitheralbumortrackartist: The artist name from your source (Subsonic, CSV, or Jellyfin)title: The album or track title from your sourcespotify_id: (Optional) The Spotify ID of the target album/trackytm_id: (Optional) The YouTube Music ID of the target album/tracktidal_id: (Optional) The Tidal ID of the target album/trackspotify_artist: (Optional) The artist name to search for on Spotifyspotify_title: (Optional) The album/track title to search for on Spotifyytm_artist: (Optional) The artist name to search for on YouTube Musicytm_title: (Optional) The album/track title to search for on YouTube Musictidal_artist: (Optional) The artist name to search for on Tidaltidal_title: (Optional) The album/track title to search for on Tidalsubsonic_artist: (Optional) The artist name to search for on Subsonicsubsonic_title: (Optional) The album/track title to search for on Subsonicsubsonic_album: (Optional) The album name to search for on Subsonic (tracks only)jellyfin_artist: (Optional) The artist name to search for on Jellyfinjellyfin_title: (Optional) The album/track title to search for on Jellyfinjellyfin_album: (Optional) The album name to search for on Jellyfin (tracks only)
Mapping Methods¶
There are two ways to specify a mapping:
1. By Service ID (Direct)¶
If you know the exact Spotify, YouTube Music, or Tidal ID, you can specify it directly:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title
album,Lazerhawk,Redline,2fK9z3234fK9z3234fK9z3234,,,,,,,,
track,Perturbator,Humans Are Such Easy Prey,,VK4Kx2pVK4Kx2pVK4Kx2p,,,,,,,
album,Carpenter Brut,Trilogy,,,123456789,,,,,,
This method is the most accurate but requires you to find the IDs manually.
2. By Metadata (Search)¶
If you don't have the ID, you can specify the artist and title to search for:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title,subsonic_artist,subsonic_title,subsonic_album,jellyfin_artist,jellyfin_title,jellyfin_album
album,Volkor X,This Means War,,,Volkor X,This Really Means War (2025),,,,,,,
album,Mitch Murder,Current Events,,,Mitch Murder,Current Events (Remastered),,,,,,,
track,Kavinsky,Nightcall,,,Kavinsky,Nightcall (Drive Original Movie Soundtrack),,,,,,,
This method will search for the specified artist and title on the target service and use the normal matching logic to find the best match.
Note: For Subsonic and Jellyfin targets, only metadata-based mappings are supported (no ID columns). This is because track IDs are server-specific and not portable across different Subsonic/Jellyfin instances.
Target Service Specificity¶
You can specify mappings for multiple target services in the same file. The appropriate mapping will be used based on the --to target you specify:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title,subsonic_artist,subsonic_title,subsonic_album,jellyfin_artist,jellyfin_title,jellyfin_album
album,Volkor X,This Means War,,,Volkor X,This Really Means War (2025),Volkor X,This Means War (Deluxe),Volkor X,This Means War,Volkor X,This Means War,,,
In this example:
- When pushing to Spotify, it will search for "Volkor X - This Really Means War (2025)"
- When pushing to YouTube Music, it will search for "Volkor X - This Means War (Deluxe)"
- When pushing to Tidal, it will search for "Volkor X - This Means War"
- When pushing to Subsonic, it will search for "Volkor X - This Means War"
Example Use Cases¶
For a complete example CSV file with all these use cases and more, see mappings_complete_example.csv.
1. Remastered Albums¶
Your source has "This Means War" but Spotify only has "This Really Means War (2025)":
type,artist,title,spotify_id,ytm_id,spotify_artist,spotify_title,ytm_artist,ytm_title
album,Volkor X,This Means War,,,Volkor X,This Really Means War (2025),,
2. Different Artist Names¶
Your source has "Mitch Murder" but the album is listed under "Mitchell" on Spotify:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title
album,Mitch Murder,Current Events,,,Mitchell,Current Events,,,,
3. Soundtrack Tracks¶
Your source has just "Nightcall" but Spotify has it as part of a soundtrack:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title
track,Kavinsky,Nightcall,,,Kavinsky,Nightcall (Drive Original Movie Soundtrack),,,,
4. Using Service IDs¶
If you want to be absolutely certain, use the service ID:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title,subsonic_artist,subsonic_title,subsonic_album,jellyfin_artist,jellyfin_title,jellyfin_album
album,Lazerhawk,Redline,2fK9z3234fK9z3234fK9z3234,,,,,,,,,,,
To find service IDs:
Spotify:
1. Open the album/track in Spotify
2. Click "..." → "Share" → "Copy Spotify URI"
3. The ID is the last part after spotify:album: or spotify:track:
Tidal:
1. Open the album/track in Tidal
2. Click "..." → "Share" → "Copy Link"
3. The URL looks like https://tidal.com/browse/album/123456789
4. The ID is the numeric part at the end
5. Mapping to Subsonic/Jellyfin¶
When pushing playlists from streaming services to your local server, you can map tracks with different metadata:
type,artist,title,spotify_id,ytm_id,tidal_id,spotify_artist,spotify_title,ytm_artist,ytm_title,tidal_artist,tidal_title,subsonic_artist,subsonic_title,subsonic_album,jellyfin_artist,jellyfin_title,jellyfin_album
track,The Beatles,Let It Be,,,,,,,,,Beatles,Let It Be,Let It Be (Remastered),,,
track,Foo Fighters,Best Of You,,,,,,,,,Foo Fighters,Best of You,Greatest Hits,,,
This is useful when: - Your local files use different artist name formatting ("Beatles" vs "The Beatles") - Your local files are from different albums (e.g., remastered versions, compilations) - Track titles have slight variations in your local library
Statistics¶
When using mappings, the statistics output will show how many items were added via mappings:
==================================================
Statistics
==================================================
Total albums processed: 97
Skipped (filtered out): 5
Successfully added: 75
Added via mappings: 10
Skipped (already in library): 5
Skipped (not found): 1
Skipped (low similarity): 1
Errors: 0
==================================================
Notes¶
- Mappings are only used when the source artist/title exactly matches (case-insensitive)
- If a mapping is found, the normal search and matching logic is bypassed (unless using metadata mapping)
- Mappings work for albums, tracks, and playlist tracks
- You can mix both mapping methods in the same CSV file
- Empty columns are allowed - just leave them blank