add vnd.tidal.bts support

This commit is contained in:
oskvr37
2024-07-27 17:15:30 +02:00
parent 7e8cc24ab7
commit 9bdbad75cd
3 changed files with 48 additions and 14 deletions
+14 -9
View File
@@ -61,18 +61,23 @@ def main():
MASTER_QUALITIES: list[TrackQuality] = ["HI_RES_LOSSLESS", "LOSSLESS"]
if track["audioQuality"] in MASTER_QUALITIES:
print("▶️ {0} quality - {1} bit, {2:.1f} kHz"
.format(TRACK_QUALITY[track['audioQuality']]['name'],
track['bitDepth'],
track['sampleRate'] / 1000))
print(
"▶️ {0} quality - {1} bit, {2:.1f} kHz".format(
TRACK_QUALITY[track["audioQuality"]]["name"],
track["bitDepth"],
track["sampleRate"] / 1000,
)
)
else:
print(f"▶️ {TRACK_QUALITY[track['audioQuality']]['name']}")
if track["manifestMimeType"] == "application/dash+xml":
track_path = downloadTrack(config["settings"]["download_path"], track_id, track["manifest"])
print(f"✨ Track saved in {track_path}")
else:
print(f"🚨 Mime type `{track["manifestMimeType"]}` not supported yet")
track_path = downloadTrack(
config["settings"]["download_path"],
track_id,
track["manifest"],
track["manifestMimeType"],
)
print(f"✨ Track saved in {track_path}")
if __name__ == "__main__":
+30 -4
View File
@@ -1,14 +1,29 @@
import requests
import json
from os import makedirs
from xml.etree.ElementTree import fromstring
from base64 import b64decode
from typing import TypedDict, List
from .types import ManifestMimeType
def decodeManifest(manifest: str):
return b64decode(manifest).decode()
def parseTrackManifest(xml_content: str):
def parseManifest(manifest: str):
class AudioFileInfo(TypedDict):
mimeType: str
codecs: str
encryptionType: str
urls: List[str]
data: AudioFileInfo = json.loads(manifest)
return data
def parseManifestXML(xml_content: str):
"""
Parses XML manifest file of the track.
"""
@@ -61,9 +76,20 @@ def threadDownload(urls: list[str]) -> bytes:
return data
def downloadTrack(path: str, file_name: str, manifest: str):
decoded_manifest = decodeManifest(manifest)
track_urls, codecs = parseTrackManifest(decoded_manifest)
def downloadTrack(
path: str, file_name: str, encoded_manifest: str, mime_type: ManifestMimeType
):
manifest = decodeManifest(encoded_manifest)
match mime_type:
case "application/dash+xml":
track_urls, codecs = parseManifestXML(manifest)
case "application/vnd.tidal.bts":
data = parseManifest(manifest)
track_urls, codecs = data["urls"], data["codecs"]
case _:
raise ValueError(f"Unknown `mime_type`: {mime_type}")
track_data = threadDownload(track_urls)
makedirs(path, exist_ok=True)
+4 -1
View File
@@ -115,12 +115,15 @@ class PlaylistResponse(TypedDict):
items: List[PlaylistItem]
ManifestMimeType = Literal["application/dash+xml", "application/vnd.tidal.bts"]
class TrackResponse(TypedDict):
trackId: int
assetPresentation: Literal["FULL"]
audioMode: Literal["STEREO"]
audioQuality: TrackQuality
manifestMimeType: Literal["application/dash+xml", "application/vnd.tidal.bts"]
manifestMimeType: ManifestMimeType
manifestHash: str
manifest: str
albumReplayGain: float