diff --git a/README.md b/README.md index e99e34f..bee918e 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,12 @@ following settings. By default no transcoding is done. +* **`albumart_maxwidth`** Downscale the embedded album art to a width + of maximum `albumart_maxwidth` pixels. The aspect ratio of the image + will be preserved. This is comparable to the setting with the same + name of the [convert plugin][convert plugin]. + + * **`removable`** If this is `true` (the default) and `directory` does not exist, the `update` command will ask you to confirm the creation of the external collection. (optional) diff --git a/beetsplug/alternatives.py b/beetsplug/alternatives.py index 6b1fdec..85ef97c 100644 --- a/beetsplug/alternatives.py +++ b/beetsplug/alternatives.py @@ -181,6 +181,7 @@ def parse_config(self, config: confuse.ConfigView): self.query, _ = parse_query_string(query, Item) self.removable = config.get(dict).get("removable", True) # type: ignore + self.album_art_maxwidth = config.get(dict).get("album_art_maxwidth", None) # type: ignore if "directory" in config: dir = config["directory"].as_path() @@ -342,7 +343,14 @@ def _sync_art(self, item: Item, path: Path): album = item.get_album() if album and album.artpath and Path(str(album.artpath, "utf8")).is_file(): self._log.debug(f"Embedding art from {album.artpath} into {path}") - art.embed_item(self._log, item, album.artpath, itempath=bytes(path)) + + art.embed_item( + self._log, + item, + album.artpath, + maxwidth=self.album_art_maxwidth, + itempath=bytes(path), + ) class ExternalConvert(External): diff --git a/test/cli_test.py b/test/cli_test.py index bfe1bac..4673128 100644 --- a/test/cli_test.py +++ b/test/cli_test.py @@ -8,6 +8,7 @@ import pytest from beets.library import Item from beets.ui import UserError +from beets.util.artresizer import ArtResizer from confuse import ConfigValueError from mediafile import MediaFile @@ -348,6 +349,8 @@ def test_embed_art(self, tmp_path: Path): This test comprehensively checks that embedded artwork is up-to-date with the artwork file, even if no changes to the database happen. + + It also tests if the album_art_maxwidth is applied """ def touch_art(item: Item, image_path: Path): @@ -363,7 +366,8 @@ def touch_art(item: Item, image_path: Path): item_mtime_alt = Path(str(item.path, "utf8")).stat().st_mtime os.utime(image_path, (item_mtime_alt + 2, item_mtime_alt + 2)) - # Initially add album without artwork. + # Initially add album without artwork. Do not do resizing + self.config["alternatives"]["myexternal"]["album_art_maxwidth"] = None album = self.add_album(myexternal="true") album.store() self.runcli("alt", "update", "myexternal") @@ -373,7 +377,7 @@ def touch_art(item: Item, image_path: Path): # Make a copy of the artwork, so that changing mtime/content won't # affect the repository. - image_path = tmp_path / "image" + image_path = tmp_path / "image.png" shutil.copy(self.IMAGE_FIXTURE1, image_path) touch_art(item, image_path) @@ -395,6 +399,24 @@ def touch_art(item: Item, image_path: Path): item = album.items().get() assert_has_embedded_artwork(self.get_path(item), self.IMAGE_FIXTURE2) + # now set a maxwidth and verify the final image has the right + # dimensions + touch_art(item, image_path) + self.config["alternatives"]["myexternal"]["album_art_maxwidth"] = 1 + self.runcli("alt", "update", "myexternal") + mediafile = MediaFile(self.get_path(item)) + tmp_embedded_image = tmp_path / "embedded_image.png" + with open(tmp_embedded_image, "wb") as binary_file: + binary_file.write(mediafile.art) + art_resizer = ArtResizer() + (width, height) = art_resizer.get_size(bytes(tmp_embedded_image)) + assert width == 1 + + # reset + self.config["alternatives"]["myexternal"]["album_art_maxwidth"] = None + + + def test_update_all(self, tmp_path: Path): dir_a = tmp_path / "a" dir_a.mkdir()