Skip to content

Add music album images to your music file directories

License

Notifications You must be signed in to change notification settings

jtmoon79/coverlovin2

Repository files navigation

CoverLovin2

CircleCI build coveralls code coverage PyPi version PyPi Python versions Commits since License

CoverLovin2 (Cover Loving, too!), Python name coverlovin2, is a Python script for downloading album cover art images, either via local searching and copying, or via downloading from various online services. A common use-case is creating "cover.jpg" files for a large collection of ripped Compact Disc albums.


Script Usage

Quickstart

To see what it will do without changing any files

coverlovin2 -s- --test /path/to/music/library

Recommended use

  1. Get your own Discogs Personal Access Token.

  2. Install coverlovin2

    python -m pip install coverlovin2
    
  3. Run once with the better searches (skip Google CSE; too complicated)

    coverlovin2 -d -sl -se -sm \
        -sd -dt "DISCOGS PERSONAL ACCESS TOKEN" \
        /path/to/music/library
    

    The prior will write cover.jpg files to each found Artist-Album directory.

  4. Run again to copy the previously downloaded cover.jpg to folder.jpg.

    coverlovin2 -d -n "folder" -sl /path/to/music/library
    

--help

The verbose --help message

usage: app.py [-h] [-n IMAGE_NAME] [-i {jpg,png,gif}]
              [-o] [-s*] [-s-] [-sl] [-se] [-sm]
              [-sg] [-sgz {small,medium,large}] [--sgid GID] [--sgkey GKEY]
              [-sd] [-dt DISCOGS_TOKEN] [-v] [-r REFERER] [-d] [--test]
              DIRS [DIRS ...]

This Python-based program is for automating downloading album cover art images.
A common use-case is creating a "cover.jpg" file for a collection of ripped
Compact Disc albums.

Given a list of directories, DIRS, recursively identify "album" directories.
"Album" directories have audio files, e.g. files with extensions like .mp3 or
.flac.  For each "album" directory, attempt to determine the Artist and Album.
Then find an album cover image file using the requested --search providers.  If
an album cover image file is found then write it to IMAGE_NAME.IMAGE_TYPE within
each "album" directory.

Audio files supported are .mp3, .m4a, .mp4, .flac, .ogg, .wma, .asf.

optional arguments:
  -h, --help            show this help message and exit

Required Arguments:
  DIRS                  directories to scan for audio files (Required)

Recommended:
  -n IMAGE_NAME, --image-name IMAGE_NAME
                        cover image file name IMAGE_NAME. This is the file name that will be created within passed DIRS. This will be appended with the preferred
                        image TYPE, e.g. "jpg", "png", etc. (default: "cover")
  -i {jpg,png,gif}, --image-type {jpg,png,gif}
                        image format IMAGE_TYPE (default: "jpg")
  -o, --overwrite       overwrite any previous file of the same file IMAGE_NAME and IMAGE_TYPE (default: False)

Search all:
  -s*, --search-all     Search for album cover images using all methods and services
  -s-, --search-all-no-init
                        Search for album cover images using all methods and services that do not require user initialization (e.g. no Google CSE, no Discogs).

Search the local directory for likely album cover images:
  -sl, --search-likely-cover
                        For any directory with audio media files but no file "IMAGE_NAME.IMAGE_TYPE", search the directory for files that are likely album cover
                        images. For example, given options: --name "cover" --type "jpg", and a directory of .mp3 files with a file "album.jpg", it is reasonable to
                        guess "album.jpg" is a an album cover image file. So copy file "album.jpg" to "cover.jpg" . This will skip an internet image lookup and
                        download and could be a more reliable way to retrieve the correct album cover image.

Search the local directory for an embedded album cover image:
  -se, --search-embedded
                        Search audio media files for embedded images. If found, attempt to extract the embedded image.

Search Musicbrainz NGS webservice:
  -sm, --search-musicbrainz
                        Search for album cover images using musicbrainz NGS webservice. MusicBrainz lookup is the most reliable web search method.

