Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grab cover art from MusicBrainz/Cover Art Archive and add it to the resulting whipper rips #436

Merged
merged 3 commits into from
Jan 14, 2020

Conversation

ABCbum
Copy link
Contributor

@ABCbum ABCbum commented Dec 23, 2019

Submitted as a part of GCI competition

Description
Fixes: #50

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 using musicbrainzngs.
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).

Problems

  • EmbedPicTureTask shouldn't be a task.
  • The test checks only getCoverArt's functionality (embedding isn't tested)

@MerlijnWajer
Copy link
Collaborator

Here's a thought: should an error fetching the cover art be fatal or not? Also - let's make sure it's an optional feature.

@ABCbum
Copy link
Contributor Author

ABCbum commented Dec 23, 2019

Alright, i'm just testing before bed :DD . Thank for your early suggestions.

Also i think it shouldn't be fatal.

@ABCbum ABCbum marked this pull request as ready for review December 24, 2019 10:43
@q3cpma
Copy link

q3cpma commented Dec 26, 2019

Isn't it possible to import conditionally? It seems strange to bloat the mandatory dependencies for an optional feature.

@ABCbum
Copy link
Contributor Author

ABCbum commented Dec 27, 2019

Isn't it possible to import conditionally? It seems strange to bloat the mandatory dependencies for an optional feature.

Hi @q3cpma , I don't really get what you mean right now but maybe i should move from PIL import Image to where it is used ?.

@q3cpma
Copy link

q3cpma commented Dec 27, 2019 via email

@ABCbum
Copy link
Contributor Author

ABCbum commented Dec 27, 2019

Yeah i think thats a good point, just move the import statement down to the _make_flac_picture should solve the problem for the time being if you dont use it but i will try to find an alternative way. Thanks a lot, @q3cpma .

@JoeLametta
Copy link
Collaborator

Fixed conflicts and squashed.

@ABCbum
Copy link
Contributor Author

ABCbum commented Dec 28, 2019

@JoeLametta , thanks for doing that for me ;)

@JoeLametta
Copy link
Collaborator

JoeLametta commented Dec 28, 2019

@ABCbum I think @q3cpma means that as this one (grabbing cover art) is not a primary feature of whipper, it should be possible to install and use whipper without the new dependency (pillow).
Maybe you can leave the menu command entry as it is but handle the case in which the module is missing, report it (example: optional dependency needed for bla, bla, bla), etc.

try:
    from PIL import Image
except ImportError as e:
    logger.warning("bla, bla", e)
    ...

@ABCbum
Copy link
Contributor Author

ABCbum commented Dec 28, 2019

@JoeLametta , i think that's a great idea but how about requirements.txt, README.md and dockerfile ?

We can solve README.md my simply adding (optional) next to pillow. But what about the other two ? Should we remove pillow or not ?

@JoeLametta
Copy link
Collaborator

JoeLametta commented Dec 28, 2019

  • requirements / setup.py: maybe this (or we can create an optional-requirements.txt file where all optional, pip installable, dependencies will go).
  • README.md: just list it is as an optional dependency
  • Dockerfile: always install it (maybe you can use the python3-pil apt package instead)

@ABCbum
Copy link
Contributor Author

ABCbum commented Dec 28, 2019

I'm not sure if what i did in this commit correct tho, @JoeLametta .

whipper/command/cd.py Outdated Show resolved Hide resolved
@JoeLametta
Copy link
Collaborator

JoeLametta commented Dec 29, 2019

I'm not sure if what i did in this commit correct tho, @JoeLametta .

This is not enough but I'm also not sure which is the best way to handle this. @Freso do you have any advice about this?

@JoeLametta
Copy link
Collaborator

@ABCbum General comment: return == return None.

@Freso
Copy link
Member

Freso commented Dec 30, 2019

The "best"/canonical way of specifying optional dependencies is to specify them as "extras" in setup.py, see https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies

whipper/command/cd.py Outdated Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
@JoeLametta
Copy link
Collaborator

Small changes + history rewritten to be easier to understand.

@JoeLametta
Copy link
Collaborator

@ABCbum could you add a test case?

