mirror of
https://github.com/tcsenpai/swingmusic.git
synced 2025-06-07 03:35:35 +00:00
support lyrics from tags
This commit is contained in:
parent
9c0d4e91de
commit
a3281300d0
@ -1,6 +1,11 @@
|
|||||||
from flask import Blueprint, request
|
from flask import Blueprint, request
|
||||||
|
|
||||||
from app.lib.lyrics import get_lyrics, check_lyrics_file, get_lyrics_from_duplicates
|
from app.lib.lyrics import (
|
||||||
|
get_lyrics,
|
||||||
|
check_lyrics_file,
|
||||||
|
get_lyrics_from_duplicates,
|
||||||
|
get_lyrics_from_tags,
|
||||||
|
)
|
||||||
|
|
||||||
api = Blueprint("lyrics", __name__, url_prefix="")
|
api = Blueprint("lyrics", __name__, url_prefix="")
|
||||||
|
|
||||||
@ -18,15 +23,19 @@ def send_lyrics():
|
|||||||
if filepath is None or trackhash is None:
|
if filepath is None or trackhash is None:
|
||||||
return {"error": "No filepath or trackhash provided"}, 400
|
return {"error": "No filepath or trackhash provided"}, 400
|
||||||
|
|
||||||
lyrics = get_lyrics(filepath)
|
is_synced = True
|
||||||
|
lyrics, copyright = get_lyrics(filepath)
|
||||||
|
|
||||||
if lyrics is None:
|
if not lyrics:
|
||||||
lyrics = get_lyrics_from_duplicates(trackhash, filepath)
|
lyrics, copyright = get_lyrics_from_duplicates(trackhash, filepath)
|
||||||
|
|
||||||
if lyrics is None:
|
if not lyrics:
|
||||||
|
lyrics, is_synced, copyright = get_lyrics_from_tags(filepath)
|
||||||
|
|
||||||
|
if not lyrics:
|
||||||
return {"error": "No lyrics found"}, 204
|
return {"error": "No lyrics found"}, 204
|
||||||
|
|
||||||
return {"lyrics": lyrics}, 200
|
return {"lyrics": lyrics, "synced": is_synced, "copyright": copyright}, 200
|
||||||
|
|
||||||
|
|
||||||
@api.route("/lyrics/check", methods=["POST"])
|
@api.route("/lyrics/check", methods=["POST"])
|
||||||
@ -39,9 +48,11 @@ def check_lyrics():
|
|||||||
if filepath is None or trackhash is None:
|
if filepath is None or trackhash is None:
|
||||||
return {"error": "No filepath or trackhash provided"}, 400
|
return {"error": "No filepath or trackhash provided"}, 400
|
||||||
|
|
||||||
exists, filepath = check_lyrics_file(filepath, trackhash)
|
exists = check_lyrics_file(filepath, trackhash)
|
||||||
|
|
||||||
if exists:
|
if exists:
|
||||||
return {"filepath": filepath}, 200
|
return {"exists": exists}, 200
|
||||||
|
|
||||||
return {"filepath": None}
|
exists = get_lyrics_from_tags(filepath, just_check=True)
|
||||||
|
|
||||||
|
return {"exists": exists}, 200
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from tinytag import TinyTag
|
||||||
|
|
||||||
from app.store.tracks import TrackStore
|
from app.store.tracks import TrackStore
|
||||||
|
|
||||||
filepath = "/home/cwilvx/Music/Editor's Pick/Bad Day 😢/6 Dogs - Crying in the Rarri.m4a"
|
filepath = "/home/cwilvx/Music/Editor's Pick/Bad Day 😢/6 Dogs - Crying in the Rarri.m4a"
|
||||||
|
# filepath = "/home/cwilvx/Music/90s/Ballads/All-4-One - I Swear.mp3"
|
||||||
|
filepath = "/home/cwilvx/Music/Afrobeats/Kabusa Oriental Choir/Kabusa Oriental Choir - Bandana.m4a"
|
||||||
|
|
||||||
|
|
||||||
def split_line(line: str):
|
def split_line(line: str):
|
||||||
@ -22,19 +26,33 @@ def convert_to_milliseconds(time: str):
|
|||||||
return int(milliseconds)
|
return int(milliseconds)
|
||||||
|
|
||||||
|
|
||||||
|
def format_synced_lyrics(lines: list[str]):
|
||||||
|
"""
|
||||||
|
Formats synced lyrics into a list of dicts
|
||||||
|
"""
|
||||||
|
lyrics = []
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
# if line starts with [ and ends with ] .ie. ID3 tag, skip it
|
||||||
|
if line.startswith("[") and line.endswith("]"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# if line does not start with [ skip it
|
||||||
|
if not line.startswith("["):
|
||||||
|
continue
|
||||||
|
|
||||||
|
time, lyric = split_line(line)
|
||||||
|
milliseconds = convert_to_milliseconds(time)
|
||||||
|
|
||||||
|
lyrics.append({"time": milliseconds, "text": lyric})
|
||||||
|
|
||||||
|
return lyrics
|
||||||
|
|
||||||
|
|
||||||
def get_lyrics_from_lrc(filepath: str):
|
def get_lyrics_from_lrc(filepath: str):
|
||||||
with open(filepath, mode="r") as file:
|
with open(filepath, mode="r") as file:
|
||||||
lines = (f.removesuffix("\n") for f in file.readlines())
|
lines = (f.removesuffix("\n") for f in file.readlines())
|
||||||
|
return format_synced_lyrics(lines)
|
||||||
lyrics = []
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
time, lyric = split_line(line)
|
|
||||||
milliseconds = convert_to_milliseconds(time)
|
|
||||||
|
|
||||||
lyrics.append({"time": milliseconds, "text": lyric})
|
|
||||||
|
|
||||||
return lyrics
|
|
||||||
|
|
||||||
|
|
||||||
def get_lyrics_file_rel_to_track(filepath: str):
|
def get_lyrics_file_rel_to_track(filepath: str):
|
||||||
@ -66,9 +84,12 @@ def get_lyrics(track_path: str):
|
|||||||
lyrics_path = get_lyrics_file_rel_to_track(track_path)
|
lyrics_path = get_lyrics_file_rel_to_track(track_path)
|
||||||
|
|
||||||
if lyrics_path:
|
if lyrics_path:
|
||||||
return get_lyrics_from_lrc(lyrics_path)
|
lyrics = get_lyrics_from_lrc(lyrics_path)
|
||||||
|
copyright = get_extras(track_path, ["copyright"])
|
||||||
|
|
||||||
|
return lyrics, copyright[0]
|
||||||
else:
|
else:
|
||||||
return None
|
return None, ""
|
||||||
|
|
||||||
|
|
||||||
def get_lyrics_from_duplicates(trackhash: str, filepath: str):
|
def get_lyrics_from_duplicates(trackhash: str, filepath: str):
|
||||||
@ -78,23 +99,69 @@ def get_lyrics_from_duplicates(trackhash: str, filepath: str):
|
|||||||
|
|
||||||
for track in TrackStore.tracks:
|
for track in TrackStore.tracks:
|
||||||
if track.trackhash == trackhash and track.filepath != filepath:
|
if track.trackhash == trackhash and track.filepath != filepath:
|
||||||
lyrics = get_lyrics(track.filepath)
|
lyrics, copyright = get_lyrics(track.filepath)
|
||||||
|
|
||||||
if lyrics:
|
if lyrics:
|
||||||
return lyrics
|
return lyrics, copyright
|
||||||
|
|
||||||
|
return None, ""
|
||||||
|
|
||||||
|
|
||||||
def check_lyrics_file(filepath: str, trackhash: str):
|
def check_lyrics_file(filepath: str, trackhash: str):
|
||||||
lyrics_exists = check_lyrics_file_rel_to_track(filepath)
|
lyrics_exists = check_lyrics_file_rel_to_track(filepath)
|
||||||
|
|
||||||
if lyrics_exists:
|
if lyrics_exists:
|
||||||
return True, filepath
|
return True
|
||||||
|
|
||||||
for track in TrackStore.tracks:
|
for track in TrackStore.tracks:
|
||||||
if track.trackhash == trackhash and track.filepath != filepath:
|
if track.trackhash == trackhash and track.filepath != filepath:
|
||||||
lyrics_exists = check_lyrics_file_rel_to_track(track.filepath)
|
lyrics_exists = check_lyrics_file_rel_to_track(track.filepath)
|
||||||
|
|
||||||
if lyrics_exists:
|
if lyrics_exists:
|
||||||
return True, track.filepath
|
return True
|
||||||
|
|
||||||
return False, None
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_synced(lyrics: list[str]):
|
||||||
|
# try to split lines and get milliseconds
|
||||||
|
# if any passes, return True
|
||||||
|
|
||||||
|
for line in lyrics:
|
||||||
|
time, _ = split_line(line)
|
||||||
|
milliseconds = convert_to_milliseconds(time)
|
||||||
|
|
||||||
|
if milliseconds != 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_extras(filepath: str, keys: list[str]):
|
||||||
|
tags = TinyTag.get(filepath)
|
||||||
|
extras = tags.extra
|
||||||
|
|
||||||
|
return [extras.get(key, "").strip() for key in keys]
|
||||||
|
|
||||||
|
|
||||||
|
def get_lyrics_from_tags(filepath: str, just_check: bool = False):
|
||||||
|
"""
|
||||||
|
Gets the lyrics from the tags of the track
|
||||||
|
"""
|
||||||
|
lyrics, copyright = get_extras(filepath, ["lyrics", "copyright"])
|
||||||
|
lyrics = lyrics.replace("engdesc", "")
|
||||||
|
exists = bool(lyrics.replace("\n", "").strip())
|
||||||
|
|
||||||
|
if just_check:
|
||||||
|
return exists
|
||||||
|
|
||||||
|
if not exists:
|
||||||
|
return None, False, ""
|
||||||
|
|
||||||
|
lines = lyrics.split("\n")
|
||||||
|
synced = test_is_synced(lines[:15])
|
||||||
|
|
||||||
|
if synced:
|
||||||
|
return format_synced_lyrics(lines), synced, copyright
|
||||||
|
|
||||||
|
return lines, synced, copyright
|
||||||
|
Loading…
x
Reference in New Issue
Block a user