Search Google Custom Search Engine (CSE):
  -sg, --search-googlecse
                        Search for album cover images using Google CSE. Using the Google CSE requires an Engine ID and API Key. Google CSE reliability entirely
                        depends upon the added "Sites to search". The end of this help message has more advice around using Google CSE. Google CSE is the most
                        cumbersome search method.
  -sgz {small,medium,large}, --sgsize {small,medium,large}
                        Google CSE optional image file size (default: "large")
  --sgid GID            Google CSE ID (URL parameter "cx") typically looks like "009494817879853929660:efj39xwwkng". REQUIRED to use Google CSE.
  --sgkey GKEY          Google CSE API Key (URL parameter "key") typically looks like "KVEIA49cnkwoaaKZKGX_OSIxhatybxc9kd59Dst". REQUIRED to use Google CSE.

Search Discogs webservice:
  -sd, --search-discogs
                        Search for album cover images using Discogs webservice.
  -dt DISCOGS_TOKEN, --discogs-token DISCOGS_TOKEN
                        Discogs authentication Personal Access Token.

Debugging and Miscellanea:
  -v, --version         show program's version number and exit
  -r REFERER, --referer REFERER
                        Referer url used in HTTP GET requests (default: "https://github.com/jtmoon79/coverlovin2")
  -d, --debug           Print debugging messages. May be passed twice.
  --test                Only test, do not write any files

This program attempts to create album cover image files for the passed DIRS.  It
does this several ways, searching for album cover image files already present in
the directory (-sl).  If not found, it attempts to figure out the Artist and
Album for that directory then searches online services for an album cover image
(-sm or -sg).

Directories are searched recursively.  Any directory that contains one or more
with file name extension .mp3 or .m4a or .mp4 or .flac or .ogg or .wma or .asf
is presumed to be an album directory.  Given a directory of such files, file
contents will be read for the Artist name and Album name using embedded audio
tags (ID3, Windows Media, etc.).  If no embedded media tags are present then a
reasonable guess will be made about the Artist and Album based on the directory
name; specifically this will try to match a directory name with a pattern like
"Artist - Year - Album" or "Artist - Album".
From there, online search services are used to search for the required album
cover image. If found, it is written to the album directory to file name
IMAGE_NAME.IMAGE_TYPE (-n … -i …).

If option --search-googlecse is chosen then you must create your Google Custom
Search Engine (CSE).  This can be setup at https://cse.google.com/cse/all .  It
takes about 5 minutes.  This is where your own values for --sgid and --sgkey can
be created. --sgid is "Search engine ID" (URI parameter "cx") and --sgkey is
under the "Custom Search JSON API" from which you can generate an API Key (URI
parameter "key"). A key can be generated at
https://console.developers.google.com/apis/credentials.
Google CSE settings must have "Image search" as "ON"  and "Search the entire
web" as "OFF".

If option --search-discogs is chosen then you must pass a Discogs Personal
Access Token (PAT). A PAT is a forty character string generated at
https://www.discogs.com/settings/developers with the button "Generate new token".
Requires a discogs account.
Discogs does rate-limit throttling which this program will wait on. It significantly
increases the time to search for candidate album cover images.

Shortcomings:

- Does not handle Various Artist albums.

- --search-discogs can only retrieve jpg file no matter the --image-type passed.

- Multi-threading is only a rudimentary implementation. Does not efficiently queue
  non-overlapping tasks, i.e. the artist-album directory search phase must entirely
  finish before the album cover search phase begins, e.g. will not do HTTP searches
  as soon as possible.

PyPi project: https://pypi.org/project/CoverLovin2/
Source code: https://github.com/jtmoon79/coverlovin2

Inspired by the program coverlovin.

Common Media Player expectations

Sonos systems will use file folder.jpg.

Windows Media Player will use file folder.jpg if media-embedded images are not available.

VLC Media Player will use file folder.jpg if media-embedded images are not available.

MusicBee will use file cover.png or cover.jpg within the MUSIC library view, Album and Tracks pane if media-embedded images are not available.

Winamp will use file cover.png or cover.jpg if media-embedded images are not available.

One Commander will use file cover.jpg, folder.jpg, front.jpg, or background.jpg.

Installation

  • Using pip from pypi:

    python -m pip install coverlovin2
    
  • Using pip from source:

    python -m pip install -e "git+https://github.com/jtmoon79/coverlovin2.git@master#egg=CoverLovin2"
    

Invocation

There are few ways to run coverlovin2.

As a module

python -m coverlovin2 --version

As a standalone program

coverlovin2 --version

As a pip-run program

pip-run coverlovin2 -- -m coverlovin2 --version

or

