Support fetching cover art images from the Cover Art Archive

Add option `--cover-art` to `whipper cd rip` command which accepts three values:
- `file`: save the downloaded cover image as standalone file in the rip folder (named `cover.jpg`)
- `embed`: embed the download cover image into all the ripped audio tracks (no standalone file will be kept)
- `complete`: save standalone cover image as standalone file and embed it into all the ripped audio tracks (`file` + `embed`)

Every cover art is fetched from the Cover Art Archive as JPEG thumbnail with a maximum dimension of 500px.
Other supported values for the thumbnails are 250, 500 and 1200 (currently only some images have a corresponding 1200px sized thumbnail).

This feature introduces an optional dependency on the `Pillow` module which is required for the decoding of the cover file (required by the `embed` and `complete` option values).

Problem:
- EmbedPicTureTask shouldn't be a task.

Signed-off-by: ABCbum <kimlong221002@gmail.com>
Co-authored-by: JoeLametta <JoeLametta@users.noreply.github.com>
Signed-off-by: JoeLametta <JoeLametta@users.noreply.github.com>
This commit is contained in:
ABCbum
2019-12-23 23:03:49 +07:00
committed by JoeLametta
parent 150f0d5e91
commit f61214a238
4 changed files with 135 additions and 6 deletions

View File

@@ -27,6 +27,7 @@ import re
import os
import time
from tempfile import NamedTemporaryFile
from whipper.common import accurip, cache, checksum, common, mbngs, path
from whipper.program import cdrdao, cdparanoia
from whipper.image import image
@@ -470,6 +471,35 @@ class Program:
stop = track.getIndex(1).absolute - 1
return start, stop
def getCoverArt(self, path, release_id):
"""
Get cover art image from Cover Art Archive.
:param path: where to store the fetched image
:type path: str
:param release_id: a release id (self.program.metadata.mbid)
:type release_id: str
:returns: path to the downloaded cover art, else `None`
:rtype: str or None
"""
cover_art_path = os.path.join(path, 'cover.jpg')
logger.debug('fetching cover art for release: %r', release_id)
try:
data = musicbrainzngs.get_image_front(release_id, 500)
except musicbrainzngs.ResponseError as e:
logger.error('error fetching cover art: %r', e)
return
if data:
with NamedTemporaryFile(suffix='.cover.jpg', delete=False) as f:
f.write(data)
os.chmod(f.name, 0o644)
os.replace(f.name, cover_art_path)
logger.debug('cover art fetched at: %r', cover_art_path)
return cover_art_path
return
@staticmethod
def verifyTrack(runner, trackResult):
is_wave = not trackResult.filename.endswith('.flac')
@@ -490,7 +520,7 @@ class Program:
return ret
def ripTrack(self, runner, trackResult, offset, device, taglist,
overread, what=None):
overread, what=None, coverArtPath=None):
"""
Ripping the track may change the track's filename as stored in
trackResult.
@@ -516,7 +546,8 @@ class Program:
offset=offset,
device=device,
taglist=taglist,
what=what)
what=what,
coverArtPath=coverArtPath)
runner.run(t)