lyrics support

This commit is contained in:
logykk 2022-02-16 21:56:09 +13:00
parent 00d10b15d3
commit b449126495
4 changed files with 41 additions and 14 deletions

View File

@ -64,9 +64,10 @@ def client(args) -> None:
search_text = ''
while len(search_text) == 0:
search_text = input('Enter search or URL: ')
if not download_from_urls([args.search]):
search(args.search)
search(search_text)
else:
if not download_from_urls([args.search]):
search(args.search)
def download_from_urls(urls: list[str]) -> bool:
""" Downloads from a list of urls """

View File

@ -33,6 +33,7 @@ PRINT_PROGRESS_INFO = 'PRINT_PROGRESS_INFO'
PRINT_WARNINGS = 'PRINT_WARNINGS'
RETRY_ATTEMPTS = 'RETRY_ATTEMPTS'
CONFIG_VERSION = 'CONFIG_VERSION'
DOWNLOAD_LYRICS = 'DOWNLOAD_LYRICS'
CONFIG_VALUES = {
CREDENTIALS_LOCATION: { 'default': '', 'type': str, 'arg': '--credentials-location' },
@ -41,6 +42,7 @@ CONFIG_VALUES = {
ROOT_PATH: { 'default': '', 'type': str, 'arg': '--root-path' },
ROOT_PODCAST_PATH: { 'default': '', 'type': str, 'arg': '--root-podcast-path' },
SPLIT_ALBUM_DISCS: { 'default': 'False', 'type': bool, 'arg': '--split-album-discs' },
DOWNLOAD_LYRICS: { 'default': 'True', 'type': bool, 'arg': '--download-lyrics' },
MD_ALLGENRES: { 'default': 'False', 'type': bool, 'arg': '--md-allgenres' },
MD_GENREDELIMITER: { 'default': ',', 'type': str, 'arg': '--md-genredelimiter' },
DOWNLOAD_FORMAT: { 'default': 'ogg', 'type': str, 'arg': '--download-format' },
@ -187,6 +189,10 @@ class Config:
def get_download_format(cls) -> str:
return cls.get(DOWNLOAD_FORMAT)
@classmethod
def get_download_lyrics(cls) -> bool:
return cls.get(DOWNLOAD_LYRICS)
@classmethod
def get_bulk_wait_time(cls) -> int:
return cls.get(BULK_WAIT_TIME)

View File

@ -1,10 +1,10 @@
from pathlib import Path, PurePath
import math
import re
import time
import uuid
from typing import Any, Tuple, List
from librespot.audio.decoders import AudioQuality
from librespot.metadata import TrackId
import ffmpy
@ -64,7 +64,6 @@ def get_song_info(song_id) -> Tuple[List[str], List[Any], str, str, Any, Any, An
def get_song_genres(rawartists: List[str], track_name: str) -> List[str]:
try:
genres = []
for data in rawartists:
@ -86,6 +85,26 @@ def get_song_genres(rawartists: List[str], track_name: str) -> List[str]:
raise ValueError(f'Failed to parse GENRES response: {str(e)}\n{raw}')
def get_song_lyrics(song_id: str, file_save: str) -> None:
raw, lyrics = Zotify.invoke_url(f'https://spclient.wg.spotify.com/color-lyrics/v2/track/{song_id}')
formatted_lyrics = lyrics['lyrics']['lines']
if(lyrics['lyrics']['syncType'] == "UNSYNCED"):
with open(file_save, 'w') as file:
for line in formatted_lyrics:
file.writelines(line['words'] + '\n')
elif(lyrics['lyrics']['syncType'] == "LINE_SYNCED"):
with open(file_save, 'w') as file:
for line in formatted_lyrics:
timestamp = int(line['startTimeMs'])
ts_minutes = str(math.floor(timestamp / 60000)).zfill(2)
ts_seconds = str(math.floor((timestamp % 60000) / 1000)).zfill(2)
ts_millis = str(math.floor(timestamp % 1000))[:2].zfill(2)
file.writelines(f'[{ts_minutes}:{ts_seconds}.{ts_millis}]' + line['words'] + '\n')
else:
raise ValueError(f'Filed to fetch lyrics: {song_id}')
def get_song_duration(song_id: str) -> float:
""" Retrieves duration of song in second as is on spotify """
@ -96,14 +115,9 @@ def get_song_duration(song_id: str) -> float:
# convert to seconds
duration = float(ms_duration)/1000
# debug
# print(duration)
# print(type(duration))
return duration
# noinspection PyBroadException
def download_track(mode: str, track_id: str, extra_keys=None, disable_progressbar=False) -> None:
""" Downloads raw song audio from Spotify """
@ -182,8 +196,8 @@ def download_track(mode: str, track_id: str, extra_keys=None, disable_progressba
else:
if track_id != scraped_song_id:
track_id = scraped_song_id
track_id = TrackId.from_base62(track_id)
stream = Zotify.get_content_stream(track_id, Zotify.DOWNLOAD_QUALITY)
track = TrackId.from_base62(track_id)
stream = Zotify.get_content_stream(track, Zotify.DOWNLOAD_QUALITY)
create_download_directory(filedir)
total_size = stream.input_stream.size
@ -213,6 +227,8 @@ def download_track(mode: str, track_id: str, extra_keys=None, disable_progressba
genres = get_song_genres(raw_artists, name)
if(Zotify.CONFIG.get_download_lyrics()):
get_song_lyrics(track_id, PurePath(filedir / str(song_name + '.lrc')))
convert_audio_format(filename_temp)
set_audio_tags(filename_temp, artists, genres, name, album_name, release_year, disc_number, track_number)
set_music_thumbnail(filename_temp, image_url)

View File

@ -56,14 +56,18 @@ class Zotify:
def get_auth_header(cls):
return {
'Authorization': f'Bearer {cls.__get_auth_token()}',
'Accept-Language': f'{cls.CONFIG.get_language()}'
'Accept-Language': f'{cls.CONFIG.get_language()}',
'Accept': 'application/json',
'app-platform': 'WebPlayer'
}
@classmethod
def get_auth_header_and_params(cls, limit, offset):
return {
'Authorization': f'Bearer {cls.__get_auth_token()}',
'Accept-Language': f'{cls.CONFIG.get_language()}'
'Accept-Language': f'{cls.CONFIG.get_language()}',
'Accept': 'application/json',
'app-platform': 'WebPlayer'
}, {LIMIT: limit, OFFSET: offset}
@classmethod