requirements.txt Outdated Show resolved Hide resolved
whipper/command/cd.py Show resolved Hide resolved
whipper/command/cd.py Show resolved Hide resolved
whipper/command/cd.py Show resolved Hide resolved
whipper/command/cd.py Show resolved Hide resolved
whipper/command/cd.py Outdated Show resolved Hide resolved
whipper/command/cd.py Outdated Show resolved Hide resolved
whipper/command/cd.py Show resolved Hide resolved
whipper/common/encode.py Show resolved Hide resolved
whipper/common/program.py Outdated Show resolved Hide resolved
@JoeLametta JoeLametta force-pushed the grab-cover-art branch 2 times, most recently from d4080a6 to 9b2e5f7 Compare January 3, 2020 17:16
@ABCbum
Copy link
Contributor Author

ABCbum commented Jan 3, 2020

@ABCbum could you add a test case?

I have added a "draft" test case i'm not sure if it's an okay one.

@JoeLametta JoeLametta force-pushed the grab-cover-art branch 4 times, most recently from 410042c to b9be520 Compare January 6, 2020 09:24
@JoeLametta
Copy link
Collaborator

JoeLametta commented Jan 9, 2020

I have added a "draft" test case i'm not sure if it's an okay one.

If you want to test whether the embedding works too I've attached this FLAC file (the extension is ZIP because GitHub doesn't allow attaching FLAC files directly, just rename it). The file content is just 1s of silence (stereo, 44100 Hz) with the test image embedded as front cover. 😉

@JoeLametta
Copy link
Collaborator

JoeLametta commented Jan 10, 2020

@ABCbum Same file without attached cover: test_1s_silence_stereo_no_cover.flac.zip

I have generated the source wave file with the following code:

import wave

with wave.open('test.wav', 'wb') as f:
    duration = 1  # duration in seconds
    nchannels = 2  # Set to 1 for mono
    sampwidth = 2  # 16 bit
    framerate = 44100  # CD sample rate
    f.setnchannels(nchannels)
    f.setsampwidth(sampwidth)
    f.setframerate(framerate)
    f.setnframes(framerate * duration)
    f.writeframes(b'\x00' * nchannels * sampwidth * framerate * duration)

@ABCbum
Copy link
Contributor Author

ABCbum commented Jan 11, 2020

I have added a "draft" test case i'm not sure if it's an okay one.

If you want to test whether the embedding works too I've attached this FLAC file (the extension is ZIP because GitHub doesn't allow attaching FLAC files directly, just rename it). The file content is just 1s of silence (stereo, 44100 Hz) with the test image embedded as front cover. 😉

Yeah it works locally to me :D not sure if i should write a test case for that.

@JoeLametta JoeLametta force-pushed the grab-cover-art branch 3 times, most recently from d5ab69a to 93b3f0f Compare January 14, 2020 15:55
ABCbum and others added 3 commits January 14, 2020 15:57
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>
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>
Mock two functions `getCoverArt`, `get_image_front` and use
a locally available cover art to check if the created cover
art exists.

Problems:
- How to check image's quality.
- Not sure if only this check is enough (do we need to check the
embedding part?).

Signed-off-by: ABCbum <kimlong221002@gmail.com>
@JoeLametta JoeLametta merged commit 9e37219 into whipper-team:develop Jan 14, 2020
@JoeLametta
Copy link
Collaborator

Merged, thanks!

@@ -290,6 +291,14 @@ def add_arguments(self):
help="whether to continue ripping if "
"the disc is a CD-R",
default=False)
self.parser.add_argument('-C', '--cover-art',
action="store", dest="fetch_cover_art",
help="Fetch cover art and save it as "
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
help="Fetch cover art and save it as "
help="fetch cover art and save it as "

I just noticed a small detail that this shouldn't be capital just to be consistent 😉.

JoeLametta added a commit that referenced this pull request Jan 28, 2020
Reported by user "ABCbum" in comment (#436 (comment)).

Signed-off-by: JoeLametta <JoeLametta@users.noreply.github.com>
@mores
Copy link

mores commented Dec 22, 2020

Lets say someone already issued:
whipper cd rip
<repeat 100 times>

Now they want to go back and '--cover-art complete' without re-ripping. Can you just patch existing files with just artwork ?

or is beet fetchart the way to go ?

@JoeLametta
Copy link
Collaborator

Now they want to go back and '--cover-art complete' without re-ripping. Can you just patch existing files with just artwork ?

That's not possible with the current implementation and I would say that's out of scope for whipper and best left to a specialized tool (musical tagger).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Grab cover art
6 participants