From 383159d5f4594a4ccb85127f0700fd2614720edb Mon Sep 17 00:00:00 2001 From: nathom Date: Mon, 19 Apr 2021 13:25:49 -0700 Subject: [PATCH] Fix issues with converting single tracks --- streamrip/bases.py | 59 ++++++++++++++++++++++++----------------- streamrip/cli.py | 3 +++ streamrip/core.py | 2 ++ streamrip/downloader.py | 16 +++++------ streamrip/utils.py | 21 +++++++++++++++ 5 files changed, 68 insertions(+), 33 deletions(-) diff --git a/streamrip/bases.py b/streamrip/bases.py index 5f70b26..71545d2 100644 --- a/streamrip/bases.py +++ b/streamrip/bases.py @@ -83,13 +83,9 @@ class Track: self.id = None self.__dict__.update(kwargs) - # TODO: remove these - self.container = "FLAC" - self.sampling_rate = 44100 - self.bit_depth = 16 - self.downloaded = False self.tagged = False + self.converted = False # TODO: find better solution for attr in ("quality", "folder", "meta"): setattr(self, attr, None) @@ -440,24 +436,37 @@ class Track: if album_meta is not None: self.meta.add_album_meta(album_meta) # extend meta with album info - if self.quality in (2, 3, 4): - self.container = "FLAC" - logger.debug("Tagging file with %s container", self.container) - audio = FLAC(self.path) - elif self.quality <= 1: - if self.client.source == "tidal": - self.container = "AAC" + # TODO: make this cleaner + if self.converted: + if self.container == 'FLAC': + audio = FLAC(self.path) + elif self.container in ("AAC", "ALAC", "MP4"): audio = MP4(self.path) - else: - self.container = "MP3" + elif self.container == 'MP3': + audio = ID3() try: audio = ID3(self.path) except ID3NoHeaderError: audio = ID3() - - logger.debug("Tagging file with %s container", self.container) else: - raise InvalidQuality(f'Invalid quality: "{self.quality}"') + if self.quality in (2, 3, 4): + self.container = "FLAC" + logger.debug("Tagging file with %s container", self.container) + audio = FLAC(self.path) + elif self.quality <= 1: + if self.client.source == "tidal": + self.container = "AAC" + audio = MP4(self.path) + else: + self.container = "MP3" + try: + audio = ID3(self.path) + except ID3NoHeaderError: + audio = ID3() + + logger.debug("Tagging file with %s container", self.container) + else: + raise InvalidQuality(f'Invalid quality: "{self.quality}"') # automatically generate key, value pairs based on container tags = self.meta.tags(self.container) @@ -467,7 +476,7 @@ class Track: if embed_cover and cover is None: assert hasattr(self, "cover_path") cover = Tracklist.get_cover_obj( - self.cover_path, self.quality, self.client.source + self.cover_path, self.container, self.client.source ) if isinstance(audio, FLAC): @@ -547,6 +556,8 @@ class Track: if not kwargs.get("stay_temp", False): self.move(self.final_path) + self.converted = True + @property def title(self) -> str: """The title of the track. @@ -848,7 +859,7 @@ class Tracklist(list): @staticmethod def get_cover_obj( - cover_path: str, quality: int, source: str + cover_path: str, container: str, source: str ) -> Union[Picture, APIC]: """Given the path to an image and a quality id, return an initialized cover object that can be used for every track in the album. @@ -869,12 +880,14 @@ class Tracklist(list): return cover_obj - if quality > 1: + if container == 'FLAC': cover = Picture - elif source == "tidal": + elif container == 'MP3': + cover = APIC + elif container in ('AAC', 'ALAC', 'MP4'): cover = MP4Cover else: - cover = APIC + raise Exception(container) if cover is Picture: size_ = os.path.getsize(cover_path) @@ -891,8 +904,6 @@ class Tracklist(list): with open(cover_path, "rb") as img: return cover(img.read(), imageformat=MP4Cover.FORMAT_JPEG) - raise InvalidQuality(f"Quality {quality} not allowed") - def download_message(self) -> str: """The message to display after calling `Tracklist.download`. diff --git a/streamrip/cli.py b/streamrip/cli.py index 2fffb05..6f3c98e 100644 --- a/streamrip/cli.py +++ b/streamrip/cli.py @@ -143,6 +143,9 @@ def filter_discography(ctx, **kwargs): def search(ctx, **kwargs): """Search and download media in interactive mode. + The QUERY must be surrounded in quotes if it contains spaces. If your query + contains single quotes, use double quotes, and vice versa. + Example usage: $ rip search 'fleetwood mac rumours' diff --git a/streamrip/core.py b/streamrip/core.py index c39c01c..77e8880 100644 --- a/streamrip/core.py +++ b/streamrip/core.py @@ -186,6 +186,8 @@ class MusicDL(list): item.download(**arguments) if isinstance(item, Track): item.tag() + if arguments['conversion']['enabled']: + item.convert(**arguments['conversion']) if self.db != [] and hasattr(item, "id"): self.db.add(item.id) diff --git a/streamrip/downloader.py b/streamrip/downloader.py index c2731c8..b383abc 100644 --- a/streamrip/downloader.py +++ b/streamrip/downloader.py @@ -18,7 +18,7 @@ from .constants import ALBUM_KEYS, FLAC_MAX_BLOCKSIZE, FOLDER_FORMAT from .db import MusicDB from .exceptions import InvalidSourceError, NonStreamable from .metadata import TrackMetadata -from .utils import clean_format, safe_get, tidal_cover_url, tqdm_download +from .utils import clean_format, safe_get, tidal_cover_url, tqdm_download, get_container logger = logging.getLogger(__name__) @@ -132,8 +132,9 @@ class Album(Tracklist): embed_cover = kwargs.get("embed_cover", True) # embed by default if self.client.source != "deezer" and embed_cover: + # container generated when formatting folder name self.cover_obj = self.get_cover_obj( - cover_path, self.quality, self.client.source + cover_path, self.container, self.client.source ) else: self.cover_obj = None @@ -220,14 +221,11 @@ class Album(Tracklist): return fmt def _get_formatted_folder(self, parent_folder: str, quality: int) -> str: - if quality >= 2: - self.container = "FLAC" - else: + # necessary to format the folder + self.container = get_container(quality, self.client.source) + if self.container in ('AAC', 'MP3'): + # lossy codecs don't have these metrics self.bit_depth = self.sampling_rate = None - if self.client.source == "tidal": - self.container = "AAC" - else: - self.container = "MP3" formatted_folder = clean_format(self.folder_format, self._get_formatter()) diff --git a/streamrip/utils.py b/streamrip/utils.py index f95c2af..ab8bb43 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -277,3 +277,24 @@ def extract_interpreter_url(url: str) -> str: r = session.get(url) artist_id = re.search(r"getSimilarArtist\(\s*'(\w+)'", r.text).group(1) return artist_id + + +def get_container(quality: int, source: str) -> str: + """Get the "container" given the quality. `container` can also be the + the codec; both work. + + :param quality: quality id + :type quality: int + :param source: + :type source: str + :rtype: str + """ + if quality >= 2: + container = "FLAC" + else: + if source == "tidal": + container = "AAC" + else: + container = "MP3" + + return container