pip-run --use-pep517 --quiet \
  "git+https://github.com/jtmoon79/coverlovin2" \
  -- -m coverlovin2 --version

As a pipx program

pipx run coverlovin2

See script execution-modes.

Run Phases

coverlovin2 runs in a few phases:

  1. recursively search passed directory paths for "album" directories. An "album" directory merely holds audio files of type .mp3, .m4a, .mp4, .flac, .ogg, .wma, or .asf. (see coverlovin2/app.py::AUDIO_TYPES).
  2. employ a few techniques for determining the artist and album for that directory. The most reliable technique is to read available embedded audio tags within the directory. (see coverlovin2/app.py::process_dir)
  3. using user-passed search options, search for the album cover art image file.
  4. if album cover art is found, create that image file into the "album" directory. The name and type of image (.jpg, .png, .gif) is based on user-passed options for the IMAGE_NAME and IMAGE_TYPE.

Development

First development session

Clone the repository:

git clone [email protected]:jtmoon79/coverlovin2.git

Using pipenv

Install pipenv.

Start the Python virtual environment and install the dependencies:

cd coverlovin2
pipenv --python 3.9 shell
pipenv install --dev

See the Pipfile.

Using pip

Install pip and virtualenv.

Create a virtual environment and install the dependencies:

cd coverlovin2
python -m virtualenv --copies .venv
.venv/Scripts/activate.ps1
python -m pip install --upgrade pip wheel setuptools
python -m pip install -e ".[dev]"

See the setup.py.

Subsequent development sessions

Using pipenv

pipenv

Start the pipenv shell (bash)

./tools/pipenv-shell.sh

(Powershell)

.\tools\pipenv-shell.ps1
pipenv update

Update Pipfile.lock with the latest libraries

  1. force upgrade within pip virtual environment

    python -m pip install --upgrade \
      attrs \
      discogs-client \
      musicbrainzngs \
      mutagen \
      Pillow \
      tabulate
    

    The listing of packages should follow those found in Pipfile.

  2. run pytests (they must pass)

    python -m pip install pytest pytest-dependency
    python -m pytest ./coverlovin2
    
  3. manually note versions installed

    python -m pip list -v
    
  4. tweak versions in Pipfile and setup.py the with pip list versions

  5. update Pipfile.lock

    python -m pipenv update
    
  6. commit changes

    git add Pipfile.lock Pipfile setup.py
    git commit -v -m "pipenv update"
    

pipenv update succeeds more often when run under Windows.

Using pip

python -m pip install --upgrade -e ".[dev]"

pytest

If pytests can run then the development environment is ready.

Run pytest tests (bash)

./tools/pytest-run.sh

or (Powershell)

.\tools\pytest-run.ps1

build

python setup.py bdist_wheel

or use the helper script

./tools/build-install-test.sh

new release

See Create A New Release.

Other Miscellaneous Notes

coverlovin2 requires Python version 3.7 or greater.

coverlovin2 is inspired by coverlovin.

coverlovin2 is a practice project for sake of the author catching up to changes in the Python Universe and the github Universe.
Some things the author explored:

  • project badges (are fun and useful)!
  • online services
  • pytests!
  • Rudimentary OAuth 1.0a authentication.
  • type-hinting‼
    coverlovin2 is very type-hinted code and could be even more so. The author thinks type-hinting is a good idea but it still needs improvement. In it's current form in Python 3.7, it feels clumsy to write and to grok. Also, PyCharm and mypy seem to catch different type-hint warnings.
    • mypy (and bugs? ☹)
  • Python 3.7 classes and programming (like SimpleQueue and namedtuple)
    • virtual environment manager pipenv.
  • printing odd UTF-8 characters (for example, \uFF5B, ) and coercing UTF8 mode (within a context without UTF8 support; MinGW bash on Windows)

Issues‼ 🐛 🐵

Other projects Bug Issues 🐛 and Feature Issues 🐵 the author created in the course of writing this application:

🐵 pypa/pipenv #3505

🐛 pypa/pipenv #3521

🐛 pypa/pipenv #3523

🐛 pypa/pipenv #3529

🐛 pypa/pipenv #3573

🐛 pypa/pipenv #4906

🐛 python/mypy #6476

🐛 python/mypy #6473

🐛 ant-druha/PowerShell #16


profile for @JamesThomasMoon on Stack Exchange, a network of free, community-driven Q&A sites