mirror of
				https://github.com/KevinMidboe/spotify-downloader.git
				synced 2025-10-29 18:00:15 +00:00 
			
		
		
		
	Use YouTube as fallback for track metadata if not found on Spotify
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| from logzero import logger as log | ||||
| import os | ||||
| import sys | ||||
| import urllib.request | ||||
|  | ||||
| from spotdl import const | ||||
|  | ||||
| @@ -253,3 +254,12 @@ def remove_duplicates(tracks): | ||||
|     local_set = set() | ||||
|     local_set_add = local_set.add | ||||
|     return [x for x in tracks if not (x in local_set or local_set_add(x))] | ||||
|  | ||||
|  | ||||
| def content_available(url): | ||||
|     try: | ||||
|         response = urllib.request.urlopen(url) | ||||
|     except HTTPError: | ||||
|         return False | ||||
|     else: | ||||
|         return response.getcode() < 300 | ||||
|   | ||||
| @@ -46,6 +46,8 @@ class EmbedMetadata: | ||||
|     def __init__(self, music_file, meta_tags): | ||||
|         self.music_file = music_file | ||||
|         self.meta_tags = meta_tags | ||||
|         self.spotify_metadata = meta_tags["spotify_metadata"] | ||||
|         self.provider = "spotify" if meta_tags["spotify_metadata"] else "youtube" | ||||
|  | ||||
|     def as_mp3(self): | ||||
|         """ Embed metadata to MP3 files. """ | ||||
| @@ -62,7 +64,7 @@ class EmbedMetadata: | ||||
|         audiofile["lyricist"] = meta_tags["artists"][0]["name"] | ||||
|         audiofile["arranger"] = meta_tags["artists"][0]["name"] | ||||
|         audiofile["performer"] = meta_tags["artists"][0]["name"] | ||||
|         audiofile["website"] = meta_tags["external_urls"]["spotify"] | ||||
|         audiofile["website"] = meta_tags["external_urls"][self.provider] | ||||
|         audiofile["length"] = str(meta_tags["duration"]) | ||||
|         if meta_tags["publisher"]: | ||||
|             audiofile["encodedby"] = meta_tags["publisher"] | ||||
| @@ -78,7 +80,7 @@ class EmbedMetadata: | ||||
|         audiofile["TYER"] = TYER(encoding=3, text=meta_tags["year"]) | ||||
|         if meta_tags["publisher"]: | ||||
|             audiofile["TPUB"] = TPUB(encoding=3, text=meta_tags["publisher"]) | ||||
|         audiofile["COMM"] = COMM(encoding=3, text=meta_tags["external_urls"]["spotify"]) | ||||
|         audiofile["COMM"] = COMM(encoding=3, text=meta_tags["external_urls"][self.provider]) | ||||
|         if meta_tags["lyrics"]: | ||||
|             audiofile["USLT"] = USLT( | ||||
|                 encoding=3, desc=u"Lyrics", text=meta_tags["lyrics"] | ||||
| @@ -106,7 +108,7 @@ class EmbedMetadata: | ||||
|         audiofile = MP4(music_file) | ||||
|         self._embed_basic_metadata(audiofile, preset=M4A_TAG_PRESET) | ||||
|         audiofile[M4A_TAG_PRESET["year"]] = meta_tags["year"] | ||||
|         audiofile[M4A_TAG_PRESET["comment"]] = meta_tags["external_urls"]["spotify"] | ||||
|         audiofile[M4A_TAG_PRESET["comment"]] = meta_tags["external_urls"][self.provider] | ||||
|         if meta_tags["lyrics"]: | ||||
|             audiofile[M4A_TAG_PRESET["lyrics"]] = meta_tags["lyrics"] | ||||
|         try: | ||||
| @@ -127,7 +129,7 @@ class EmbedMetadata: | ||||
|         audiofile = FLAC(music_file) | ||||
|         self._embed_basic_metadata(audiofile) | ||||
|         audiofile["year"] = meta_tags["year"] | ||||
|         audiofile["comment"] = meta_tags["external_urls"]["spotify"] | ||||
|         audiofile["comment"] = meta_tags["external_urls"][self.provider] | ||||
|         if meta_tags["lyrics"]: | ||||
|             audiofile["lyrics"] = meta_tags["lyrics"] | ||||
|  | ||||
| @@ -147,7 +149,8 @@ class EmbedMetadata: | ||||
|         meta_tags = self.meta_tags | ||||
|         audiofile[preset["artist"]] = meta_tags["artists"][0]["name"] | ||||
|         audiofile[preset["albumartist"]] = meta_tags["album"]["artists"][0]["name"] | ||||
|         audiofile[preset["album"]] = meta_tags["album"]["name"] | ||||
|         if meta_tags["album"]["name"]: | ||||
|             audiofile[preset["album"]] = meta_tags["album"]["name"] | ||||
|         audiofile[preset["title"]] = meta_tags["name"] | ||||
|         audiofile[preset["date"]] = meta_tags["release_date"] | ||||
|         audiofile[preset["originaldate"]] = meta_tags["release_date"] | ||||
|   | ||||
							
								
								
									
										31
									
								
								spotdl/patcher.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								spotdl/patcher.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| import pafy | ||||
|  | ||||
| from spotdl import internals | ||||
|  | ||||
|  | ||||
| def _getbestthumb(self): | ||||
|     url = self._ydl_info["thumbnails"][0]["url"] | ||||
|     if url: | ||||
|         return url | ||||
|  | ||||
|     part_url = "http://i.ytimg.com/vi/%s/" % self.videoid | ||||
|     # Thumbnail resolution sorted in descending order | ||||
|     thumbs = ("maxresdefault.jpg", | ||||
|               "sddefault.jpg", | ||||
|               "hqdefault.jpg", | ||||
|               "mqdefault.jpg", | ||||
|               "default.jpg") | ||||
|     for thumb in thumbs: | ||||
|         url = part_url + thumb | ||||
|         if self._content_available(url): | ||||
|             return url | ||||
|  | ||||
|  | ||||
| @classmethod | ||||
| def _content_available(cls, url): | ||||
|     return internals.content_available(url) | ||||
|  | ||||
| def patch_pafy(): | ||||
|     pafy.backend_shared.BasePafy._bestthumb = None | ||||
|     pafy.backend_shared.BasePafy._content_available = _content_available | ||||
|     pafy.backend_shared.BasePafy.getbestthumb = _getbestthumb | ||||
| @@ -81,6 +81,7 @@ def generate_metadata(raw_song): | ||||
|     # Some sugar | ||||
|     meta_tags["year"], *_ = meta_tags["release_date"].split("-") | ||||
|     meta_tags["duration"] = meta_tags["duration_ms"] / 1000.0 | ||||
|     meta_tags["spotify_metadata"] = True | ||||
|     # Remove unwanted parameters | ||||
|     del meta_tags["duration_ms"] | ||||
|     del meta_tags["available_markets"] | ||||
|   | ||||
| @@ -14,6 +14,12 @@ from spotdl import const | ||||
| # Read more on mps-youtube/pafy#199 | ||||
| pafy.g.opener.addheaders.append(("Range", "bytes=0-")) | ||||
|  | ||||
| # Implement unreleased methods on Pafy object | ||||
| # More info: https://github.com/mps-youtube/pafy/pull/211 | ||||
| if pafy.__version__ <= "0.5.4": | ||||
|     from spotdl import patcher | ||||
|     patcher.patch_pafy() | ||||
|  | ||||
|  | ||||
| def set_api_key(): | ||||
|     if const.args.youtube_api_key: | ||||
| @@ -49,6 +55,8 @@ def match_video_and_metadata(track, force_pafy=True): | ||||
|         track = slugify(content.title).replace("-", " ") | ||||
|         if not const.args.no_metadata: | ||||
|             meta_tags = spotify_tools.generate_metadata(track) | ||||
|             if meta_tags is None: # and const.args.allow_youtube: | ||||
|                 meta_tags = generate_metadata(content) | ||||
|     else: | ||||
|         # Let it generate metadata, youtube doesn't know spotify slang | ||||
|         if not const.args.no_metadata or internals.is_spotify(track): | ||||
| @@ -56,11 +64,37 @@ def match_video_and_metadata(track, force_pafy=True): | ||||
|  | ||||
|         if force_pafy: | ||||
|             content = go_pafy(track, meta_tags) | ||||
|             if meta_tags is None: # and const.args.allow_youtube: | ||||
|                 meta_tags = generate_metadata(content) | ||||
|         else: | ||||
|             content = None | ||||
|     return content, meta_tags | ||||
|  | ||||
|  | ||||
| def generate_metadata(content): | ||||
|     """ Fetch a song's metadata from YouTube. """ | ||||
|     meta_tags = {"spotify_metadata": False, | ||||
|                  "name": content.title, | ||||
|                  "artists": [{"name": content.author}], | ||||
|                  "duration": content.length, | ||||
|                  "external_urls": {"youtube": content.watchv_url}, | ||||
|                  "album": {"images" : [{"url": content.getbestthumb()}], "name": None}, | ||||
|                  "year": content.published.split("-")[0], | ||||
|                  "release_date": content.published.split(" ")[0], | ||||
|                  "type": "track", | ||||
|                  "disc_number": 1, | ||||
|                  "track_number": 1, | ||||
|                  "total_tracks": 1, | ||||
|                  "publisher": None, | ||||
|                  "external_ids": {"isrc": None}, | ||||
|                  "lyrics": None, | ||||
|                  "copyright": None, | ||||
|                  "genre": None, | ||||
|                  } | ||||
|  | ||||
|     return meta_tags | ||||
|  | ||||
|  | ||||
| def get_youtube_title(content, number=None): | ||||
|     """ Get the YouTube video's title. """ | ||||
|     title = content.title | ||||
|   | ||||
		Reference in New Issue
	
	Block a user