Fix issues with converting single tracks

This commit is contained in:
nathom 2021-04-19 13:25:49 -07:00
parent 86d877f1f5
commit 383159d5f4
5 changed files with 68 additions and 33 deletions

View file

@ -83,13 +83,9 @@ class Track:
self.id = None self.id = None
self.__dict__.update(kwargs) self.__dict__.update(kwargs)
# TODO: remove these
self.container = "FLAC"
self.sampling_rate = 44100
self.bit_depth = 16
self.downloaded = False self.downloaded = False
self.tagged = False self.tagged = False
self.converted = False
# TODO: find better solution # TODO: find better solution
for attr in ("quality", "folder", "meta"): for attr in ("quality", "folder", "meta"):
setattr(self, attr, None) setattr(self, attr, None)
@ -440,24 +436,37 @@ class Track:
if album_meta is not None: if album_meta is not None:
self.meta.add_album_meta(album_meta) # extend meta with album info self.meta.add_album_meta(album_meta) # extend meta with album info
if self.quality in (2, 3, 4): # TODO: make this cleaner
self.container = "FLAC" if self.converted:
logger.debug("Tagging file with %s container", self.container) if self.container == 'FLAC':
audio = FLAC(self.path) audio = FLAC(self.path)
elif self.quality <= 1: elif self.container in ("AAC", "ALAC", "MP4"):
if self.client.source == "tidal":
self.container = "AAC"
audio = MP4(self.path) audio = MP4(self.path)
else: elif self.container == 'MP3':
self.container = "MP3" audio = ID3()
try: try:
audio = ID3(self.path) audio = ID3(self.path)
except ID3NoHeaderError: except ID3NoHeaderError:
audio = ID3() audio = ID3()
logger.debug("Tagging file with %s container", self.container)
else: 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 # automatically generate key, value pairs based on container
tags = self.meta.tags(self.container) tags = self.meta.tags(self.container)
@ -467,7 +476,7 @@ class Track:
if embed_cover and cover is None: if embed_cover and cover is None:
assert hasattr(self, "cover_path") assert hasattr(self, "cover_path")
cover = Tracklist.get_cover_obj( 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): if isinstance(audio, FLAC):
@ -547,6 +556,8 @@ class Track:
if not kwargs.get("stay_temp", False): if not kwargs.get("stay_temp", False):
self.move(self.final_path) self.move(self.final_path)
self.converted = True
@property @property
def title(self) -> str: def title(self) -> str:
"""The title of the track. """The title of the track.
@ -848,7 +859,7 @@ class Tracklist(list):
@staticmethod @staticmethod
def get_cover_obj( def get_cover_obj(
cover_path: str, quality: int, source: str cover_path: str, container: str, source: str
) -> Union[Picture, APIC]: ) -> Union[Picture, APIC]:
"""Given the path to an image and a quality id, return an initialized """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. cover object that can be used for every track in the album.
@ -869,12 +880,14 @@ class Tracklist(list):
return cover_obj return cover_obj
if quality > 1: if container == 'FLAC':
cover = Picture cover = Picture
elif source == "tidal": elif container == 'MP3':
cover = APIC
elif container in ('AAC', 'ALAC', 'MP4'):
cover = MP4Cover cover = MP4Cover
else: else:
cover = APIC raise Exception(container)
if cover is Picture: if cover is Picture:
size_ = os.path.getsize(cover_path) size_ = os.path.getsize(cover_path)
@ -891,8 +904,6 @@ class Tracklist(list):
with open(cover_path, "rb") as img: with open(cover_path, "rb") as img:
return cover(img.read(), imageformat=MP4Cover.FORMAT_JPEG) return cover(img.read(), imageformat=MP4Cover.FORMAT_JPEG)
raise InvalidQuality(f"Quality {quality} not allowed")
def download_message(self) -> str: def download_message(self) -> str:
"""The message to display after calling `Tracklist.download`. """The message to display after calling `Tracklist.download`.

View file

@ -143,6 +143,9 @@ def filter_discography(ctx, **kwargs):
def search(ctx, **kwargs): def search(ctx, **kwargs):
"""Search and download media in interactive mode. """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: Example usage:
$ rip search 'fleetwood mac rumours' $ rip search 'fleetwood mac rumours'

View file

@ -186,6 +186,8 @@ class MusicDL(list):
item.download(**arguments) item.download(**arguments)
if isinstance(item, Track): if isinstance(item, Track):
item.tag() item.tag()
if arguments['conversion']['enabled']:
item.convert(**arguments['conversion'])
if self.db != [] and hasattr(item, "id"): if self.db != [] and hasattr(item, "id"):
self.db.add(item.id) self.db.add(item.id)

View file

@ -18,7 +18,7 @@ from .constants import ALBUM_KEYS, FLAC_MAX_BLOCKSIZE, FOLDER_FORMAT
from .db import MusicDB from .db import MusicDB
from .exceptions import InvalidSourceError, NonStreamable from .exceptions import InvalidSourceError, NonStreamable
from .metadata import TrackMetadata 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__) logger = logging.getLogger(__name__)
@ -132,8 +132,9 @@ class Album(Tracklist):
embed_cover = kwargs.get("embed_cover", True) # embed by default embed_cover = kwargs.get("embed_cover", True) # embed by default
if self.client.source != "deezer" and embed_cover: if self.client.source != "deezer" and embed_cover:
# container generated when formatting folder name
self.cover_obj = self.get_cover_obj( self.cover_obj = self.get_cover_obj(
cover_path, self.quality, self.client.source cover_path, self.container, self.client.source
) )
else: else:
self.cover_obj = None self.cover_obj = None
@ -220,14 +221,11 @@ class Album(Tracklist):
return fmt return fmt
def _get_formatted_folder(self, parent_folder: str, quality: int) -> str: def _get_formatted_folder(self, parent_folder: str, quality: int) -> str:
if quality >= 2: # necessary to format the folder
self.container = "FLAC" self.container = get_container(quality, self.client.source)
else: if self.container in ('AAC', 'MP3'):
# lossy codecs don't have these metrics
self.bit_depth = self.sampling_rate = None 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()) formatted_folder = clean_format(self.folder_format, self._get_formatter())

View file

@ -277,3 +277,24 @@ def extract_interpreter_url(url: str) -> str:
r = session.get(url) r = session.get(url)
artist_id = re.search(r"getSimilarArtist\(\s*'(\w+)'", r.text).group(1) artist_id = re.search(r"getSimilarArtist\(\s*'(\w+)'", r.text).group(1)
return artist_id 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