dropcreations / Manzana-Apple-Music-Downloader

A python program to download albums and songs with AAC codec in .m4a container format and music-videos up to 4K in AVC or HEVC codec in .mp4 format from Apple Music.

Home Page:https://music.apple.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How do i install it? How can i test it?

darkne777 opened this issue · comments

I have few samples in my mind for study purposes, but i am unable to install it.
Can anybody assist, tyvm.

@darkne777 There is nothing to install. Use this as a usual python project. but you have to find some stuff to test it and copy ffmpeg.exe to the binaries folder.

python manzana.py [options]

dropcodestudio@gmail.com

I entered the media-user-token manually, but the following error occurs, what should I do next?

    $$$$$$\$$$$\   $$$$$$\  $$$$$$$\  $$$$$$$$\ $$$$$$\  $$$$$$$\   $$$$$$\
    $$  _$$  _$$\  \____$$\ $$  __$$\ \____$$  |\____$$\ $$  __$$\  \____$$\
    $$ / $$ / $$ | $$$$$$$ |$$ |  $$ |  $$$$ _/ $$$$$$$ |$$ |  $$ | $$$$$$$ |
    $$ | $$ | $$ |$$  __$$ |$$ |  $$ | $$  _/  $$  __$$ |$$ |  $$ |$$  __$$ |
    $$ | $$ | $$ |\$$$$$$$ |$$ |  $$ |$$$$$$$$\\$$$$$$$ |$$ |  $$ |\$$$$$$$ |
    \__| \__| \__| \_______|\__|  \__|\________|\_______|\__|  \__| \_______|

                        ──── Apple Music Downloader ────

[23:26:38] [ManzanaCore] INFO: Checking access token found in cache...
[23:26:39] [ManzanaCore] INFO: Checking media-user-token...
[23:26:45] [ManzanaCore] INFO: Fetching api response...
[23:26:45] [ManzanaCore] INFO: Using the previous response found in cache...
[23:26:45] [ManzanaCore] INFO: Downloading album artwork...

     Downloading ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 665.5/665.5 kB 5.8 MB/s eta 0:00:00

[23:26:55] [ManzanaCore] INFO: Getting playback information...
[23:26:58] [ManzanaCore] INFO: Extracting key ID...
[23:26:59] [ManzanaCore] INFO: Getting Service Certificate...
[23:26:59] [ManzanaCore] INFO: Requesting License...
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ D:\Portable Soft\Downloads\Manzana Apple Music Downloader\manzana.py:64 in │
│ │
│ 61 if name == "main": │
│ 62 │ os.system('cls' if os.name == 'nt' else 'clear') │
│ 63 │ console.print(LOGO) │
│ ❱ 64 │ main() │
│ 65 │
│ │
│ D:\Portable Soft\Downloads\Manzana Apple Music Downloader\manzana.py:59 in main │
│ │
│ 56 │ │ type=str │
│ 57 │ ) │
│ 58 │ args = parser.parse_args() │
│ ❱ 59 │ arguments(args) │
│ 60 │
│ 61 if name == "main": │
│ 62 │ os.system('cls' if os.name == 'nt' else 'clear') │
│ │
│ D:\Portable Soft\Downloads\Manzana Apple Music Downloader\handler.py:102 in arguments │
│ │
│ 99 │ │ │ │ │ │ if os.path.exists("_Cover.mp4"): os.remove("_Cover.mp4") │
│ 100 │ │
│ 101 │ for track in data["tracks"]: │
│ ❱ 102 │ │ content = applemusic.getStreamInfo( │
│ 103 │ │ │ track.get("id"), │
│ 104 │ │ │ track.get("type") │
│ 105 │ │ ) │
│ │
│ D:\Portable Soft\Downloads\Manzana Apple Music Downloader\api\api.py:403 in getStreamInfo │
│ │
│ 400 │ │ │ │ if not cert_data_b64: logger.error("Failed to get Service Certificate!", │
│ 401 │ │ │ │ │
│ 402 │ │ │ │ logger.info("Requesting License...") │
│ ❱ 403 │ │ │ │ correct, keys = self.__widevine(id, keyId, licenseUrl, cert_data_b64) │
│ 404 │ │ │ │ if not correct or not keys: logger.error("Failed to get License!", 1) │
│ 405 │ │ │ │ │
│ 406 │ │ │ │ self.__keys.set(pssh, keys) │
│ │
│ D:\Portable Soft\Downloads\Manzana Apple Music Downloader\api\api.py:239 in __widevine │
│ │
│ 236 │ │
│ 237 │ def __widevine(self, trackId, keyId, licenseUrl, cert_data_b64, _type="song"): │
│ 238 │ │ if _type == "song": │
│ ❱ 239 │ │ │ pssh_data = WidevinePsshData() │
│ 240 │ │ │ pssh_data.algorithm = 1 │
│ 241 │ │ │ pssh_data.key_id.append(base64.b64decode(keyId.split(",")[1])) │
│ 242 │ │ │ pssh = base64.b64encode(pssh_data.SerializeToString()).decode("utf8") │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
NameError: name 'WidevinePsshData' is not defined
PS D:\Portable Soft\Downloads\Manzana Apple Music Downloader>

@a1waysbeta You have to find widevine protos and scripts.

dropcodestudio@gmail.com

Sorry, I don't understand the script. I extracted three files from the phone, client_id.bin, private_key.pem, **.wvd, but I don't know what to rename them and how to put them in the folder.

I have two suggestion

  1. There should be a separate "Download" folder where all the content is automatically saved inside. So that it won't mess with the code folder

  2. Is it possible to get all the artist content by just giving a link to the artist profile i.e https://music.apple.com/us/artist/drake/271256 will get all the singles, EPs, Albums, Top Videos and More to see content all together

i get the same error, Any luck ?

@Gareryer Updating...
@sureshfizzy What error you got?

@dropcreations
E:\Extensions\Manzana-Apple-Music-Downloader-main>python manzana.py Traceback (most recent call last): File "E:\Extensions\Manzana-Apple-Music-Downloader-main\manzana.py", line 4, in <module> from rich.console import Console ModuleNotFoundError: No module named 'rich'

where as:
:\Extensions\Manzana-Apple-Music-Downloader-main>pip install -r requirements.txt Requirement already satisfied: rich in c:\users\leviathan\appdata\local\programs\python\python311\lib
Any idea how to troubleshoot?
TIA

@parades-onSoul try pip install rich command

@dropcreations can you fix this ?




        $$$$$$\$$$$\   $$$$$$\  $$$$$$$\  $$$$$$$$\ $$$$$$\  $$$$$$$\   $$$$$$\
        $$  _$$  _$$\  \____$$\ $$  __$$\ \____$$  |\____$$\ $$  __$$\  \____$$\
        $$ / $$ / $$ | $$$$$$$ |$$ |  $$ |  $$$$ _/ $$$$$$$ |$$ |  $$ | $$$$$$$ |
        $$ | $$ | $$ |$$  __$$ |$$ |  $$ | $$  _/  $$  __$$ |$$ |  $$ |$$  __$$ |
        $$ | $$ | $$ |\$$$$$$$ |$$ |  $$ |$$$$$$$$\\$$$$$$$ |$$ |  $$ |\$$$$$$$ |
        \__| \__| \__| \_______|\__|  \__|\________|\_______|\__|  \__| \_______|

                            ──── Apple Music Downloader ────



[21:31:23] [ManzanaCore] INFO: Checking access token found in cache...
[21:31:24] [ManzanaCore] INFO: Checking media-user-token...
[21:31:25] [ManzanaCore] INFO: Fetching api response...
[21:31:25] [ManzanaCore] INFO: Using the previous response found in cache...
[21:31:25] [ManzanaCore] INFO: Downloading album artwork...

         Downloading ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 264.8/264.8 kB 1.5 MB/s eta 0:00:00

[21:31:26] [ManzanaCore] INFO: Getting playback information...
[21:31:28] [ManzanaCore] INFO: Extracting key ID...
[21:31:28] [ManzanaCore] INFO: Getting Service Certificate...
[21:31:29] [ManzanaCore] INFO: Requesting License...
no client ID blob available for this device
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ C:\Users\UsEr\Documents\project\appledl\manzana.py:64 in <module>                                │
│                                                                                                  │
│   61 if __name__ == "__main__":                                                                  │
│   62 │   os.system('cls' if os.name == 'nt' else 'clear')                                        │
│   63 │   console.print(LOGO)                                                                     │
│ ❱ 64 │   main()                                                                                  │
│   65                                                                                             │
│                                                                                                  │
│ C:\Users\UsEr\Documents\project\appledl\manzana.py:59 in main                                    │
│                                                                                                  │
│   56 │   │   type=str                                                                            │
│   57 │   )                                                                                       │
│   58 │   args = parser.parse_args()                                                              │
│ ❱ 59 │   arguments(args)                                                                         │
│   60                                                                                             │
│   61 if __name__ == "__main__":                                                                  │
│   62 │   os.system('cls' if os.name == 'nt' else 'clear')                                        │
│                                                                                                  │
│ C:\Users\UsEr\Documents\project\appledl\handler.py:102 in arguments                              │
│                                                                                                  │
│    99 │   │   │   │   │   │   if os.path.exists("_Cover.mp4"): os.remove("_Cover.mp4")           │
│   100 │                                                                                          │
│   101 │   for track in data["tracks"]:                                                           │
│ ❱ 102 │   │   content = applemusic.getStreamInfo(                                                │
│   103 │   │   │   track.get("id"),                                                               │
│   104 │   │   │   track.get("type")                                                              │
│   105 │   │   )                                                                                  │
│                                                                                                  │
│ C:\Users\UsEr\Documents\project\appledl\api\api.py:403 in getStreamInfo                          │
│                                                                                                  │
│   400 │   │   │   │   if not cert_data_b64: logger.error("Failed to get Service Certificate!",   │
│   401 │   │   │   │                                                                              │
│   402 │   │   │   │   logger.info("Requesting License...")                                       │
│ ❱ 403 │   │   │   │   correct, keys = self.__widevine(id, keyId, licenseUrl, cert_data_b64)      │
│   404 │   │   │   │   if not correct or not keys: logger.error("Failed to get License!", 1)      │
│   405 │   │   │   │                                                                              │
│   406 │   │   │   │   self.__keys.set(pssh, keys)                                                │
│                                                                                                  │
│ C:\Users\UsEr\Documents\project\appledl\api\api.py:244 in __widevine                             │
│                                                                                                  │
│   241 │   │   │   pssh_data.key_id.append(base64.b64decode(keyId.split(",")[1]))                 │
│   242 │   │   │   pssh = base64.b64encode(pssh_data.SerializeToString()).decode("utf8")          │
│   243 │   │   │   wvdecrypt = WvDecrypt(init_data_b64=pssh, cert_data_b64=cert_data_b64, devic   │
│ ❱ 244 │   │   │   license_b64 = self.__getServiceCertificate(trackId, keyId, licenseUrl, b64en   │
│   245 │   │                                                                                      │
│   246 │   │   elif _type == "mv":                                                                │
│   247 │   │   │   wvdecrypt = WvDecrypt(init_data_b64=keyId.split(",")[-1], cert_data_b64=cert   │
│                                                                                                  │
│ C:\Python311\Lib\base64.py:58 in b64encode                                                       │
│                                                                                                  │
│    55 │   alternative alphabet for the '+' and '/' characters.  This allows an                   │
│    56 │   application to e.g. generate url or filesystem safe Base64 strings.                    │
│    57 │   """                                                                                    │
│ ❱  58 │   encoded = binascii.b2a_base64(s, newline=False)                                        │
│    59 │   if altchars is not None:                                                               │
│    60 │   │   assert len(altchars) == 2, repr(altchars)                                          │
│    61 │   │   return encoded.translate(bytes.maketrans(b'+/', altchars))                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: a bytes-like object is required, not 'int'

@py7hon You haven't added a device. device_client_id_blob and device_private_key must add to widevine/devices/android_generic folder before using. See here

@py7hon You haven't added a device. device_client_id_blob and device_private_key must add to widevine/devices/android_generic folder before using. See here

thanks its working

where to find media user token?

@parades-onSoul
where to find media user token?

Open music.apple.com and login, then open dev tools on browser, application -> cookies -> https://music.apple.com

@parades-onSoul
where to find media user token?

Open music.apple.com and login, then open dev tools on browser, application -> cookies -> https://music.apple.com

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ E:\Extensions\Manzana-Apple-Music-Downloader-main\manzana.py:64 in │
│ │
│ 61 if name == "main": │
│ 62 │ os.system('cls' if os.name == 'nt' else 'clear') │
│ 63 │ console.print(LOGO) │
│ ❱ 64 │ main() │
│ 65 │
│ │
│ E:\Extensions\Manzana-Apple-Music-Downloader-main\manzana.py:59 in main │
│ │
│ 56 │ │ type=str │
│ 57 │ ) │
│ 58 │ args = parser.parse_args() │
│ ❱ 59 │ arguments(args) │
│ 60 │
│ 61 if name == "main": │
│ 62 │ os.system('cls' if os.name == 'nt' else 'clear') │
│ │
│ E:\Extensions\Manzana-Apple-Music-Downloader-main\handler.py:58 in arguments │
│ │
│ 55 │ if args.sync: syncMsPointCount = 3 │
│ 56 │ │
│ 57 │ applemusic = AppleMusic(CACHE, CONFIG, syncMsPointCount, args.anim) │
│ ❱ 58 │ data = applemusic.getInfo(args.url) │
│ 59 │ │
│ 60 │ __dir = data.get("dir") │
│ 61 │
│ │
│ E:\Extensions\Manzana-Apple-Music-Downloader-main\api\api.py:429 in getInfo │
│ │
│ 426 │ │ self.__getUrl(url) │
│ 427 │ │ │
│ 428 │ │ if self.kind == "album": │
│ ❱ 429 │ │ │ return album( │
│ 430 │ │ │ │ self.__getJson(), │
│ 431 │ │ │ │ syncpoints=self.sync, │
│ 432 │ │ │ │ animartwork=self.animartwork │
│ │
│ E:\Extensions\Manzana-Apple-Music-Downloader-main\api\album.py:104 in album │
│ │
│ 101 │ │ │ │
│ 102 │ │ │ if "lyrics" in track["relationships"]: │
│ 103 │ │ │ │ if len(track["relationships"]["lyrics"].get("data")) > 0: │
│ ❱ 104 │ │ │ │ │ __info.update(getLyrics(track["relationships"]["lyrics"]["data"][0][ │
│ 105 │ │ │ │
│ 106 │ │ │ _info["type"] = 1 │
│ 107 │
│ │
│ E:\Extensions\Manzana-Apple-Music-Downloader-main\api\lyrics.py:17 in getLyrics │
│ │
│ 14 │ elif syncpoints == 2: return f'{mins:0>2}:{secs:05.2f}' │
│ 15 │
│ 16 def getLyrics(ttml, syncpoints: int): │
│ ❱ 17 │ ttml = BeautifulSoup(ttml, "lxml") │
│ 18 │ │
│ 19 │ info = {} │
│ 20 │
│ │
│ C:\Python 3.11\Lib\site-packages\bs4_init
.py:250 in init
│ │
│ 247 │ │ │ │ features = self.DEFAULT_BUILDER_FEATURES │
│ 248 │ │ │ builder_class = builder_registry.lookup(*features) │
│ 249 │ │ │ if builder_class is None: │
│ ❱ 250 │ │ │ │ raise FeatureNotFound( │
│ 251 │ │ │ │ │ "Couldn't find a tree builder with the features you " │
│ 252 │ │ │ │ │ "requested: %s. Do you need to install a parser library?" │
│ 253 │ │ │ │ │ % ",".join(features)) │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser
library?

any solution

any solution

Try pip install lxml

`[09:28:26] [ManzanaCore] INFO: Checking access token found in cache...
[09:28:29] [ManzanaCore] INFO: Checking media-user-token...
[09:28:30] [ManzanaCore] INFO: Fetching api response...
[09:28:30] [ManzanaCore] INFO: Using the previous response found in cache...
[09:28:30] [ManzanaCore] INFO: Downloading album artwork...

     Downloading ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 949.9/949.9 kB 733.7 kB/s eta 0:00:00

[09:28:32] [ManzanaCore] INFO: Getting playback information...
[09:28:33] [ManzanaCore] INFO: Extracting key ID...
[09:28:33] [ManzanaCore] INFO: Getting Service Certificate...
[09:28:33] [ManzanaCore] INFO: Requesting License...
[09:28:34] [ManzanaCore] INFO: Downloading "01 - Azhik.m4a"...

     Downloading ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 3.0/3.0 MB 1.0 MB/s eta 0:00:00

[09:28:41] [ManzanaCore] INFO: Decrypting audio...
[09:28:41] [ManzanaCore] INFO: Muxing audio...
[09:28:41] [ManzanaCore] ERROR: Muxing failed!
`
If am not wrong i need to put FFmpeg in binaries?

so far what i have done:
donwloaded ffmpeg zip from site extracted it > bin of ffmepg> copied ffmpeg.exe > pasted it in binaries on manazana folder

still failed

`[09:28:26] [ManzanaCore] INFO: Checking access token found in cache... [09:28:29] [ManzanaCore] INFO: Checking media-user-token... [09:28:30] [ManzanaCore] INFO: Fetching api response... [09:28:30] [ManzanaCore] INFO: Using the previous response found in cache... [09:28:30] [ManzanaCore] INFO: Downloading album artwork...

     Downloading ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 949.9/949.9 kB 733.7 kB/s eta 0:00:00

[09:28:32] [ManzanaCore] INFO: Getting playback information... [09:28:33] [ManzanaCore] INFO: Extracting key ID... [09:28:33] [ManzanaCore] INFO: Getting Service Certificate... [09:28:33] [ManzanaCore] INFO: Requesting License... [09:28:34] [ManzanaCore] INFO: Downloading "01 - Azhik.m4a"...

     Downloading ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 3.0/3.0 MB 1.0 MB/s eta 0:00:00

[09:28:41] [ManzanaCore] INFO: Decrypting audio... [09:28:41] [ManzanaCore] INFO: Muxing audio... [09:28:41] [ManzanaCore] ERROR: Muxing failed! ` If am not wrong i need to put FFmpeg in binaries?

so far what i have done: donwloaded ffmpeg zip from site extracted it > bin of ffmepg> copied ffmpeg.exe > pasted it in binaries on manazana folder

still failed

Just install GPAC on your system. (https://gpac.wp.imt.fr/downloads/)

@dropcreations its all good now and thanks bro for making this amazing tool.Btw do you have any plan to add fairplay support?
@py7hon thanks too bro.

i have this error:
C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main>manzana.py
Traceback (most recent call last):
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\manzana.py", line 7, in
from handler import arguments
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\handler.py", line 6, in
from api import AppleMusic
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\api_init_.py", line 1, in
from api.api import AppleMusic
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\api\api.py", line 16, in
from widevine import WvDecrypt
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\widevine_init_.py", line 2, in
from widevine.wvdecrypt import WvDecrypt
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\widevine\wvdecrypt.py", line 2, in
from widevine import cdm
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\widevine\cdm.py", line 20, in
import widevine.formats.wv_proto2_pb2 as wv_proto2
File "C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main\widevine\formats\wv_proto2_pb2.py", line 7, in
from google.protobuf.internal import builder as builder
ImportError: cannot import name 'builder' from 'google.protobuf.internal' (C:\Users\heyfr\AppData\Local\Programs\Python\Python39\lib\site-packages\google\protobuf\internal_init
.py)

C:\Users\heyfr\Desktop\Manzana-Apple-Music-Downloader-main>

@vidclub0 See here

Follow these steps:

  • Install the latest protobuf version (use below command)
pip install --upgrade protobuf
  • Copy builder.py from .../Lib/site-packages/google/protobuf/internal to another folder on your computer (let's say Documents)
  • Install a protobuf version that is compatible with project (3.19.4)
pip install protobuf==3.19.4
  • Copy builder.py from (let's say Documents) to ...lib/site-packages/google/protobuf/internal
  • Run

I have two suggestion

  1. There should be a separate "Download" folder where all the content is automatically saved inside. So that it won't mess with the code folder
  2. Is it possible to get all the artist content by just giving a link to the artist profile i.e https://music.apple.com/us/artist/drake/271256 will get all the singles, EPs, Albums, Top Videos and More to see content all together

@Gareryer Artist URL support has been added and it also saves files to a separate directory called output. Enjoy...!