Implemented URL parsing and music identification improvements

This commit is contained in:
Alexander Karpov 2024-02-01 15:41:12 +03:00
parent aa49e4afc3
commit a87385db78
2 changed files with 60 additions and 24 deletions

View File

@ -1,3 +1,5 @@
import threading
import spotipy import spotipy
from django.conf import settings from django.conf import settings
from spotdl import Song, Spotdl from spotdl import Song, Spotdl
@ -23,21 +25,28 @@ def search(name: str, session: spotipy.Spotify, search_type="track"):
return res return res
def download_url(url, user_id=None): thread_local = threading.local()
def get_spotdl_client():
if not hasattr(thread_local, "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", "musixmatch"],
} }
thread_local.spotdl_client = Spotdl(
spotdl_client = Spotdl(
client_id=settings.MUSIC_SPOTIFY_ID, client_id=settings.MUSIC_SPOTIFY_ID,
client_secret=settings.MUSIC_SPOTIFY_SECRET, client_secret=settings.MUSIC_SPOTIFY_SECRET,
user_auth=False, user_auth=False,
headless=False, headless=False,
downloader_settings=spot_settings, downloader_settings=spot_settings,
) )
return thread_local.spotdl_client
def download_url(url, user_id=None):
spotdl_client = get_spotdl_client()
session = create_session() session = create_session()
if "track" in url: if "track" in url:

View File

@ -1,7 +1,9 @@
from datetime import timedelta from datetime import timedelta
import pylast import pylast
import spotipy
import structlog import structlog
import yt_dlp
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
@ -9,6 +11,7 @@
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 pytube import Channel, Playlist
from spotipy import SpotifyClientCredentials
from akarpov.music.api.serializers import SongSerializer from akarpov.music.api.serializers import SongSerializer
from akarpov.music.models import ( from akarpov.music.models import (
@ -28,22 +31,46 @@
@shared_task @shared_task
def list_tracks(url, user_id): def list_tracks(url, user_id):
if "music.youtube.com" in url: if "music.youtube.com" in url or "youtu.be" in url:
url = url.replace("music.youtube.com", "youtube.com") url = url.replace("music.youtube.com", "youtube.com")
url = url.replace("youtu.be", "youtube.com")
if "spotify.com" in url: if "spotify.com" in url:
spotify.download_url(url, user_id) spotify.download_url(url, user_id)
elif "music.yandex.ru" in url: elif "music.yandex.ru" in url:
yandex.load_playlist(url, user_id) yandex.load_playlist(url, user_id)
elif "channel" in url or "/c/" in url: if "youtube.com" in url:
p = Channel(url) if "channel" in url or "/c/" in url:
for video in p.video_urls: channel = Channel(url)
process_yb.apply_async(kwargs={"url": video, "user_id": user_id}) for video in channel.videos:
with yt_dlp.YoutubeDL({}) as ydl:
info = ydl.extract_info(video, download=False)
if info.get("category") == "Music":
process_yb.apply_async(
kwargs={"url": video.watch_url, "user_id": user_id}
)
elif "playlist" in url or "&list=" in url: elif "playlist" in url or "&list=" in url:
p = Playlist(url) playlist = Playlist(url)
for video in p.video_urls: for video in playlist.videos:
process_yb.apply_async(kwargs={"url": video, "user_id": user_id}) process_yb.apply_async(
kwargs={"url": video.watch_url, "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})
else:
spotify_manager = SpotifyClientCredentials(
client_id=settings.MUSIC_SPOTIFY_ID,
client_secret=settings.MUSIC_SPOTIFY_SECRET,
)
spotify_search = spotipy.Spotify(client_credentials_manager=spotify_manager)
results = spotify_search.search(q=url, type="track", limit=1)
top_track = (
results["tracks"]["items"][0] if results["tracks"]["items"] else None
)
if top_track:
spotify.download_url(top_track["external_urls"]["spotify"], user_id)
url = top_track["external_urls"]["spotify"]
return url return url