From a968a1a33a77d121e004035bc749d4b5cce66be2 Mon Sep 17 00:00:00 2001 From: uh wot Date: Wed, 12 Jul 2023 01:15:35 +0200 Subject: [PATCH 1/3] added hires flac support, rewrote session selection entirely --- interface.py | 59 ++++++++++++++++++++++++++++++++++++++-------------- tidal_api.py | 2 +- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/interface.py b/interface.py index 7ade841..f96c010 100644 --- a/interface.py +++ b/interface.py @@ -23,7 +23,7 @@ module_information = ModuleInformation( global_settings={ 'tv_token': '7m7Ap0JC9j1cOM3n', 'tv_secret': 'vRAdA108tlvkJpTsGZS8rGZ7xTlbJ0qaZ2K9saEzsgY=', - 'mobile_atmos_token': 'dN2N95wCyEBTllu4', + 'mobile_atmos_token': 'km8T1xS355y7dd3H', 'mobile_default_token': 'WAU9gXp3tHhK4Nns', 'enable_mobile': True, 'force_non_spatial': False, @@ -424,26 +424,52 @@ class ModuleInterface: # add the region locked album to the cache in order to properly use it later (force_album_format) self.album_cache = {album_id: album_data} - # check if album is only available in LOSSLESS and STEREO, so it switches to the MOBILE_DEFAULT which will - # get FLACs faster, instead of using MPEG-DASH - # lmao what did I smoke when I wrote this, track_data and not album_data! - if (self.settings['force_non_spatial'] or ( - (quality_tier is QualityEnum.LOSSLESS or track_data.get('audioQuality') == 'LOSSLESS') - and track_data.get('audioModes') == ['STEREO'])) and ( - SessionType.MOBILE_DEFAULT.name in self.available_sessions): - self.session.default = SessionType.MOBILE_DEFAULT - elif (track_data.get('audioModes') == ['SONY_360RA'] - or ('DOLBY_ATMOS' in track_data.get('audioModes') and self.settings['prefer_ac4'])) \ - and SessionType.MOBILE_ATMOS.name in self.available_sessions: - self.session.default = SessionType.MOBILE_ATMOS + # MOBILE_DEFAULT is used whenever possible to avoid MPEG-DASH, which slows downloading + session = SessionType.MOBILE_DEFAULT + hires_flac = False + media_tags = track_data['mediaMetadata']['tags'] + + if quality_tier is QualityEnum.HIFI: + format = None + + if 'HIRES_LOSSLESS' in media_tags: + format = 'flac_hires' + + if 'SONY_360RA' in media_tags and not format and not self.settings['force_non_spacial']: + format = '360ra' + + if 'DOLBY_ATMOS' in media_tags and not format and not self.settings['force_non_spacial']: + if self.settings['prefer_ac4']: + format = 'ac4' + else: + format = 'ac3' + + session = { + 'flac_hires': SessionType.MOBILE_ATMOS, + '360ra': SessionType.MOBILE_ATMOS, + 'ac4': SessionType.MOBILE_ATMOS, + 'ac3': SessionType.TV, + None: SessionType.MOBILE_DEFAULT, + }[format] + + if format == 'flac_hires': + hires_flac = True + elif 'SONY_360RA' in media_tags: + # if 360RA is available, we don't use the mobile session here because that will get 360RA + # there are no tracks with both 360RA and atmos afaik, + # so this shouldn't be an issue for now + session = SessionType.TV + + if session.name in self.available_sessions: + self.session.default = session else: - self.session.default = SessionType.TV + hires_flac = False # define all default values in case the stream_data is None (region locked) audio_track, mqa_file, track_codec, bitrate, download_args, error = None, None, CodecEnum.FLAC, None, None, None try: - stream_data = self.session.get_stream_url(track_id, self.quality_parse[quality_tier]) + stream_data = self.session.get_stream_url(track_id, self.quality_parse[quality_tier] if not hires_flac else 'HI_RES_LOSSLESS') except TidalRequestError as e: error = e # definitely region locked @@ -498,7 +524,8 @@ class ModuleInterface: 'LOW': 96, 'HIGH': 320, 'LOSSLESS': 1411, - 'HI_RES': None + 'HI_RES': None, + 'HI_RES_LOSSLESS': None }[stream_data['audioQuality']] # manually set bitrate for immersive formats diff --git a/tidal_api.py b/tidal_api.py index 9a3ef04..ab8fc9a 100644 --- a/tidal_api.py +++ b/tidal_api.py @@ -110,7 +110,7 @@ class TidalApi(object): return resp_json def get_stream_url(self, track_id, quality): - return self._get('tracks/' + str(track_id) + '/playbackinfopostpaywall', { + return self._get('tracks/' + str(track_id) + '/playbackinfopostpaywall/v4', { 'playbackmode': 'STREAM', 'assetpresentation': 'FULL', 'audioquality': quality, From d19583413affe6e0befd7f122c6fa03d23a4c89f Mon Sep 17 00:00:00 2001 From: uh wot Date: Wed, 12 Jul 2023 02:14:22 +0200 Subject: [PATCH 2/3] moved spatial formats out of hifi quality since there's a goddamn option for it already god i shouldn't be doing this at 2am --- interface.py | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/interface.py b/interface.py index f96c010..7cf1dc3 100644 --- a/interface.py +++ b/interface.py @@ -424,37 +424,28 @@ class ModuleInterface: # add the region locked album to the cache in order to properly use it later (force_album_format) self.album_cache = {album_id: album_data} - # MOBILE_DEFAULT is used whenever possible to avoid MPEG-DASH, which slows downloading - session = SessionType.MOBILE_DEFAULT - hires_flac = False media_tags = track_data['mediaMetadata']['tags'] + format = None + if 'HIRES_LOSSLESS' in media_tags and quality_tier is QualityEnum.HIFI: + format = 'flac_hires' + if 'SONY_360RA' in media_tags and not format and not self.settings['force_non_spatial']: + format = '360ra' + if 'DOLBY_ATMOS' in media_tags and not format and not self.settings['force_non_spatial']: + if self.settings['prefer_ac4']: + format = 'ac4' + else: + format = 'ac3' - if quality_tier is QualityEnum.HIFI: - format = None + session = { + 'flac_hires': SessionType.MOBILE_ATMOS, + '360ra': SessionType.MOBILE_ATMOS, + 'ac4': SessionType.MOBILE_ATMOS, + 'ac3': SessionType.TV, + # MOBILE_DEFAULT is used whenever possible to avoid MPEG-DASH, which slows downloading + None: SessionType.MOBILE_DEFAULT, + }[format] - if 'HIRES_LOSSLESS' in media_tags: - format = 'flac_hires' - - if 'SONY_360RA' in media_tags and not format and not self.settings['force_non_spacial']: - format = '360ra' - - if 'DOLBY_ATMOS' in media_tags and not format and not self.settings['force_non_spacial']: - if self.settings['prefer_ac4']: - format = 'ac4' - else: - format = 'ac3' - - session = { - 'flac_hires': SessionType.MOBILE_ATMOS, - '360ra': SessionType.MOBILE_ATMOS, - 'ac4': SessionType.MOBILE_ATMOS, - 'ac3': SessionType.TV, - None: SessionType.MOBILE_DEFAULT, - }[format] - - if format == 'flac_hires': - hires_flac = True - elif 'SONY_360RA' in media_tags: + if not format and 'SONY_360RA' in media_tags: # if 360RA is available, we don't use the mobile session here because that will get 360RA # there are no tracks with both 360RA and atmos afaik, # so this shouldn't be an issue for now @@ -463,13 +454,13 @@ class ModuleInterface: if session.name in self.available_sessions: self.session.default = session else: - hires_flac = False + format = None # define all default values in case the stream_data is None (region locked) audio_track, mqa_file, track_codec, bitrate, download_args, error = None, None, CodecEnum.FLAC, None, None, None try: - stream_data = self.session.get_stream_url(track_id, self.quality_parse[quality_tier] if not hires_flac else 'HI_RES_LOSSLESS') + stream_data = self.session.get_stream_url(track_id, self.quality_parse[quality_tier] if format != 'flac_hires' else 'HI_RES_LOSSLESS') except TidalRequestError as e: error = e # definitely region locked From 50ce6dbf619d8c6d3929765af7b1510e00d2adfd Mon Sep 17 00:00:00 2001 From: uh wot Date: Wed, 12 Jul 2023 02:59:01 +0200 Subject: [PATCH 3/3] fixed bit depth and sample rate info on hires flacs --- interface.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface.py b/interface.py index 7cf1dc3..f806ba3 100644 --- a/interface.py +++ b/interface.py @@ -506,7 +506,8 @@ class ModuleInterface: download_args = {'file_url': manifest['urls'][0]} # https://en.wikipedia.org/wiki/Audio_bit_depth#cite_ref-1 - bit_depth = 16 if track_codec in {CodecEnum.FLAC, CodecEnum.ALAC} else None + bit_depth = (24 if stream_data and stream_data['audioQuality'] == 'HI_RES_LOSSLESS' else 16) \ + if track_codec in {CodecEnum.FLAC, CodecEnum.ALAC} else None sample_rate = 48 if track_codec in {CodecEnum.EAC3, CodecEnum.MHA1, CodecEnum.AC4} else 44.1 if stream_data: @@ -532,6 +533,8 @@ class ModuleInterface: # more precise bitrate tidal uses MPEG-DASH if audio_track: bitrate = audio_track.bitrate // 1000 + if stream_data['audioQuality'] == 'HI_RES_LOSSLESS': + sample_rate = audio_track.sample_rate / 1000 # now set everything for MQA if mqa_file is not None and mqa_file.is_mqa: