mirror of
https://github.com/oskvr37/tiddl.git
synced 2026-06-13 04:05:08 +03:00
✨ add vnd.tidal.bts support
This commit is contained in:
+14
-9
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user