Skip to content

Instantly share code, notes, and snippets.

@rhasselbaum
Last active February 15, 2021 15:24
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rhasselbaum/e1cf714e21f00741826f to your computer and use it in GitHub Desktop.
Save rhasselbaum/e1cf714e21f00741826f to your computer and use it in GitHub Desktop.
Export Google Music Playlists to M3U

Recently, I decided to migrate my music library from Google Play Music to a self-hosted server running Subsonic. Only problem is I have a bunch of playlists, and Google provides no way to export those into any format that Subsonic can consume (m3u, pls, xspf). I also couldn't find an unofficial tool to do this. The best I could find was a handy app in the Play store called Playlist Backup. It can't export playlists for music stored remotely at Google, but it can create lists of albums and tracks names. Good enough! Now all I needed was a utility that could employ some fuzzy logic to match these lists to my local music files, which follow a typical Artist / Albumn / Track hierarchy.

Turns out, Python 3 makes this really easy! Just copy the script below:

playlist-gen.py:

#!/usr/bin/env python3

# Converts a list of audio tracks to corresponding files in a file system using fuzzy matching.
# Track names are read from standard input. For each, we try to find the best match to a
# file path under the current directory recursively. The best match is written to standard output.
# Optionally, a path prefix can be given as an argument to the script. If given, it will be
# prepended to each output file path (e.g. "/media/music/".

import re
import difflib
import sys
import glob
import os.path

# Get optional path prefix, which could be passed in as an argument.
path_prefix = sys.argv[1] if len(sys.argv) > 1 else ''

# Get list of paths to files under the current directory.
files = [file for file in glob.glob('**', recursive=True) if os.path.isfile(file)]

# Each line from standard input is expected to be a track name. Could have artist and album info, too.
for track in sys.stdin.readlines():
    # Here's the magic. Find the best match! Python is so awesome.
    close_matches = difflib.get_close_matches(track, files, n=1, cutoff=0.1)
    if close_matches:
        print("{0}{1}".format(path_prefix, close_matches[0]))
    else:
        print('!! NO MATCH: {0}'.format(track), file=sys.stderr)

To use it, change directory to the root of your music file hierarchy, then invoke the script like this:

python3 /path/to/playlist-gen.py <path/to/track_list.txt

It will try to match the tracks in track_list.txt to files under the current directory and print a list of the best matches to standard output. If you are satisfied with the results, you can create an M3U playlist file simply by redirecting the output to a file:

python3 /path/to/playlist-gen.py <path/to/track_list.txt >path/to/playlist.m3u

If it cannot find a reaosnable match for a track, it prints an error to standard error and keeps going so you can circle back and set those tracks manually afterwards.

If you want a path name to be prepended to each file in the output, you can supply it as an argument. For example, my music folder in Subsonic is /opt/music/General so I would use:

python3 /path/to/playlist-gen.py /opt/music/General <path/to/track_list.txt >path/to/playlist.m3u
@lucidBrot
Copy link

lucidBrot commented Sep 14, 2017

You gave me hope! Sadly, the app linked does not support the current version and just fails on every playlist. Do you happen to know of an alternative that still works?

(Btw in case you care: you've got a type "reaosnable")

EDIT: I'll try it with https://webapps.stackexchange.com/questions/50311/print-playlist-from-google-play-music tomorrow or so. But seems like your script is amazing, the question is only how to get that songlist without all the errors from the JS-Script from my link. I'll keep you updated

2nd EDIT: The second answer on the above link gave me 159 of my 161 Songs in the playlist. Would be nice to know what it skipped (maybe duplicates). I might check this manually

3rd EDIT: That works. Thanks again! The differences seem to actually be duplicates.

@wwwwiiiillll
Copy link

you can transfer your playlist and tracks from one source to another by using this tool MusConv.com tool.

@lucidBrot
Copy link

For anybody googling in 2021, while GPM is drawing its last breaths: I also made an export script: https://github.com/lucidBrot/migrate-from-google-play-music for extracting songs and playlists from Google Takeout and cleaning up the library duplicates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment