<!-- README.md -->
# CoverLovin2 <!-- omit in toc -->
[![Build Status](https://img.shields.io/travis/com/jtmoon79/coverlovin2.svg?branch=master&style=flat-square&logo=travis)](https://app.travis-ci.com/github/jtmoon79/coverlovin2/)
[![CircleCI](https://img.shields.io/circleci/build/gh/jtmoon79/coverlovin2.svg?logo=circleci&style=flat-square)](https://circleci.com/gh/jtmoon79/coverlovin2)
[![codecov.io code coverage](https://img.shields.io/codecov/c/github/jtmoon79/coverlovin2/branch?main&token=Q2OXTL7U02&style=flat-square&logo=codecov)](https://codecov.io/gh/jtmoon79/coverlovin2)
[![coveralls code coverage](https://img.shields.io/coveralls/github/jtmoon79/coverlovin2/branch?main&token=Q2OXTL7U02&style=flat-square&logo=coveralls)](https://coveralls.io/github/jtmoon79/coverlovin2)
[![PyPi version](https://img.shields.io/pypi/v/coverlovin2.svg?longCache=True&logo=pypi&color=blue&style=flat-square)](https://pypi.org/pypi/coverlovin2/)
[![PyPi Python versions](https://img.shields.io/pypi/pyversions/coverlovin2.svg?longCache=True&logo=pypi&style=flat-square)](https://pypi.org/pypi/coverlovin2/)
[![Commits since](https://img.shields.io/github/commits-since/jtmoon79/coverlovin2/latest.svg?color=yellow&style=flat-square)](https://img.shields.io/github/commits-since/jtmoon79/coverlovin2/latest.svg)
[![License](https://img.shields.io/pypi/l/coverlovin2?style=flat-square)](https://opensource.org/licenses/Apache-2.0)
*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.
----
<!-- TOC updated by VS Code extention Markdown All In One -->
- [Script Usage](#script-usage)
- [Quickstart](#quickstart)
- [Recommended use](#recommended-use)
- [`--help`](#--help)
- [Common Media Player expectations](#common-media-player-expectations)
- [Installation](#installation)
- [Invocation](#invocation)
- [Development](#development)
- [First development session](#first-development-session)
- [Using `pipenv`](#using-pipenv)
- [Using `pip`](#using-pip)
- [Subsequent development sessions](#subsequent-development-sessions)
- [Using `pipenv`](#using-pipenv-1)
- [pipenv](#pipenv)
- [pipenv update](#pipenv-update)
- [Using `pip`](#using-pip-1)
- [pytest](#pytest)
- [build](#build)
- [new release](#new-release)
- [Other Miscellaneous Notes](#other-miscellaneous-notes)
- [IssuesβΌ π π΅](#issues---)
- [Run Phases](#run-phases)
## 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](https://www.discogs.com/settings/developers).
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
```lang-text
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`](https://pypi.org/project/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`](https://pypi.org/project/pipx/) program
pipx run coverlovin2
See script [execution-modes](./tools/execution-modes.sh).
## Development
### First development session
Clone the repository:
git clone git@github.com: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](./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](./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](https://github.com/jtmoon79/goto_http_redirect_server/blob/master/tools/build-install-steps.md).
## Other Miscellaneous Notes
coverlovin2 requires Python version 3.7 or greater.
coverlovin2 is inspired by [coverlovin](https://github.com/amorphic/coverlovin).
coverlovin2 is a practice project for sake of the author catching up to changes
in the Python Universe and the github Universe.<br/>
Some things the author explored:
- project badges (are fun _and useful_)!
- online services
- CI Services
- <img height="10" width="10" src="https://api.iconify.design/simple-icons/travisci.svg?color=yellow"/> [Travis CI](https://travis-ci.com/jtmoon79/coverlovin2)
- <img height="10" width="10" src="https://api.iconify.design/simple-icons/circleci.svg?color=white"/> [Circle CI](https://circleci.com/gh/jtmoon79/coverlovin2)
- <img height="10" width="10" src="https://api.iconify.design/simple-icons/codecov.svg?color=red"/> [codecov.io](https://codecov.io/gh/jtmoon79/coverlovin2)
- [Requires.io](https://requires.io/github/jtmoon79/coverlovin2)
- βΉ landscape.io ([had too many problems](https://github.com/landscapeio/landscape-issues/issues))
- <img height="10" width="10" src="https://api.iconify.design/simple-icons/pypi.svg?color=yellow"/> package distribution service [pypi](https://pypi.org/project/CoverLovin2/)
- <img height="10" width="10" src="https://api.iconify.design/simple-icons/pytest.svg?color=yellow"/> [pytests](./coverlovin2/test)!
- pytest [code coverage](https://pypi.org/project/pytest-cov/)!
- Rudimentary OAuth 1.0a authentication.
- type-hintingβΌ<br/>
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](https://github.com/python/mypy/issues/6476)? βΉ)
- 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](https://github.com/pypa/pipenv/issues/3505)
π [pypa/pipenv #3521](https://github.com/pypa/pipenv/issues/3521)
π [pypa/pipenv #3523](https://github.com/pypa/pipenv/issues/3523)
π [pypa/pipenv #3529](https://github.com/pypa/pipenv/issues/3529)
π [pypa/pipenv #3573](https://github.com/pypa/pipenv/issues/3573)
π [pypa/pipenv #4906](https://github.com/pypa/pipenv/issues/4906)
π [python/mypy #6476](https://github.com/python/mypy/issues/6476)
π [python/mypy #6473](https://github.com/python/mypy/issues/6473)
π [ant-druha/PowerShell #16](https://github.com/ant-druha/PowerShell/issues/16)
### 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`](./coverlovin2/app.py)).
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`](./coverlovin2/app.py))
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`.
<br/>
----
<a href="https://stackexchange.com/users/216253/"><img src="https://stackexchange.com/users/flair/216253.png" width="208" height="58" alt="profile for @JamesThomasMoon on Stack Exchange, a network of free, community-driven Q&A sites" title="profile for @JamesThomasMoon on Stack Exchange, a network of free, community-driven Q&A sites" /></a>
Raw data
{
"_id": null,
"home_page": "https://github.com/jtmoon79/coverlovin2",
"name": "CoverLovin2",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "audio image music",
"author": "James Thomas Moon",
"author_email": "",
"download_url": "",
"platform": null,
"description": "<!-- README.md -->\r\n\r\n# CoverLovin2 <!-- omit in toc -->\r\n\r\n[![Build Status](https://img.shields.io/travis/com/jtmoon79/coverlovin2.svg?branch=master&style=flat-square&logo=travis)](https://app.travis-ci.com/github/jtmoon79/coverlovin2/)\r\n[![CircleCI](https://img.shields.io/circleci/build/gh/jtmoon79/coverlovin2.svg?logo=circleci&style=flat-square)](https://circleci.com/gh/jtmoon79/coverlovin2)\r\n[![codecov.io code coverage](https://img.shields.io/codecov/c/github/jtmoon79/coverlovin2/branch?main&token=Q2OXTL7U02&style=flat-square&logo=codecov)](https://codecov.io/gh/jtmoon79/coverlovin2)\r\n[![coveralls code coverage](https://img.shields.io/coveralls/github/jtmoon79/coverlovin2/branch?main&token=Q2OXTL7U02&style=flat-square&logo=coveralls)](https://coveralls.io/github/jtmoon79/coverlovin2)\r\n[![PyPi version](https://img.shields.io/pypi/v/coverlovin2.svg?longCache=True&logo=pypi&color=blue&style=flat-square)](https://pypi.org/pypi/coverlovin2/)\r\n[![PyPi Python versions](https://img.shields.io/pypi/pyversions/coverlovin2.svg?longCache=True&logo=pypi&style=flat-square)](https://pypi.org/pypi/coverlovin2/)\r\n[![Commits since](https://img.shields.io/github/commits-since/jtmoon79/coverlovin2/latest.svg?color=yellow&style=flat-square)](https://img.shields.io/github/commits-since/jtmoon79/coverlovin2/latest.svg)\r\n[![License](https://img.shields.io/pypi/l/coverlovin2?style=flat-square)](https://opensource.org/licenses/Apache-2.0)\r\n\r\n*CoverLovin2* (Cover Loving, too!), Python name *coverlovin2*, is a Python\r\nscript for downloading album cover art images, either via local searching and\r\ncopying, or via downloading from various online services.\r\nA common use-case is creating \"`cover.jpg`\" files for a large collection of\r\nripped Compact Disc albums.\r\n\r\n----\r\n\r\n<!-- TOC updated by VS Code extention Markdown All In One -->\r\n- [Script Usage](#script-usage)\r\n - [Quickstart](#quickstart)\r\n - [Recommended use](#recommended-use)\r\n - [`--help`](#--help)\r\n - [Common Media Player expectations](#common-media-player-expectations)\r\n- [Installation](#installation)\r\n- [Invocation](#invocation)\r\n- [Development](#development)\r\n - [First development session](#first-development-session)\r\n - [Using `pipenv`](#using-pipenv)\r\n - [Using `pip`](#using-pip)\r\n - [Subsequent development sessions](#subsequent-development-sessions)\r\n - [Using `pipenv`](#using-pipenv-1)\r\n - [pipenv](#pipenv)\r\n - [pipenv update](#pipenv-update)\r\n - [Using `pip`](#using-pip-1)\r\n - [pytest](#pytest)\r\n - [build](#build)\r\n - [new release](#new-release)\r\n- [Other Miscellaneous Notes](#other-miscellaneous-notes)\r\n - [Issues\u203c \ud83d\udc1b \ud83d\udc35](#issues---)\r\n - [Run Phases](#run-phases)\r\n\r\n## Script Usage\r\n\r\n### Quickstart\r\n\r\nTo see what it will do without changing any files\r\n\r\n coverlovin2 -s- --test /path/to/music/library\r\n\r\n### Recommended use\r\n\r\n1. Get your own [Discogs Personal Access Token](https://www.discogs.com/settings/developers).\r\n2. Install coverlovin2\r\n\r\n python -m pip install coverlovin2\r\n\r\n3. Run once with the better searches (skip Google CSE; too complicated)\r\n\r\n coverlovin2 -d -sl -se -sm \\\r\n -sd -dt \"DISCOGS PERSONAL ACCESS TOKEN\" \\\r\n /path/to/music/library\r\n\r\n The prior will write `cover.jpg` files to each found Artist-Album directory.\r\n\r\n4. Run again to copy the previously downloaded `cover.jpg` to `folder.jpg`.\r\n\r\n coverlovin2 -d -n \"folder\" -sl /path/to/music/library\r\n\r\n### `--help`\r\n\r\nThe verbose `--help` message\r\n\r\n```lang-text\r\nusage: app.py [-h] [-n IMAGE_NAME] [-i {jpg,png,gif}]\r\n [-o] [-s*] [-s-] [-sl] [-se] [-sm]\r\n [-sg] [-sgz {small,medium,large}] [--sgid GID] [--sgkey GKEY]\r\n [-sd] [-dt DISCOGS_TOKEN] [-v] [-r REFERER] [-d] [--test]\r\n DIRS [DIRS ...]\r\n\r\nThis Python-based program is for automating downloading album cover art images.\r\nA common use-case is creating a \"cover.jpg\" file for a collection of ripped\r\nCompact Disc albums.\r\n\r\nGiven a list of directories, DIRS, recursively identify \"album\" directories.\r\n\"Album\" directories have audio files, e.g. files with extensions like .mp3 or\r\n.flac. For each \"album\" directory, attempt to determine the Artist and Album.\r\nThen find an album cover image file using the requested --search providers. If\r\nan album cover image file is found then write it to IMAGE_NAME.IMAGE_TYPE within\r\neach \"album\" directory.\r\n\r\nAudio files supported are .mp3, .m4a, .mp4, .flac, .ogg, .wma, .asf.\r\n\r\noptional arguments:\r\n -h, --help show this help message and exit\r\n\r\nRequired Arguments:\r\n DIRS directories to scan for audio files (Required)\r\n\r\nRecommended:\r\n -n IMAGE_NAME, --image-name IMAGE_NAME\r\n 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\r\n image TYPE, e.g. \"jpg\", \"png\", etc. (default: \"cover\")\r\n -i {jpg,png,gif}, --image-type {jpg,png,gif}\r\n image format IMAGE_TYPE (default: \"jpg\")\r\n -o, --overwrite overwrite any previous file of the same file IMAGE_NAME and IMAGE_TYPE (default: False)\r\n\r\nSearch all:\r\n -s*, --search-all Search for album cover images using all methods and services\r\n -s-, --search-all-no-init\r\n Search for album cover images using all methods and services that do not require user initialization (e.g. no Google CSE, no Discogs).\r\n\r\nSearch the local directory for likely album cover images:\r\n -sl, --search-likely-cover\r\n For any directory with audio media files but no file \"IMAGE_NAME.IMAGE_TYPE\", search the directory for files that are likely album cover\r\n images. For example, given options: --name \"cover\" --type \"jpg\", and a directory of .mp3 files with a file \"album.jpg\", it is reasonable to\r\n 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\r\n download and could be a more reliable way to retrieve the correct album cover image.\r\n\r\nSearch the local directory for an embedded album cover image:\r\n -se, --search-embedded\r\n Search audio media files for embedded images. If found, attempt to extract the embedded image.\r\n\r\nSearch Musicbrainz NGS webservice:\r\n -sm, --search-musicbrainz\r\n Search for album cover images using musicbrainz NGS webservice. MusicBrainz lookup is the most reliable web search method.\r\n\r\nSearch Google Custom Search Engine (CSE):\r\n -sg, --search-googlecse\r\n Search for album cover images using Google CSE. Using the Google CSE requires an Engine ID and API Key. Google CSE reliability entirely\r\n 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\r\n cumbersome search method.\r\n -sgz {small,medium,large}, --sgsize {small,medium,large}\r\n Google CSE optional image file size (default: \"large\")\r\n --sgid GID Google CSE ID (URL parameter \"cx\") typically looks like \"009494817879853929660:efj39xwwkng\". REQUIRED to use Google CSE.\r\n --sgkey GKEY Google CSE API Key (URL parameter \"key\") typically looks like \"KVEIA49cnkwoaaKZKGX_OSIxhatybxc9kd59Dst\". REQUIRED to use Google CSE.\r\n\r\nSearch Discogs webservice:\r\n -sd, --search-discogs\r\n Search for album cover images using Discogs webservice.\r\n -dt DISCOGS_TOKEN, --discogs-token DISCOGS_TOKEN\r\n Discogs authentication Personal Access Token.\r\n\r\nDebugging and Miscellanea:\r\n -v, --version show program's version number and exit\r\n -r REFERER, --referer REFERER\r\n Referer url used in HTTP GET requests (default: \"https://github.com/jtmoon79/coverlovin2\")\r\n -d, --debug Print debugging messages. May be passed twice.\r\n --test Only test, do not write any files\r\n\r\nThis program attempts to create album cover image files for the passed DIRS. It\r\ndoes this several ways, searching for album cover image files already present in\r\nthe directory (-sl). If not found, it attempts to figure out the Artist and\r\nAlbum for that directory then searches online services for an album cover image\r\n(-sm or -sg).\r\n\r\nDirectories are searched recursively. Any directory that contains one or more\r\nwith file name extension .mp3 or .m4a or .mp4 or .flac or .ogg or .wma or .asf\r\nis presumed to be an album directory. Given a directory of such files, file\r\ncontents will be read for the Artist name and Album name using embedded audio\r\ntags (ID3, Windows Media, etc.). If no embedded media tags are present then a\r\nreasonable guess will be made about the Artist and Album based on the directory\r\nname; specifically this will try to match a directory name with a pattern like\r\n\"Artist - Year - Album\" or \"Artist - Album\".\r\nFrom there, online search services are used to search for the required album\r\ncover image. If found, it is written to the album directory to file name\r\nIMAGE_NAME.IMAGE_TYPE (-n \u2026 -i \u2026).\r\n\r\nIf option --search-googlecse is chosen then you must create your Google Custom\r\nSearch Engine (CSE). This can be setup at https://cse.google.com/cse/all . It\r\ntakes about 5 minutes. This is where your own values for --sgid and --sgkey can\r\nbe created. --sgid is \"Search engine ID\" (URI parameter \"cx\") and --sgkey is\r\nunder the \"Custom Search JSON API\" from which you can generate an API Key (URI\r\nparameter \"key\"). A key can be generated at\r\nhttps://console.developers.google.com/apis/credentials.\r\nGoogle CSE settings must have \"Image search\" as \"ON\" and \"Search the entire\r\nweb\" as \"OFF\".\r\n\r\nIf option --search-discogs is chosen then you must pass a Discogs Personal\r\nAccess Token (PAT). A PAT is a forty character string generated at\r\nhttps://www.discogs.com/settings/developers with the button \"Generate new token\".\r\nRequires a discogs account.\r\nDiscogs does rate-limit throttling which this program will wait on. It significantly\r\nincreases the time to search for candidate album cover images.\r\n\r\nShortcomings:\r\n\r\n- Does not handle Various Artist albums.\r\n\r\n- --search-discogs can only retrieve jpg file no matter the --image-type passed.\r\n\r\n- Multi-threading is only a rudimentary implementation. Does not efficiently queue\r\n non-overlapping tasks, i.e. the artist-album directory search phase must entirely\r\n finish before the album cover search phase begins, e.g. will not do HTTP searches\r\n as soon as possible.\r\n\r\nPyPi project: https://pypi.org/project/CoverLovin2/\r\nSource code: https://github.com/jtmoon79/coverlovin2\r\n\r\nInspired by the program coverlovin.\r\n```\r\n\r\n### Common Media Player expectations\r\n\r\n_Sonos_ systems will use file `folder.jpg`.\r\n\r\n_Windows Media Player_ will use file `folder.jpg` if media-embedded images are not available.\r\n\r\n_VLC Media Player_ will use file `folder.jpg` if media-embedded images are not available.\r\n\r\n_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.\r\n\r\n_Winamp_ will use file `cover.png` or `cover.jpg` if media-embedded images are not available.\r\n\r\n_One Commander_ will use file `cover.jpg`, `folder.jpg`, `front.jpg`, or `background.jpg`.\r\n\r\n## Installation\r\n\r\n- Using `pip` from pypi:\r\n\r\n python -m pip install coverlovin2\r\n\r\n- Using `pip` from source:\r\n\r\n python -m pip install -e \"git+https://github.com/jtmoon79/coverlovin2.git@master#egg=CoverLovin2\"\r\n\r\n## Invocation\r\n\r\nThere are few ways to run coverlovin2.\r\n\r\nAs a module\r\n\r\n python -m coverlovin2 --version\r\n\r\nAs a standalone program\r\n\r\n coverlovin2 --version\r\n\r\nAs a [`pip-run`](https://pypi.org/project/pip-run/) program\r\n\r\n pip-run coverlovin2 -- -m coverlovin2 --version\r\n\r\nor\r\n\r\n pip-run --use-pep517 --quiet \\\r\n \"git+https://github.com/jtmoon79/coverlovin2\" \\\r\n -- -m coverlovin2 --version\r\n\r\nAs a [`pipx`](https://pypi.org/project/pipx/) program\r\n\r\n pipx run coverlovin2\r\n\r\nSee script [execution-modes](./tools/execution-modes.sh).\r\n\r\n## Development\r\n\r\n### First development session\r\n\r\nClone the repository:\r\n\r\n git clone git@github.com:jtmoon79/coverlovin2.git\r\n\r\n#### Using `pipenv`\r\n\r\nInstall `pipenv`.\r\n\r\nStart the Python virtual environment and install the dependencies:\r\n\r\n cd coverlovin2\r\n pipenv --python 3.9 shell\r\n pipenv install --dev\r\n\r\nSee the [Pipfile](./Pipfile).\r\n\r\n#### Using `pip`\r\n\r\nInstall `pip` and `virtualenv`.\r\n\r\nCreate a virtual environment and install the dependencies:\r\n\r\n cd coverlovin2\r\n python -m virtualenv --copies .venv\r\n .venv/Scripts/activate.ps1\r\n python -m pip install --upgrade pip wheel setuptools\r\n python -m pip install -e \".[dev]\"\r\n\r\nSee the [setup.py](./setup.py).\r\n\r\n### Subsequent development sessions\r\n\r\n#### Using `pipenv`\r\n\r\n##### pipenv\r\n\r\nStart the `pipenv` shell (bash)\r\n\r\n ./tools/pipenv-shell.sh\r\n\r\n(Powershell)\r\n\r\n .\\tools\\pipenv-shell.ps1\r\n\r\n##### pipenv update\r\n\r\nUpdate `Pipfile.lock` with the latest libraries\r\n\r\n1. force upgrade within pip virtual environment\r\n\r\n python -m pip install --upgrade \\\r\n attrs \\\r\n discogs-client \\\r\n musicbrainzngs \\\r\n mutagen \\\r\n Pillow \\\r\n tabulate\r\n\r\n The listing of packages should follow those found in `Pipfile`.\r\n\r\n2. run pytests (they must pass)\r\n\r\n python -m pip install pytest pytest-dependency\r\n python -m pytest ./coverlovin2\r\n\r\n3. manually note versions installed\r\n\r\n python -m pip list -v\r\n\r\n4. tweak versions in `Pipfile` and `setup.py` the with `pip list` versions\r\n\r\n5. update `Pipfile.lock`\r\n\r\n python -m pipenv update\r\n\r\n6. commit changes\r\n\r\n git add Pipfile.lock Pipfile setup.py\r\n git commit -v -m \"pipenv update\"\r\n\r\n`pipenv update` succeeds more often when run under Windows.\r\n\r\n#### Using `pip`\r\n\r\n python -m pip install --upgrade -e \".[dev]\"\r\n\r\n#### pytest\r\n\r\nIf pytests can run then the development environment is ready.\r\n\r\nRun `pytest` tests (bash)\r\n\r\n ./tools/pytest-run.sh\r\n\r\nor (Powershell)\r\n\r\n .\\tools\\pytest-run.ps1\r\n\r\n#### build\r\n\r\n python setup.py bdist_wheel\r\n\r\nor use the helper script\r\n\r\n ./tools/build-install-test.sh\r\n\r\n#### new release\r\n\r\nSee [Create A New Release](https://github.com/jtmoon79/goto_http_redirect_server/blob/master/tools/build-install-steps.md).\r\n\r\n## Other Miscellaneous Notes\r\n\r\ncoverlovin2 requires Python version 3.7 or greater.\r\n\r\ncoverlovin2 is inspired by [coverlovin](https://github.com/amorphic/coverlovin).\r\n\r\ncoverlovin2 is a practice project for sake of the author catching up to changes\r\nin the Python Universe and the github Universe.<br/>\r\nSome things the author explored:\r\n\r\n- project badges (are fun _and useful_)!\r\n- online services\r\n - CI Services\r\n - <img height=\"10\" width=\"10\" src=\"https://api.iconify.design/simple-icons/travisci.svg?color=yellow\"/> [Travis CI](https://travis-ci.com/jtmoon79/coverlovin2)\r\n - <img height=\"10\" width=\"10\" src=\"https://api.iconify.design/simple-icons/circleci.svg?color=white\"/> [Circle CI](https://circleci.com/gh/jtmoon79/coverlovin2)\r\n - <img height=\"10\" width=\"10\" src=\"https://api.iconify.design/simple-icons/codecov.svg?color=red\"/> [codecov.io](https://codecov.io/gh/jtmoon79/coverlovin2)\r\n - [Requires.io](https://requires.io/github/jtmoon79/coverlovin2)\r\n - \u2639 landscape.io ([had too many problems](https://github.com/landscapeio/landscape-issues/issues))\r\n - <img height=\"10\" width=\"10\" src=\"https://api.iconify.design/simple-icons/pypi.svg?color=yellow\"/> package distribution service [pypi](https://pypi.org/project/CoverLovin2/)\r\n- <img height=\"10\" width=\"10\" src=\"https://api.iconify.design/simple-icons/pytest.svg?color=yellow\"/> [pytests](./coverlovin2/test)!\r\n - pytest [code coverage](https://pypi.org/project/pytest-cov/)!\r\n- Rudimentary OAuth 1.0a authentication.\r\n- type-hinting\u203c<br/>\r\ncoverlovin2 is very type-hinted code and could be even more so. The author\r\nthinks type-hinting is a good idea but it still needs improvement. In it's\r\ncurrent form in Python 3.7, it feels clumsy to write and to grok. Also, PyCharm\r\nand mypy seem to catch different type-hint warnings.\r\n - mypy (and [bugs](https://github.com/python/mypy/issues/6476)? \u2639)\r\n- Python 3.7 classes and programming (like `SimpleQueue` and `namedtuple`)\r\n - virtual environment manager `pipenv`.\r\n- printing odd UTF-8 characters (for example, `\\uFF5B`, `\uff5b`) and coercing UTF8\r\nmode (within a context without UTF8 support; MinGW bash on Windows)\r\n\r\n### Issues\u203c \ud83d\udc1b \ud83d\udc35\r\n\r\nOther projects Bug Issues \ud83d\udc1b and Feature Issues \ud83d\udc35 the author created in the\r\ncourse of writing this application:\r\n\r\n\ud83d\udc35 [pypa/pipenv #3505](https://github.com/pypa/pipenv/issues/3505)\r\n\r\n\ud83d\udc1b [pypa/pipenv #3521](https://github.com/pypa/pipenv/issues/3521)\r\n\r\n\ud83d\udc1b [pypa/pipenv #3523](https://github.com/pypa/pipenv/issues/3523)\r\n\r\n\ud83d\udc1b [pypa/pipenv #3529](https://github.com/pypa/pipenv/issues/3529)\r\n\r\n\ud83d\udc1b [pypa/pipenv #3573](https://github.com/pypa/pipenv/issues/3573)\r\n\r\n\ud83d\udc1b [pypa/pipenv #4906](https://github.com/pypa/pipenv/issues/4906)\r\n\r\n\ud83d\udc1b [python/mypy #6476](https://github.com/python/mypy/issues/6476)\r\n\r\n\ud83d\udc1b [python/mypy #6473](https://github.com/python/mypy/issues/6473)\r\n\r\n\ud83d\udc1b [ant-druha/PowerShell #16](https://github.com/ant-druha/PowerShell/issues/16)\r\n\r\n### Run Phases\r\n\r\ncoverlovin2 runs in a few phases:\r\n\r\n1. recursively search passed directory paths for \"album\" directories. An \"album\"\r\ndirectory merely holds audio files of type `.mp3`, `.m4a`, `.mp4`, `.flac`,\r\n`.ogg`, `.wma`, or `.asf`. (see [`coverlovin2/app.py::AUDIO_TYPES`](./coverlovin2/app.py)).\r\n2. employ a few techniques for determining the artist and album for that\r\ndirectory. The most reliable technique is to read available embedded audio tags\r\nwithin the directory. (see [`coverlovin2/app.py::process_dir`](./coverlovin2/app.py))\r\n3. using user-passed search options, search for the album cover art image file.\r\n4. if album cover art is found, create that image file into the \"album\"\r\ndirectory. The name and type of image (`.jpg`, `.png`, `.gif`) is based on\r\nuser-passed options for the `IMAGE_NAME` and `IMAGE_TYPE`.\r\n\r\n<br/>\r\n\r\n----\r\n\r\n<a href=\"https://stackexchange.com/users/216253/\"><img src=\"https://stackexchange.com/users/flair/216253.png\" width=\"208\" height=\"58\" alt=\"profile for @JamesThomasMoon on Stack Exchange, a network of free, community-driven Q&A sites\" title=\"profile for @JamesThomasMoon on Stack Exchange, a network of free, community-driven Q&A sites\" /></a>\r\n",
"bugtrack_url": null,
"license": "Apache License 2.0 (Apache-2.0)",
"summary": "Download music album cover art for a music collection.",
"version": "0.7.5",
"project_urls": {
"Bug Reports": "https://github.com/jtmoon79/coverlovin2/issues",
"Homepage": "https://github.com/jtmoon79/coverlovin2",
"Source": "https://github.com/jtmoon79/coverlovin2"
},
"split_keywords": [
"audio",
"image",
"music"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ba5104a51659213313829988ee44ebc602193acf88d771f076df24a54a516ef3",
"md5": "dc2e5481eb7885c067d720df6da0887e",
"sha256": "f5bb4475dcee933050edb6bbd52cb96edee3b8db447bcd6d2f27e6e5222997cb"
},
"downloads": -1,
"filename": "CoverLovin2-0.7.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "dc2e5481eb7885c067d720df6da0887e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 41833,
"upload_time": "2023-11-19T07:26:28",
"upload_time_iso_8601": "2023-11-19T07:26:28.721407Z",
"url": "https://files.pythonhosted.org/packages/ba/51/04a51659213313829988ee44ebc602193acf88d771f076df24a54a516ef3/CoverLovin2-0.7.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-19 07:26:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jtmoon79",
"github_project": "coverlovin2",
"travis_ci": true,
"coveralls": true,
"github_actions": false,
"circle": true,
"lcname": "coverlovin2"
}