Skip to content

Exporting playlists

export-playlist is a console script installed alongside the service. It reads the playlists and their ordered entries from the SQLite database and writes them as M3U8 files, the Unicode-friendly variant that Mixxx recommends. It never contacts Spotify or YouTube Music, so it needs no credentials and can be run while the service is stopped.

Running the command

export-playlist [--provider PROVIDER --playlist ID] [--output PATH]

Run it from the directory holding config.toml and state.db, either as the installed script or through uv:

uv run export-playlist --provider spotify --playlist 37i9dQZEVXbNG2KDcFcKOF
uv run python -m passive_music_dl.export_playlist

The command reads the same config.toml and state.db as the service, both resolved relative to the current working directory. Playlists must already be in the database, so run the service once first to sync them.

Option Description
--provider, -p Playlist provider: spotify or youtube_music. Required with --playlist.
--playlist, -l The provider-specific playlist ID. Required with --provider.
--output, -o The file path to write to, overriding playlist_output_dir.

--provider and --playlist must be given together; giving one without the other is a usage error.

Export a single playlist

export-playlist --provider spotify --playlist 37i9dQZEVXbNG2KDcFcKOF

The playlist is written to playlist_output_dir under a file name derived from its display name (see File names).

Write to a specific path

--output writes to exactly the path given, overriding both the directory and the derived file name:

export-playlist --provider spotify --playlist 37i9dQZEVXbNG2KDcFcKOF \
  --output ~/playlists/road-trip.m3u8

--output is only accepted together with --provider and --playlist, since a batch export would otherwise write every playlist to the same file. ~ is expanded to the user's home directory.

Interactive selection

With no --provider/--playlist, the command lists every playlist already in the database - each shown as <name> [<provider>] - and exports the ones you select. Toggle an entry with Space and confirm with Enter. No provider API or authentication is involved; the list and the tracks all come from the database.

Standard input must be a terminal. A non-interactive session (for example a scheduled job or a pipe) does not prompt and exits with code 64 instead. If the database holds no playlists, or the prompt is cancelled, nothing is exported and the command exits 0.

Output

Location

Files are written to playlist_output_dir, a [download] option that defaults to a playlists directory under output_dir:

[download]
output_dir = "/srv/music"   # playlist_output_dir defaults to /srv/music/playlists
# playlist_output_dir = "/srv/playlists"   # optional override

The directory is created if it does not already exist. ~ in the configured path is expanded. --output overrides the whole path for a single export.

File contents

Each file is UTF-8 encoded - which is why the .m3u8 extension is used rather than .m3u - begins with the #EXTM3U header, and then lists the recorded filesystem path of each track, one per line, in the order the track appears in the playlist. A trailing newline ends the file.

The paths are stored as they were written under output_dir, so an absolute output_dir (as in the examples) produces absolute paths, which is what most players expect.

File names

The file is named after the playlist's display name, lowercased, with the characters a file name cannot hold removed, and a .m3u8 suffix appended. Names in any script are kept as written (हालेर गान → हालेर-गान.m3u8).

When a name contains nothing a file name can hold, the command falls back:

  • symbols are spelled out with their Adobe Glyph List names (!!!! → EXCLAMEXCLAMEXCLAMEXCLAM.m3u8);
  • if that is still empty (for example an emoji-only name), the file is named after the provider and playlist ID (spotify-pl5.m3u8), which also keeps the write inside playlist_output_dir.

Overlong names are shortened to fit the filesystem's per-component byte limit; the command logs a warning so a cut name can be traced back to the playlist it came from. See ADR-0012 for the full naming and truncation rules.

Exit codes

An unknown or empty playlist does not produce a file. For a batch export the exit code is the most serious failure encountered.

Code Meaning
0 Every requested playlist was written.
2 Usage error (bad arguments), reported by the argument parser.
64 Interactive selection was requested but standard input is not a terminal.
65 A requested playlist is not in the database, so its name is unknown.
66 A requested playlist has no entries on disk, so there was nothing to export.
73 The playlist file or its directory could not be written.
78 config.toml was missing, unreadable, or failed schema validation.

Relationship to the service

The exporter is read-only with respect to the providers and only reads the database; it never downloads or authenticates. It exists so that the ordered playlists the service tracks can be handed to an external player. The service itself continues to write tracks flat into output_dir and never writes playlists, so playlist_output_dir is only ever touched by export-playlist.