mirror of
				https://github.com/Alexander-D-Karpov/akarpov
				synced 2025-11-01 00:57:26 +03:00 
			
		
		
		
	Refine YouTube and Spotify music download process
This commit is contained in:
		
							parent
							
								
									a87385db78
								
							
						
					
					
						commit
						ffa1e9c69f
					
				|  | @ -33,7 +33,11 @@ def get_spotdl_client(): | ||||||
|         spot_settings = { |         spot_settings = { | ||||||
|             "simple_tui": True, |             "simple_tui": True, | ||||||
|             "log_level": "ERROR", |             "log_level": "ERROR", | ||||||
|             "lyrics_providers": ["genius", "musixmatch"], |             "lyrics_providers": ["genius", "azlyrics", "musixmatch"], | ||||||
|  |             "threads": 6, | ||||||
|  |             "format": "mp3", | ||||||
|  |             "ffmpeg": "ffmpeg", | ||||||
|  |             "sponsor_block": True, | ||||||
|         } |         } | ||||||
|         thread_local.spotdl_client = Spotdl( |         thread_local.spotdl_client = Spotdl( | ||||||
|             client_id=settings.MUSIC_SPOTIFY_ID, |             client_id=settings.MUSIC_SPOTIFY_ID, | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ | ||||||
| from PIL import Image | from PIL import Image | ||||||
| from pydub import AudioSegment | from pydub import AudioSegment | ||||||
| from pytube import Search, YouTube | from pytube import Search, YouTube | ||||||
|  | from spotdl.providers.audio import YouTubeMusic | ||||||
| 
 | 
 | ||||||
| from akarpov.music.models import Song | from akarpov.music.models import Song | ||||||
| from akarpov.music.services.db import load_track | from akarpov.music.services.db import load_track | ||||||
|  | @ -18,22 +19,28 @@ | ||||||
| final_filename = None | final_filename = None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ydl_opts = { | ytmusic = YouTubeMusic() | ||||||
|     "format": "m4a/bestaudio/best", |  | ||||||
|     "postprocessors": [ |  | ||||||
|         {  # Extract audio using ffmpeg |  | ||||||
|             "key": "FFmpegExtractAudio", |  | ||||||
|             "preferredcodec": "m4a", |  | ||||||
|         } |  | ||||||
|     ], |  | ||||||
|     "outtmpl": f"{settings.MEDIA_ROOT}/%(uploader)s_%(title)s.%(ext)s", |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def download_file(url): | def download_file(url): | ||||||
|  |     ydl_opts = { | ||||||
|  |         "format": "bestaudio/best", | ||||||
|  |         "outtmpl": f"{settings.MEDIA_ROOT}/%(uploader)s_%(title)s.%(ext)s", | ||||||
|  |         "postprocessors": [ | ||||||
|  |             {"key": "SponsorBlock"},  # Skip sponsor segments | ||||||
|  |             { | ||||||
|  |                 "key": "FFmpegExtractAudio", | ||||||
|  |                 "preferredcodec": "mp3", | ||||||
|  |                 "preferredquality": "192", | ||||||
|  |             },  # Extract audio | ||||||
|  |             {"key": "EmbedThumbnail"},  # Embed Thumbnail | ||||||
|  |             {"key": "FFmpegMetadata"},  # Apply correct metadata | ||||||
|  |         ], | ||||||
|  |     } | ||||||
|     with yt_dlp.YoutubeDL(ydl_opts) as ydl: |     with yt_dlp.YoutubeDL(ydl_opts) as ydl: | ||||||
|         info = ydl.extract_info(url) |         info = ydl.extract_info(url, download=True) | ||||||
|     return info["requested_downloads"][0]["_filename"] |         filename = ydl.prepare_filename(info) | ||||||
|  |     return os.path.splitext(filename)[0] + ".mp3" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def parse_description(description: str) -> list: | def parse_description(description: str) -> list: | ||||||
|  | @ -67,7 +74,7 @@ def parse_description(description: str) -> list: | ||||||
| def download_from_youtube_link(link: str, user_id: int) -> Song: | def download_from_youtube_link(link: str, user_id: int) -> Song: | ||||||
|     song = None |     song = None | ||||||
| 
 | 
 | ||||||
|     with yt_dlp.YoutubeDL(ydl_opts) as ydl: |     with yt_dlp.YoutubeDL({"ignoreerrors": True, "extract_flat": True}) as ydl: | ||||||
|         info_dict = ydl.extract_info(link, download=False) |         info_dict = ydl.extract_info(link, download=False) | ||||||
|         title = info_dict.get("title", None) |         title = info_dict.get("title", None) | ||||||
|         description = info_dict.get("description", None) |         description = info_dict.get("description", None) | ||||||
|  | @ -82,6 +89,9 @@ def download_from_youtube_link(link: str, user_id: int) -> Song: | ||||||
|         + slugify(orig_path.split("/")[-1].split(".")[0]) |         + slugify(orig_path.split("/")[-1].split(".")[0]) | ||||||
|         + ".mp3" |         + ".mp3" | ||||||
|     ) |     ) | ||||||
|  |     if orig_path.endswith(".mp3"): | ||||||
|  |         os.rename(orig_path, path) | ||||||
|  |     else: | ||||||
|         AudioSegment.from_file(orig_path).export(path) |         AudioSegment.from_file(orig_path).export(path) | ||||||
|         if orig_path != path: |         if orig_path != path: | ||||||
|             os.remove(orig_path) |             os.remove(orig_path) | ||||||
|  |  | ||||||
|  | @ -3,14 +3,13 @@ | ||||||
| import pylast | import pylast | ||||||
| import spotipy | import spotipy | ||||||
| import structlog | import structlog | ||||||
| import yt_dlp | import ytmusicapi | ||||||
| from asgiref.sync import async_to_sync | from asgiref.sync import async_to_sync | ||||||
| from celery import shared_task | from celery import shared_task | ||||||
| from channels.layers import get_channel_layer | from channels.layers import get_channel_layer | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| from django.utils.timezone import now | from django.utils.timezone import now | ||||||
| from pytube import Channel, Playlist |  | ||||||
| from spotipy import SpotifyClientCredentials | from spotipy import SpotifyClientCredentials | ||||||
| 
 | 
 | ||||||
| from akarpov.music.api.serializers import SongSerializer | from akarpov.music.api.serializers import SongSerializer | ||||||
|  | @ -40,19 +39,30 @@ def list_tracks(url, user_id): | ||||||
|         yandex.load_playlist(url, user_id) |         yandex.load_playlist(url, user_id) | ||||||
|     if "youtube.com" in url: |     if "youtube.com" in url: | ||||||
|         if "channel" in url or "/c/" in url: |         if "channel" in url or "/c/" in url: | ||||||
|             channel = Channel(url) |             ytmusic = ytmusicapi.YTMusic() | ||||||
|             for video in channel.videos: |             channel_id = url.split("/")[-1] | ||||||
|                 with yt_dlp.YoutubeDL({}) as ydl: |             channel_songs = ytmusic.get_artist(channel_id)["songs"]["results"] | ||||||
|                     info = ydl.extract_info(video, download=False) |             print(channel_songs) | ||||||
|                     if info.get("category") == "Music": | 
 | ||||||
|  |             for song in channel_songs: | ||||||
|                 process_yb.apply_async( |                 process_yb.apply_async( | ||||||
|                             kwargs={"url": video.watch_url, "user_id": user_id} |                     kwargs={ | ||||||
|  |                         "url": f"https://youtube.com/watch?v={song['videoId']}", | ||||||
|  |                         "user_id": user_id, | ||||||
|  |                     } | ||||||
|                 ) |                 ) | ||||||
|  | 
 | ||||||
|         elif "playlist" in url or "&list=" in url: |         elif "playlist" in url or "&list=" in url: | ||||||
|             playlist = Playlist(url) |             ytmusic = ytmusicapi.YTMusic() | ||||||
|             for video in playlist.videos: |             playlist_id = url.split("=")[-1] | ||||||
|  |             playlist_songs = ytmusic.get_playlist(playlist_id)["tracks"]["results"] | ||||||
|  | 
 | ||||||
|  |             for song in playlist_songs: | ||||||
|                 process_yb.apply_async( |                 process_yb.apply_async( | ||||||
|                     kwargs={"url": video.watch_url, "user_id": user_id} |                     kwargs={ | ||||||
|  |                         "url": f"https://music.youtube.com/watch?v={song['videoId']}", | ||||||
|  |                         "user_id": user_id, | ||||||
|  |                     } | ||||||
|                 ) |                 ) | ||||||
|         else: |         else: | ||||||
|             process_yb.apply_async(kwargs={"url": url, "user_id": user_id}) |             process_yb.apply_async(kwargs={"url": url, "user_id": user_id}) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user