Skip to content

Commit

Permalink
Improve accuracy of lyrics and clearing screen.
Browse files Browse the repository at this point in the history
Lyrics are now fetched from Tidal instead of the previous API. This should in theory improve the accuracy of results. Also, the screen now clears before a track/video plays to improve readability.
  • Loading branch information
ZingyTomato committed Jun 5, 2022
1 parent b6ab6e5 commit 3df1525
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 32 deletions.
46 changes: 15 additions & 31 deletions harmony/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import sys
import signal
import html
import lyrics

queue_list = []

Expand Down Expand Up @@ -68,7 +69,7 @@ def apiFailure():
return

def noStreamUrl():
info = print(colored(f"\nUnable to find any a stream URL!", 'red', attrs=['bold']))
info = print(colored(f"\nUnable to find a stream URL for the specific song!", 'red', attrs=['bold']))
return

def invalidRange():
Expand All @@ -95,6 +96,9 @@ def emptyInput():
print(colored("\nPlease enter the name of a song!", 'red', attrs=['bold']))
return

def clearScreen():
return os.system("clear")

def showQueue():
if len(item_list) == 0:
return queueIsEmpty()
Expand All @@ -104,7 +108,7 @@ def showQueue():

def showResults(query, result):
info = print(colored("Results for", 'red') + colored(f" {query}\n", 'cyan', attrs=['bold']))
lists = print(f"\n".join([f"{colored(i, 'green')}. {colored(fixFormatting(item['name']), 'red', attrs=['bold'])} - {colored(fixFormatting(item['primaryArtists']), 'cyan', attrs=['bold'])} ({time.strftime('%M:%S',time.gmtime(int(item['duration'])))}) {isExplicit(int(item['explicitContent']))}" for i, item in enumerate((result['results']), start=1)]))
lists = print(f"\n".join([f"{colored(i, 'green')}. {colored(fixFormatting(item['name']), 'red', attrs=['bold'])} - {colored(fixFormatting(item['primaryArtists'].split(',', 1)[0]), 'cyan', attrs=['bold'])} ({time.strftime('%M:%S',time.gmtime(int(item['duration'])))}) {isExplicit(int(item['explicitContent']))}" for i, item in enumerate((result['results']), start=1)]))
return songs.pickTrack(query, result)

def showResultsVideos(query, result):
Expand All @@ -125,6 +129,7 @@ def removeSubs():
return

def getSongs(query):
clearScreen()
print(colored("\nSearching for songs...", 'cyan', attrs=['bold']))
searchurl = requests.request("GET", f"{SEARCH_URL}/search/songs?query={query}&page=1&limit=20", headers=headers).text.encode()
searchjson = json.loads(searchurl)
Expand All @@ -139,6 +144,7 @@ def getSongs(query):
return showResults(query, searchjson)

def getVideos(query):
clearScreen()
print(colored("\nSearching for videos...", 'cyan', attrs=['bold']))
searchurl = requests.request("GET", f"{PIPEDAPI_URL}/search?q={query}&filter=videos", headers=headers).text.encode()
searchjson = json.loads(searchurl)
Expand All @@ -153,41 +159,44 @@ def getVideos(query):
def playTracks():
if len(item_list) == 0:
return queueIsEmpty()
clearScreen()
queuemsg = print(colored("\nPlaying songs in the Queue", 'cyan', attrs=['bold']) + colored(' (Q)uit, (L)oop, (J) Disable Lyrics\n', 'red'))
show_queue = print(f"\n".join([f"{colored(i, 'green')}. {fixFormatting(track)} \n" for i, track in enumerate((item_list), start=1)]))
print(colored("Launching MPV and searching for Lyrics...", 'green', attrs=['bold']), end="\r")
for track, title, author in zip(queue_list, title_list, author_list):
lyricsToVtt(f"{title} - {author}")
lyrics.searchLyrics(f"{title} - {author}")
os.system(f"mpv --no-video --term-osd-bar --no-resume-playback {SUB_FILE} --term-playing-msg='{fixFormatting(colored(title, 'red'))} - {fixFormatting(colored(author, 'cyan'))}' '{track}'")
removeSubs()
return emptyQueue(), removeSubs(), songs.searchSongs()

def playVideos():
if len(item_list) == 0:
return queueIsEmpty()
clearScreen()
queuemsg = print(colored("\nPlaying videos in the Queue", 'cyan', attrs=['bold']) + colored(' (Q)uit, (L)oop\n', 'red'))
show_queue = print(f"\n".join([f"{colored(i, 'green')}. {fixFormatting(track)} \n" for i, track in enumerate((item_list), start=1)]))
print(colored("Launching MPV...", 'green', attrs=['bold']), end="\r")
play_videos = [os.system(f"mpv --term-osd-bar --force-media-title='{fixFormatting(title)} --no-resume-playback '{track}' --audio-file='{audio}''") for track, audio, title in zip(queue_list, audio_list, title_list)]
play_videos = [os.system(f"mpv --term-osd-bar --force-media-title='{fixFormatting(title)}' --no-resume-playback '{track}' --audio-file='{audio}' ") for track, audio, title in zip(queue_list, audio_list, title_list)]
return emptyQueue(), videos.searchVideos()

def playTracksURL(url):
clearScreen()
print(colored("Launching MPV...", 'green', attrs=['bold']), end="\r")
play_videos = os.system(f"mpv --no-video --term-osd-bar --no-resume-playback {url} ")
return songs.searchSongs()

def playVideosURL(url):
clearScreen()
print(colored("Launching MPV...", 'green', attrs=['bold']), end="\r")
play_videos = os.system(f"mpv --no-resume-playback {url} ")
return videos.searchVideos()

def addSongs(videoid, title, author, duration, explicit):
print(colored("\nGathering info...", 'green', attrs=['bold']), end="\r")
queue_list.append(videoid)
title_list.append(title)
author_list.append(author)
item_list.append(f"{colored(title, 'red')} - {colored(author, 'cyan')} ({duration}) {explicit}")
added = print(colored(f"{fixFormatting(title)} - ", 'cyan') + colored(f"{fixFormatting(author)}", 'red') + colored(" has been added to the queue.", 'green'))
added = print(colored(f"\n{fixFormatting(title)} - ", 'cyan') + colored(f"{fixFormatting(author)}", 'red') + colored(" has been added to the queue.", 'green'))
return songs.searchSongs()

def addVideos(videoid, title, author):
Expand All @@ -204,29 +213,4 @@ def addVideos(videoid, title, author):
added = print(colored(f"{fixFormatting(title)} - ", 'cyan') + colored(f'{fixFormatting(author)}', 'red') + colored(" has been added to the queue.", 'green'))
return videos.searchVideos()

def parseTime(s):
return time.strftime('%H:%M:%S.%MS',time.gmtime(s))

def lyricsToVtt(query):
global SUB_FILE
try:
data = requests.request("GET", f"{LYRICS_API}/lyrics?q={fixFormatting(query)}", headers=headers).text.encode()
data = json.loads(data)
SUB_FILE = "--sub-file=subs.vtt"
except:
SUB_FILE = ""
return
with open("subs.vtt", "w") as file:
file.write("WEBVTT")
file.write("\n")
for i,v in enumerate(data):
try:
file.write("\n")
file.write(f"{parseTime(v['seconds'])} --> {parseTime(data[i + 1]['seconds'])}")
file.write("\n")
file.write(f"♪ {v['lyrics']} ♪".upper())
file.write("\n")
except IndexError:
return

signal.signal(signal.SIGINT, forceQuit)
49 changes: 49 additions & 0 deletions harmony/lyrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import requests
import json
import functions

headers = {
'authorization': 'Bearer eyJraWQiOiJ2OU1GbFhqWSIsImFsZyI6IkVTMjU2In0.eyJ0eXBlIjoibzJfYWNjZXNzIiwidWlkIjoxODY5NDM0NDcsInNjb3BlIjoicl91c3Igd191c3IiLCJnVmVyIjowLCJzVmVyIjowLCJjaWQiOjIzMTAsImN1ayI6ImFiZDQzMzFmLWU4N2MtNDVhYS05OWUxLTQwNWRkNmRhNThkNyIsImV4cCI6MTY1NDQ5MDY5Nywic2lkIjoiY2ZlZDhkNzYtYmY3My00ZjU5LWIyNzQtOGRjM2ZmZjlkYWQ3IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLnRpZGFsLmNvbS92MSJ9.9z3rYDKmPi2cUi3_FgcgnsFXCOaK2t1SYfKlwk2nbFU2fdbjaixdKlLzAZRAxnZVKnFX9hsrQGaUjT8Tx3SMvw',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.78 Safari/537.36'
}

def searchLyrics(query):
url = f"https://listen.tidal.com/v1/search/top-hits?query={query}&limit=1&offset=0&types=TRACKS&includeContributors=true&countryCode=US&locale=en_US&deviceType=BROWSER"

response = requests.request("GET", url, headers=headers).text.encode()

result = json.loads(response)

track_id = result['tracks']['items'][0]['id']

return getLyrics(track_id)

def getLyrics(trackid):

url = f"https://listen.tidal.com/v1/tracks/{trackid}/lyrics?countryCode=US&locale=en_US&deviceType=BROWSER"

try:
response = requests.request("GET", url, headers=headers).text.encode()

result = json.loads(response)

data = result['subtitles'].split("\n")

dataList = result["subtitles"].split("\n")
dataDict1 = {line[:10]: line[10:] for line in dataList}
except:
functions.SUB_FILE = ""
return
return lyricsToVtt(dataDict1)

def lyricsToVtt(data):
with open("subs.vtt", "w") as file:
file.write("WEBVTT")
file.write("\n")
for (start, text), end in zip(data.items(), list(data.keys())[1:] + [1]):
try:
functions.SUB_FILE = "--sub-file=subs.vtt"
file.write("\n")
file.write(f"{str(start).strip('[]')} --> {str(end).strip('[]')}\n{text}\n")
except IndexError:
return
2 changes: 1 addition & 1 deletion harmony/songs.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def pickTrack(song, json):

videoid = json['results'][int(option) - 1]['downloadUrl'][4]['link']
title = json['results'][int(option) - 1]['name']
author = json['results'][int(option) - 1]['primaryArtists']
author = json['results'][int(option) - 1]['primaryArtists'].split(',', 1)[0]
duration = time.strftime('%M:%S',time.gmtime(int(json['results'][int(option) - 1]['duration'])))
explicit = functions.isExplicit(json['results'][int(option) - 1]['explicitContent'])

Expand Down

0 comments on commit 3df1525

Please sign in to comment.