Improved MQA detection

- Downloads the first 163824 bytes and check for MQA
- Now properly downloads the file as any other track
- Already existing track check working
This commit is contained in:
Dniel97
2022-02-03 15:50:16 +01:00
parent cece36e41d
commit 54ef06f84c
3 changed files with 37 additions and 25 deletions

View File

@@ -151,8 +151,7 @@ file in order to get properly detected.
[@purpl3F0x](https://github.com/purpl3F0x) and [mqaid](https://github.com/redsudo/mqaid) by
[@redsudo](https://github.com/redsudo).**
**NOTE: `fix_mqa` is experimental! May not detect already existing tracks,
slower as normal download and could be not working at all**
**NOTE: `fix_mqa` is enabled which is experimental! May be slower as normal download and could not be working at all**
<!-- Contact -->
## Contact

View File

@@ -12,7 +12,7 @@ import ffmpeg
from tqdm import tqdm
from utils.models import *
from utils.utils import sanitise_name, silentremove, download_to_temp, create_temp_filename
from utils.utils import sanitise_name, silentremove, download_to_temp, create_temp_filename, create_requests_session
from .mqa_identifier_python.mqa_identifier import MqaIdentifier
from .tidal_api import TidalTvSession, TidalApi, SessionStorage, TidalMobileSession, SessionType
@@ -357,21 +357,16 @@ class ModuleInterface:
else:
# check if MQA
if track_codec is CodecEnum.MQA and self.settings['fix_mqa']:
self.print(f'"fix_mqa" is enabled which is experimental! May not detect already existing tracks, '
f'slower as normal download and could be not working at all', drop_level=1)
self.print(f'=== Downloading MQA {track_name} ({track_id}) ===', drop_level=1)
indent_level = self.oprinter.indent_number - self.oprinter.multiplier
# download the file to analyze it
temp_file_path = download_to_temp(manifest['urls'][0], enable_progress_bar=True,
indent_level=indent_level)
download_args = {'temp_file_path': temp_file_path}
self.print(f'"fix_mqa" is enabled which is experimental! May be slower as normal download and could '
f'not be working at all', drop_level=1)
# download the first chunk of the flac file to analyze it
temp_file_path = self.download_temp_header(manifest['urls'][0])
# detect MQA file
mqa_file = MqaIdentifier(temp_file_path)
self.print(f'=== MQA {track_id} downloaded ===', drop_level=1)
else:
download_args = {'file_url': manifest['urls'][0]}
# add the file to download_args
download_args = {'file_url': manifest['urls'][0]}
bit_depth = 24 if track_codec in [CodecEnum.EAC3, CodecEnum.MHA1] else 16
sample_rate = 48 if track_codec in [CodecEnum.EAC3, CodecEnum.MHA1, CodecEnum.AC4] else 44.1
@@ -405,6 +400,24 @@ class ModuleInterface:
return track_info
@staticmethod
def download_temp_header(file_url: str, chunk_size: int = 16384) -> str:
# create flac temp_location
temp_location = create_temp_filename() + '.flac'
# create session and download the file to the temp_location
r_session = create_requests_session()
r = r_session.get(file_url, stream=True, verify=False)
with open(temp_location, 'wb') as f:
# only download the first chunk_size bytes
for chunk in r.iter_content(chunk_size=chunk_size):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
break
return temp_location
@staticmethod
def parse_mpd(xml: bytes) -> list:
xml = xml.decode('UTF-8')
@@ -466,17 +479,13 @@ class ModuleInterface:
return tracks
def get_track_download(self, file_url: str = None, temp_file_path: str = None, audio_track: AudioTrack = None) \
def get_track_download(self, file_url: str = None, audio_track: AudioTrack = None) \
-> TrackDownloadInfo:
# only file_url, temp_file_path or audio_track at a time, with file_url > temp_file_path
# only file_url or audio_track at a time
# MHA1 or EC-3
# MHA1, EC-3 or MQA
if file_url:
return TrackDownloadInfo(download_type=DownloadEnum.URL, file_url=file_url)
# MQA file with enabled "fix_mqa"
if temp_file_path:
return TrackDownloadInfo(download_type=DownloadEnum.TEMP_FILE_PATH, temp_file_path=temp_file_path)
# MPEG-DASH
# use the total_file size for a better progress bar? Is it even possible to calculate the total size from MPD?

View File

@@ -58,7 +58,7 @@ MAGIC = 51007556744 # int.from_bytes(bytes.fromhex('0be0498c88'), 'big') jesus
class MqaIdentifier:
def __init__(self, flac_file_path: Path):
def __init__(self, flac_file_path: str or Path):
self.is_mqa = False
self.is_mqa_studio = False
self.original_sample_rate = None
@@ -76,7 +76,7 @@ class MqaIdentifier:
return int(sample_rate)
return sample_rate
def _decode_flac_samples(self, flac_file_path) -> list:
def _decode_flac_samples(self, flac_file_path: str or Path) -> list:
"""
Decodes a 16/24bit flac file to a samples list
@@ -89,7 +89,11 @@ class MqaIdentifier:
if magic == b'fLaC':
with flac.BitInputStream(f) as bf:
f = io.BytesIO()
flac.decode_file(bf, f, seconds=1)
# ignore EOFError
try:
flac.decode_file(bf, f, seconds=1)
except EOFError:
pass
f.seek(0)
with wave.open(f) as wf:
@@ -108,7 +112,7 @@ class MqaIdentifier:
return list(iter_data(wf.readframes(framerate)))
def detect(self, flac_file_path) -> bool:
def detect(self, flac_file_path: str or Path) -> bool:
"""
Detects if the FLAC file is a MQA file and also detects if it's MQA Studio (blue) and the originalSampleRate