diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..aff7da5 --- /dev/null +++ b/Brewfile @@ -0,0 +1,87 @@ +tap "helix-editor/helix" +tap "homebrew/bundle" +tap "homebrew/cask" +tap "homebrew/cask-fonts" +tap "homebrew/core" +tap "mczachurski/wallpapper" +tap "teamookla/speedtest" +brew "align" +brew "python@3.9" +brew "awk" +brew "bat" +brew "black" +brew "clang-format" +brew "cling" +brew "diff-so-fancy" +brew "dust" +brew "duti" +brew "fd" +brew "fennel" +brew "unbound" +brew "ffmpeg" +brew "flake8" +brew "fzf" +brew "gcc" +brew "gh" +brew "ghc" +brew "git-delta" +brew "gtk+3" +brew "imagemagick" +brew "ipython", link: false +brew "isort" +brew "kepubify" +brew "less" +brew "librsvg" +brew "llvm" +brew "llvm@11" +brew "luajit" +brew "luarocks" +brew "mypy" +brew "neofetch" +brew "neovim" +brew "node" +brew "nu" +brew "nushell" +brew "ormolu" +brew "prettier" +brew "ptpython", link: false +brew "pydocstyle" +brew "pyenv" +brew "pylint" +brew "pyright" +brew "ripgrep" +brew "rust" +brew "rust-analyzer" +brew "sd" +brew "speedtest-cli" +brew "stow" +brew "the_silver_searcher" +brew "tldr" +brew "tmux" +brew "tokei" +brew "tree" +brew "vim", link: false +brew "helix-editor/helix/helix" +brew "teamookla/speedtest/speedtest" +cask "alacritty" +cask "brave-browser" +cask "discord" +cask "dropbox" +cask "firefox" +cask "font-fira-code-nerd-font" +cask "font-hack-nerd-font" +cask "github" +cask "hammerspoon" +cask "hyper" +cask "iina" +cask "iterm2" +cask "karabiner-elements" +cask "kitty" +cask "macvim" +cask "qobuz" +cask "spotify" +cask "transmission" +cask "typora" +cask "via" +cask "virtualbox" +cask "zoom" diff --git a/streamrip/media.py b/streamrip/media.py index 27cc941..cf597c5 100644 --- a/streamrip/media.py +++ b/streamrip/media.py @@ -134,6 +134,15 @@ class Media(abc.ABC): def downloaded_ids(self, other): pass + @property + @abc.abstractmethod + def id(self): + pass + + @id.setter + def id(self, other): + pass + class Track(Media): """Represents a downloadable track. @@ -207,25 +216,15 @@ class Track(Media): self.meta = TrackMetadata( track=self.resp, source=source ) # meta dict -> TrackMetadata object - try: - if source == "qobuz": - self.cover_url = self.resp["album"]["image"]["large"] - elif source == "tidal": - self.cover_url = tidal_cover_url( - self.resp["album"]["cover"], 320 - ) - elif source == "deezer": - self.cover_url = self.resp["album"]["cover_medium"] - elif source == "soundcloud": - self.cover_url = ( - self.resp["artwork_url"] - or self.resp["user"].get("avatar_url") - ).replace("large", "t500x500") - else: - raise InvalidSourceError(source) - except KeyError: - logger.debug("No cover found") - self.cover_url = None + + # Because the cover urls are not parsed when only the track metadata + # is loaded, we need to do this ourselves + + # Default to large if chosen size is not available + self.cover_url = self.meta.cover_urls.get( + kwargs.get("embed_cover_size", "large"), + self.meta.cover_urls.get("large"), + ) def _prepare_download(self, **kwargs): """Do preprocessing before downloading items. @@ -830,6 +829,7 @@ class Track(Media): class Video(Media): """Only for Tidal.""" + id = None downloaded_ids: set = set() def __init__(self, client: Client, id: str, **kwargs): @@ -961,6 +961,8 @@ class Video(Media): class YoutubeVideo(Media): """Dummy class implemented for consistency with the Media API.""" + id = None + class DummyClient: """Used because YouTube downloads use youtube-dl, not a client.""" @@ -997,6 +999,7 @@ class YoutubeVideo(Media): filename_formatter = "%(track_number)s.%(track)s.%(container)s" filename = os.path.join(parent_folder, filename_formatter) + assert isinstance(self.id, str) p = subprocess.Popen( [ "youtube-dl", @@ -1063,6 +1066,8 @@ class YoutubeVideo(Media): class Booklet: """Only for Qobuz.""" + id = None + def __init__(self, resp: dict): """Initialize from the `goodies` field of the Qobuz API response. @@ -1114,6 +1119,7 @@ class Tracklist(list): the tracklist. """ + id = None # anything not in parentheses or brackets essence_regex = re.compile(r"([^\(]+)(?:\s*[\(\[][^\)][\)\]])*") @@ -1400,7 +1406,7 @@ class Album(Tracklist, Media): """ downloaded_ids: set = set() - id: str + id = None def __init__(self, client: Client, **kwargs): """Create a new Album object. @@ -1487,45 +1493,15 @@ class Album(Tracklist, Media): self.download_message() - # choose optimal cover size and download it - cover_path = os.path.join(gettempdir(), f"cover_{hash(self)}.jpg") - embed_cover_size = kwargs.get("embed_cover_size", "large") - secho(f"Downloading cover art ({embed_cover_size})", bold=True) - - assert ( - embed_cover_size in self.cover_urls - ), f"Invalid cover size. Must be in {self.cover_urls.keys()}" - - embed_cover_url = self.cover_urls[embed_cover_size] - logger.debug("Chosen cover url: %s", embed_cover_url) - if not os.path.exists(cover_path): - if embed_cover_url is None: - embed_cover_url = next(filter(None, self.cover_urls.values())) - - logger.debug("Downloading cover from url %s", embed_cover_url) - - _cover_download(embed_cover_url, cover_path) - - hires_cov_path = os.path.join(self.folder, "cover.jpg") - if kwargs.get("keep_hires_cover", True) and not os.path.exists( - hires_cov_path - ): - logger.debug("Downloading hires cover") - _cover_download(self.cover_urls["original"], hires_cov_path) - - cover_size = os.path.getsize(cover_path) - if cover_size > FLAC_MAX_BLOCKSIZE: # 16.77 MB - secho( - "Downgrading embedded cover size, too large ({cover_size}).", - fg="bright_yellow", - ) - # large is about 600x600px which is guaranteed < 16.7 MB - _cover_download(self.cover_urls["large"], cover_path) - - downsize_image( - cover_path, - kwargs.get("max_artwork_width", 999999), - kwargs.get("max_artwork_height", 999999), + cover_path = _choose_and_download_cover( + self.cover_urls, + kwargs.get("embed_cover_size", "large"), + self.folder, + kwargs.get("keep_hires_cover", True), + ( + kwargs.get("max_artwork_width", 999999), + kwargs.get("max_artwork_height", 999999), + ), ) if kwargs.get("embed_cover", True): # embed by default @@ -1978,6 +1954,7 @@ class Artist(Tracklist, Media): >>> artist.download() """ + id = None downloaded_ids: set = set() def __init__(self, client: Client, **kwargs): @@ -2277,6 +2254,8 @@ class Artist(Tracklist, Media): class Label(Artist): """Represents a downloadable Label.""" + id = None + def load_meta(self, **kwargs): """Load metadata given an id.""" assert self.client.source == "qobuz", "Label source must be qobuz" @@ -2328,3 +2307,51 @@ def _quick_download(url: str, path: str, desc: str = None): def _cover_download(url: str, path: str): _quick_download(url, path, style("Cover", fg="blue")) + + +def _choose_and_download_cover( + cover_urls: dict, + preferred_size: str, + directory: str, + keep_hires_cover: bool = True, + downsize: Tuple[int, int] = (999999, 999999), +) -> str: + # choose optimal cover size and download it + temp_cover_path = os.path.join( + gettempdir(), f"cover_{hash(cover_urls.values())}.jpg" + ) + secho(f"Downloading cover art ({preferred_size})", bold=True) + + assert ( + preferred_size in cover_urls + ), f"Invalid cover size. Must be in {cover_urls.keys()}" + + embed_cover_url = cover_urls[preferred_size] + logger.debug("Chosen cover url: %s", embed_cover_url) + if not os.path.exists(temp_cover_path): + # Sometimes a size isn't available. When this is the case, find + # the first `not None` url. + if embed_cover_url is None: + embed_cover_url = next(filter(None, cover_urls.values())) + + logger.debug("Downloading cover from url %s", embed_cover_url) + + _cover_download(embed_cover_url, temp_cover_path) + + hires_cov_path = os.path.join(directory, "cover.jpg") + if keep_hires_cover and not os.path.exists(hires_cov_path): + logger.debug("Downloading hires cover") + _cover_download(cover_urls["original"], hires_cov_path) + + cover_size = os.path.getsize(temp_cover_path) + if cover_size > FLAC_MAX_BLOCKSIZE: # 16.77 MB + secho( + "Downgrading embedded cover size, too large ({cover_size}).", + fg="bright_yellow", + ) + # large is about 600x600px which is guaranteed < 16.7 MB + _cover_download(cover_urls["large"], temp_cover_path) + + downsize_image(temp_cover_path, *downsize) + + return temp_cover_path diff --git a/streamrip/metadata.py b/streamrip/metadata.py index 1cf5c71..eada572 100644 --- a/streamrip/metadata.py +++ b/streamrip/metadata.py @@ -23,6 +23,7 @@ from .utils import get_cover_urls, get_quality_id, safe_get logger = logging.getLogger("streamrip") +# TODO: remove OrderedDict bc normal dicts are ordered now class TrackMetadata: """Contains all of the metadata needed to tag the file. diff --git a/streamrip/utils.py b/streamrip/utils.py index 2259012..864aa66 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -7,7 +7,6 @@ import functools import hashlib import logging import re -from collections import OrderedDict from string import Formatter from typing import Dict, Hashable, Iterator, Optional, Tuple, Union @@ -463,7 +462,7 @@ def get_container(quality: int, source: str) -> str: return "MP3" -def get_cover_urls(resp: dict, source: str) -> dict: +def get_cover_urls(resp: dict, source: str, is_track: bool = True) -> dict: """Parse a response dict containing cover info according to the source. :param resp: @@ -472,35 +471,42 @@ def get_cover_urls(resp: dict, source: str) -> dict: :type source: str :rtype: dict """ + if source == "qobuz": - cover_urls = OrderedDict(resp["image"]) + cover_urls = resp["image"] cover_urls["original"] = cover_urls["large"].replace("600", "org") return cover_urls if source == "tidal": uuid = resp["cover"] - return OrderedDict( - { - sk: tidal_cover_url(uuid, size) - for sk, size in zip(COVER_SIZES, (160, 320, 640, 1280)) - } - ) + return { + sk: tidal_cover_url(uuid, size) + for sk, size in zip(COVER_SIZES, (160, 320, 640, 1280)) + } if source == "deezer": - cover_urls = OrderedDict( - { - sk: resp.get(rk) # size key, resp key - for sk, rk in zip( - COVER_SIZES, - ("cover", "cover_medium", "cover_large", "cover_xl"), - ) - } - ) + cover_urls = { + sk: resp.get(rk) # size key, resp key + for sk, rk in zip( + COVER_SIZES, + ("cover", "cover_medium", "cover_large", "cover_xl"), + ) + } + if cover_urls["large"] is None and resp.get("cover_big") is not None: cover_urls["large"] = resp["cover_big"] return cover_urls + if source == "soundcloud": + cover_url = ( + resp["artwork_url"] or resp["user"].get("avatar_url") + ).replace("large", "t500x500") + + cover_urls = {"large": cover_url} + + return cover_urls + raise InvalidSourceError(source) @@ -527,6 +533,7 @@ def downsize_image(filepath: str, width: int, height: int): image = Image.open(filepath) except UnidentifiedImageError: secho("Cover art not found, skipping downsize.", fg="red") + return width = min(width, image.width) height = min(height, image.height) diff --git a/test.json b/test.json new file mode 100644 index 0000000..fb5ca68 --- /dev/null +++ b/test.json @@ -0,0 +1,523 @@ +{ + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "product_url": "/fr-fr/album/power-up-ac-dc/lf4lekh9s5v1a", + "media_count": 1, + "product_sales_factors_weekly": 1.2, + "artist": { + "id": 161143, + "name": "AC/DC", + "slug": "ac-dc", + "albums_count": 250, + "picture": null, + "image": null + }, + "genres_list": ["Pop/Rock", "Pop/Rock\u2192Rock"], + "created_at": 1603273677, + "description": "
An AC/DC album always sounds like an AC/DC album! Even if the Australian-British bandmembers are now between 65 and 73 years old, they have no reason to change their formula as its their usual prescription that everybody wants: short, sharp riffs, heavy rock infused with blues, metronomic rhythms, stadium anthems and minimalist, haiku-like lyrics. It could be said that there's a bit of a lyrical revolution going on throughout\u00a0Power Up: for the first time since\u00a0Fly on the Wall\u00a0(1985), none of the twelve tracks contain the word \u2018rock\u2019! Is this a sign? Not really\u2026 Recorded like its three predecessors in Bryan Adams\u2019 Warehouse Studio in Vancouver,\u00a0Power Up\u00a0is AC/DC's first opus since the death of rhythm guitarist Malcom Young in late 2017 (Young had been battling dementia for several months). Already in 2014 for\u00a0Rock or Bust\u00a0illness had kept him away from the recording studio with his nephew Stevie filling in for him. It was only right that his younger brother, the brilliant Angus Young, put this 17th album together as a kind of testament to his older brother. \"I know Mal's not with us anymore, but he's there with us in spirit. This band was his baby, his life. He was always one [to say], 'you keep going'. He always said, 'If you're a musician, it's a bit like being on the Titanic. The band goes down with the ship.'\"
Over the course of their 45-year career, the two brothers had always kept skeletons of song ideas and hoards of guitar riffs. These musical treasure troves were instrumental in the conception of\u00a0Power Up\u00a0which features riffs written by the late Malcom Young. Having already been at the helm of production for\u00a0Black Ice\u00a0(2008) and\u00a0Rock or Bust\u00a0(2014), American producer Brendan O\u2019Brien mixed the perfect sound to match the timelessness of the songs. Rarely have we heard such purity and simplicity from AC/DC since\u00a0Back in Black\u00a0(1980),\u00a0with an added efficiency similar to that of the Bon Scott era, as on the single\u00a0Shot in the Dark. Little to no fat here! Even Brian Johnson holds his mic with more steadiness. Occasionally, the blues spirit of the grandiose\u00a0Powerage\u00a0(1978) floats in the air, as does the fraternal and juvenile energy of\u00a0Highway to Hell\u00a0(1979). It's true that some tracks are only loosely held together by guitar riffs, ignoring fundamental harmony and melody. However, on the excellent\u00a0Through the Mists of Time\u00a0AC/DC really do some exploring, and\u00a0Demon Fire\u00a0makes it difficult to stay in your seat! Even if\u00a0Power Up\u00a0isn't particularly surprising in what it has to offer, you still have the invigorating feeling of having taken a big slap of Rock\u2019n\u2019Roll electricity straight to the face. \u00a9 Marc Zisman/Qobuz
", + "released_at": 1605222000, + "product_sales_factors_monthly": 12.7, + "release_tags": [], + "title": "Power Up", + "duration": 2462, + "parental_warning": false, + "artists": [{ "id": 161143, "name": "AC/DC", "roles": ["artist"] }], + "popularity": 0, + "genre": { + "id": 119, + "color": "#5eabc1", + "name": "Rock", + "path": [112, 119], + "slug": "rock" + }, + "catchline": "", + "id": "lf4lekh9s5v1a", + "slug": "power-up-ac-dc", + "image": { + "large": "https://static.qobuz.com/images/covers/1a/5v/lf4lekh9s5v1a_600.jpg", + "small": "https://static.qobuz.com/images/covers/1a/5v/lf4lekh9s5v1a_230.jpg", + "thumbnail": "https://static.qobuz.com/images/covers/1a/5v/lf4lekh9s5v1a_50.jpg", + "back": null + }, + "article_ids": { + "LLS": 288668122, + "SMR": 288668123, + "SHP": 288668124, + "SM2": 407079186, + "SH2": 407079187 + }, + "composer": { + "id": 573076, + "name": "Various Composers", + "slug": "various-composers", + "albums_count": 583621, + "picture": null, + "image": null + }, + "upc": "0886448802198", + "release_type": "album", + "label": { + "id": 4592, + "name": "Columbia", + "slug": "columbia", + "supplier_id": 23, + "albums_count": 23798 + }, + "product_sales_factors_yearly": 684.4, + "qobuz_id": 104017574, + "version": null, + "url": "https://www.qobuz.com/us-en/album/power-up-ac-dc/lf4lekh9s5v1a", + "maximum_technical_specifications": "24 bits / 96.0 kHz - Stereo", + "relative_url": "/album/power-up-ac-dc/lf4lekh9s5v1a", + "product_type": "album", + "subtitle": "AC/DC", + "tracks_count": 12, + "maximum_channel_count": 2, + "maximum_sampling_rate": 96, + "articles": [ + { + "id": 288668122, + "url": "/order/288668122", + "price": 12.99, + "currency": "USD", + "type": "lls", + "label": "CD-quality", + "description": "Lossless 16 bit/44.1 kHz (FLAC, ALAC, WMA, AIFF, WAV)" + }, + { + "id": 288668123, + "url": "/order/288668123", + "price": 17.49, + "currency": "USD", + "type": "smr", + "label": "Hi-Res", + "description": "Up to 24 bit/96 kHz (FLAC, ALAC, WMA, AIFF, WAV)" + }, + { + "id": 288668124, + "url": "/order/288668124", + "price": 9.99, + "currency": "USD", + "type": "shp", + "label": "Hi-Res (with Sublime)", + "description": "Up to 24 bit/96 kHz (FLAC, ALAC, WMA, AIFF, WAV)" + } + ], + "release_date_original": "2020-11-13", + "release_date_download": "2020-11-13", + "release_date_stream": "2020-11-13", + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true, + "tracks": { + "offset": 0, + "limit": 500, + "total": 12, + "items": [ + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -11.42 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668126, "SMR": 288668127, "SM2": 407079188 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914741", + "title": "Realize", + "version": null, + "duration": 217, + "parental_warning": false, + "track_number": 1, + "maximum_channel_count": 2, + "id": 104017575, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -11.12 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668129, "SMR": 288668130, "SM2": 407079189 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914742", + "title": "Rejection", + "version": null, + "duration": 246, + "parental_warning": false, + "track_number": 2, + "maximum_channel_count": 2, + "id": 104017576, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -10.41 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668132, "SMR": 288668133, "SM2": 407079190 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914743", + "title": "Shot In The Dark", + "version": null, + "duration": 185, + "parental_warning": false, + "track_number": 3, + "maximum_channel_count": 2, + "id": 104017577, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 1, + "replaygain_track_gain": -10.12 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668135, "SMR": 288668136, "SM2": 407079191 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914744", + "title": "Through The Mists Of Time", + "version": null, + "duration": 212, + "parental_warning": false, + "track_number": 4, + "maximum_channel_count": 2, + "id": 104017578, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 1, + "replaygain_track_gain": -9.9 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668138, "SMR": 288668139, "SM2": 407079192 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914745", + "title": "Kick You When You're Down", + "version": null, + "duration": 190, + "parental_warning": false, + "track_number": 5, + "maximum_channel_count": 2, + "id": 104017579, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 1, + "replaygain_track_gain": -10.98 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668141, "SMR": 288668142, "SM2": 407079193 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914746", + "title": "Witch's Spell", + "version": null, + "duration": 222, + "parental_warning": false, + "track_number": 6, + "maximum_channel_count": 2, + "id": 104017580, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 1, + "replaygain_track_gain": -10.34 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668144, "SMR": 288668145, "SM2": 407079194 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914747", + "title": "Demon Fire", + "version": null, + "duration": 210, + "parental_warning": false, + "track_number": 7, + "maximum_channel_count": 2, + "id": 104017581, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -9.35 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668147, "SMR": 288668148, "SM2": 407079195 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914748", + "title": "Wild Reputation", + "version": null, + "duration": 174, + "parental_warning": false, + "track_number": 8, + "maximum_channel_count": 2, + "id": 104017582, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -10.12 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668150, "SMR": 288668151, "SM2": 407079196 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914749", + "title": "No Man's Land", + "version": null, + "duration": 219, + "parental_warning": false, + "track_number": 9, + "maximum_channel_count": 2, + "id": 104017583, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -10.56 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668153, "SMR": 288668154, "SM2": 407079197 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914750", + "title": "Systems Down", + "version": null, + "duration": 192, + "parental_warning": false, + "track_number": 10, + "maximum_channel_count": 2, + "id": 104017584, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 0.999969, + "replaygain_track_gain": -10.46 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668156, "SMR": 288668157, "SM2": 407079198 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914751", + "title": "Money Shot", + "version": null, + "duration": 185, + "parental_warning": false, + "track_number": 11, + "maximum_channel_count": 2, + "id": 104017585, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + }, + { + "maximum_bit_depth": 24, + "copyright": "(P) 2020 Leidseplein Presse, B.V.", + "performers": "Brendan O'Brien, Producer, Mixing Engineer - AC/DC, MainArtist, AssociatedPerformer - Cliff Williams, Bass Guitar - Ryan Smith, Mastering Engineer - Mike Fraser, Engineer, Mixing Engineer - Richard Jones, Misc. Prod. - Angus Young, Composer, Lyricist, Guitar - Malcolm Young, Composer, Lyricist - Brian Johnson, Vocal - Billy Bowers, Misc. Prod. - Zach Blackstone, Assistant Engineer - Kyle Stevens, Assistant Engineer - Phil Rudd, Drums - Stevie Young, Guitar - Trace Foster, Misc. Prod. - Matt Tuggle, Assistant Engineer - Dominick Civiero, Assistant Engineer - Colin Kadlec, Assistant Engineer - Simon Murton, Misc. Prod.", + "audio_info": { + "replaygain_track_peak": 1, + "replaygain_track_gain": -9.62 + }, + "performer": { "name": "AC/DC", "id": 161143 }, + "article_ids": { "LLS": 288668159, "SMR": 288668160, "SM2": 407079199 }, + "work": null, + "composer": { "name": "Angus Young", "id": 40345 }, + "isrc": "USSM11914752", + "title": "Code Red", + "version": null, + "duration": 210, + "parental_warning": false, + "track_number": 12, + "maximum_channel_count": 2, + "id": 104017586, + "media_number": 1, + "maximum_sampling_rate": 96, + "purchasable": true, + "streamable": true, + "previewable": true, + "sampleable": true, + "downloadable": true, + "displayable": true, + "purchasable_at": 1618988400, + "streamable_at": 1618988400, + "hires": true, + "hires_streamable": true + } + ] + }, + "description_language": "en" +} diff --git a/~/.vim/undo/%Users%nathan%streamrip%streamrip%media.py b/~/.vim/undo/%Users%nathan%streamrip%streamrip%media.py new file mode 100644 index 0000000..059dc27 Binary files /dev/null and b/~/.vim/undo/%Users%nathan%streamrip%streamrip%media.py differ