Files
trackpull/docs/votify.md

3.8 KiB

Votify Download System

Overview

Votify is the primary Spotify download backend. It invokes the votify-fix CLI tool (a third-party Python package) as a subprocess, streams its output to the job log, and post-processes the resulting files.


How It Works

  1. User submits Spotify URLs and options via POST /api/download.
  2. A job is created and a background thread runs run_download().
  3. run_download() builds a votify CLI command and launches it via subprocess.Popen.
  4. stdout is streamed line-by-line into the job's output log.
  5. On completion, post-processing runs:
    • Flatten nested directories
    • Rename files from embedded metadata
    • Wrap single-track downloads in a folder
    • Convert to MP3 if requested

Authentication

Votify authenticates with Spotify using a cookies.txt file in Netscape format. This file must be uploaded by an admin via the Settings page before any downloads will succeed.

Path: /config/cookies.txt (configurable via COOKIES_PATH env var)

A Widevine device certificate (device.wvd) may also be required depending on the content. It is uploaded separately via Settings.

Path: /config/device.wvd (configurable via WVD_PATH env var)


Download Options

Option Values Description
audio_quality aac-medium, aac-high, vorbis-low, vorbis-medium, vorbis-high Audio quality
output_format original, mp3 Keep original format or convert to MP3
download_mode ytdlp, aria2c Download backend
save_cover bool Save cover art as a separate image file
save_playlist bool Save playlist metadata file
overwrite bool Re-download if file already exists
download_music_videos bool Include music video downloads
no_lrc bool Skip LRC (lyrics) file generation
video_format mp4, webm Format for music videos
cover_size small, medium, large, extra-large Cover art resolution
truncate int (optional) Limit number of tracks to download

MP3 Conversion

If output_format is set to mp3, files are converted after download using ffmpeg at 320 kbps. The conversion preserves embedded metadata. Original files are deleted after successful conversion.


Cancellation

The Popen process handle is stored on the job dict. POST /api/jobs/<id>/cancel calls process.terminate(), which sends SIGTERM to the votify subprocess.


Post-Processing Detail

After the subprocess exits, post_process_votify_files() runs:

  1. Snapshot before — records which audio files existed before the download started (to identify new files).
  2. Flatten — collapses single-subdirectory chains into the parent folder.
  3. Rename — calls rename_from_metadata() to produce Title - Artist.ext filenames.
  4. Wrap singles — if exactly one file downloaded with no enclosing folder, wraps it in a folder named after the file.
  5. Cleanup — removes leftover empty directories.

External Dependencies

Dependency Purpose
votify-fix (GitHub: GladistonXD/votify-fix) Spotify download CLI
ffmpeg MP3 conversion
aria2c Optional download manager
yt-dlp Default download manager
mp4decrypt (Bento4) MP4 DRM decryption

Limitations

  • Requires valid Spotify cookies (must be refreshed periodically when they expire).
  • DRM-protected content requires a Widevine device certificate.
  • Quality options are limited to what Votify and the Spotify API expose.

Key Files

File Relevance
app.py run_download(), post_process_votify_files(), route /api/download
utils.py rename_from_metadata(), cleanup_empty_dirs()
Dockerfile Installation of votify-fix, ffmpeg, aria2, Bento4