Skip to content

Instantly share code, notes, and snippets.

@cpeel
Created August 22, 2020 00:21
Embed
What would you like to do?
Import playlists into Plex using plexapi
#!/usr/bin/env python3
"""
Import playlists into a local Plex server. I used this to import my Google Play
Music playlists when it was being sunset. This consumes the JSON output by my
playlist-reconstructor.py at https://gist.github.com/cpeel/e18d3e1d6f9881039b6a2e024fb5dce1
The script will die if it can't find a track, only creates a playlist if it can
find all the tracks, and will skip playlists that already exist. This allows the
script to be used in an iterative process by tweaking the track title contents
in the JSON file as necessary and rerunning it. If you set the "Removed" field
to 1 in the JSON, this will skip the track and continue.
This is a pure hack job but it only had to work once and it saved me hours
of time recreating dozens of ordered playlists.
I'm posting it as a gist primarily as an example for how to search for tracks
(and artists) in using plexapi and create playlists.
You will need to populate the global variables to values for your Plex server
and library.
"""
import json
import sys
import plexapi
from plexapi.server import PlexServer
# URL and token to your Plex server. See also:
# https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/
baseurl = "http://localhost:32400"
token = "TOKEN"
# Your Plex library name
library_name = "My Music"
# JSON playlist file
playlist_json_file = "playlists.json"
def main():
# connect to plex
plex = PlexServer(baseurl, token)
# load all playlist names from Plex
plex_playlists = []
for playlist in plex.playlists():
plex_playlists.append(playlist.title)
plex_library = plex.library.section(library_name)
# load playlists from JSON
with open(playlist_json_file) as inputfile:
playlists = json.load(inputfile)
for playlist in playlists:
if playlist["Title"] in plex_playlists:
print(f"Skipping {playlist['Title']}")
continue
print(f"Importing {playlist['Title']}")
plex_items = []
for track in playlist["Tracks"]:
if track["Removed"]:
print(f"Skipping {track['Title']}")
continue
plex_track = None
print(f"Searching for {track['Title']}")
# Find the plex items matching on title and artist
results = plex_library.search(track["Title"], libtype="track")
if len(results) == 1:
plex_track = results[0]
else:
for result in results:
if result.artist().title == track["Artist"]:
plex_track = result
break
if not plex_track:
# ok try to find it by artist then title and normalize the
# track title a bit to improve matching
print("Falling back to artist search")
normalized_track_names = [
track["Title"].lower(),
track["Title"].lower().replace("’", "'"),
track["Title"].lower().replace("'", "’"),
track["Title"].lower().replace("“", '"'),
track["Title"].lower().replace('"', "“"),
track["Title"].lower().replace("&", "and"),
track["Title"].lower().replace("and", "&"),
]
results = plex_library.search(track["Artist"], libtype="artist")
for result in results:
for search_track in result.tracks():
if search_track.title.lower() in normalized_track_names:
plex_track = search_track
break
if plex_track:
break
if plex_track:
plex_items.append(plex_track)
else:
print(
f"Unable to find track for {track['Title']} by {track['Artist']}"
)
sys.exit(1)
plexapi.playlist.Playlist.create(plex, playlist["Title"], plex_items)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment