Added embedding lyrics to tracks (#129)

* add lyrics api endpoint

* embed lyrics in metadata

* add embed lyrics option
This commit is contained in:
Oskar Dudziński
2025-06-03 16:40:14 +02:00
committed by GitHub
parent ed0918e7b0
commit 7258df8ec8
6 changed files with 54 additions and 6 deletions
+5
View File
@@ -83,6 +83,11 @@ class TestApi(unittest.TestCase):
def test_video_stream(self):
self.api.getVideoStream(373513584)
def test_lyrics(self):
track_id = 103805726
lyrics = self.api.getLyrics(track_id)
self.assertEqual(lyrics.trackId, track_id)
if __name__ == "__main__":
unittest.main()
+6
View File
@@ -26,6 +26,7 @@ from tiddl.models.api import (
TrackStream,
Video,
VideoStream,
Lyrics
)
from tiddl.models.constants import TrackQuality
@@ -218,6 +219,11 @@ class TidalApi:
SessionResponse, "sessions", expire_after=DO_NOT_CACHE
)
def getLyrics(self, track_id: str | int):
return self.fetch(
Lyrics, f"tracks/{track_id}/lyrics", {"countryCode": self.country_code}
)
def getTrack(self, track_id: str | int):
return self.fetch(
Track, f"tracks/{track_id}", {"countryCode": self.country_code}
+16 -1
View File
@@ -80,6 +80,13 @@ from typing import List, Union
type=click.Choice(SinglesFilter.__args__),
help="Defines how to treat artist EPs and singles, used while downloading artist.",
)
@click.option(
"--lyrics",
"-l",
"EMBED_LYRICS",
is_flag=True,
help="Embed track lyrics in file metadata.",
)
@passContext
def DownloadCommand(
ctx: Context,
@@ -89,10 +96,12 @@ def DownloadCommand(
THREADS_COUNT: int,
DO_NOT_SKIP: bool,
SINGLES_FILTER: SinglesFilter,
EMBED_LYRICS: bool
):
"""Download resources"""
SINGLES_FILTER = SINGLES_FILTER or ctx.obj.config.download.singles_filter
EMBED_LYRICS = EMBED_LYRICS or ctx.obj.config.download.embed_lyrics
# TODO: pretty print
logging.debug(
@@ -103,6 +112,7 @@ def DownloadCommand(
THREADS_COUNT,
DO_NOT_SKIP,
SINGLES_FILTER,
EMBED_LYRICS
)
)
@@ -201,9 +211,14 @@ def DownloadCommand(
if not cover_data and item.album.cover:
cover_data = Cover(item.album.cover).content
if EMBED_LYRICS:
lyrics_subtitles = api.getLyrics(item.id).subtitles
else:
lyrics_subtitles = ""
try:
addMetadata(path, item, cover_data, credits, album_artist=album_artist)
addMetadata(path, item, cover_data, credits, album_artist=album_artist, lyrics=lyrics_subtitles)
except Exception as e:
logging.error(f"Can not add metadata to: {path}, {e}")
+1
View File
@@ -27,6 +27,7 @@ class DownloadConfig(BaseModel):
path: Path = Path.home() / "Music" / "Tiddl"
threads: int = 4
singles_filter: SinglesFilter = "none"
embed_lyrics: bool = False
class AuthConfig(BaseModel):
+15 -5
View File
@@ -24,6 +24,7 @@ def addMetadata(
cover_data=b"",
credits: List[AlbumItemsCredits.ItemWithCredits.CreditsEntry] = [],
album_artist="",
lyrics="",
):
logger.debug((track_path, track.id))
@@ -76,13 +77,22 @@ def addMetadata(
contributor.name for contributor in entry.contributors
]
if lyrics:
metadata["LYRICS"] = lyrics
elif extension == ".m4a":
if cover_data:
if lyrics or cover_data:
metadata = MutagenMP4(track_path)
metadata["covr"] = [
MP4Cover(cover_data, imageformat=MP4Cover.FORMAT_JPEG)
]
metadata.save(track_path)
if lyrics:
metadata["\xa9lyr"] = [lyrics]
if cover_data:
metadata["covr"] = [
MP4Cover(cover_data, imageformat=MP4Cover.FORMAT_JPEG)
]
metadata.save()
metadata = MutagenEasyMP4(track_path)
metadata.update(
+11
View File
@@ -11,6 +11,7 @@ __all__ = [
"Favorites",
"TrackStream",
"Search",
"Lyrics"
]
@@ -167,3 +168,13 @@ class Search(BaseModel):
tracks: Tracks
videos: Videos
topHit: Optional[TopHit] = None
class Lyrics(BaseModel):
isRightToLeft: bool
lyrics: str
lyricsProvider: str
providerCommontrackId: str
providerLyricsId: str
subtitles: str
trackId: int