[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fetching synchronized lyrics from LRCLIB
From: |
Daniel Semyonov |
Subject: |
Fetching synchronized lyrics from LRCLIB |
Date: |
Thu, 28 Nov 2024 02:06:17 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
Hi,
For a while I had a some code in my EMMS config for fetching synced
lyrics from LRCLIB (lrclib.net).
The main function can be used both interactively and as a track
initialization function (interactively it fetches lyrics, optionally
overwriting, for the currently playing track).
This service used to be non-free, though the developer promised to free
it at some point in the future.
Well, it turns out this actually happened (in April actually, I didn't
notice), and the server software is now licensed under MIT, so I
separated this code into its own file and integrated it into EMMS (patch
attached).
I think this will be a nice addition to EMMS, should this be added?
Daniel
>From b2b64c7d41e35434fc6ce36228eb4dadb84e43ac Mon Sep 17 00:00:00 2001
From: Daniel Semyonov <daniel@dsemy.com>
Date: Thu, 28 Nov 2024 01:49:13 +0200
Subject: [PATCH] Add an EMMS module for fetching synchronized lyrics from
LRCLIB
---
emms-lyrics-lrclib.el | 113 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 emms-lyrics-lrclib.el
diff --git a/emms-lyrics-lrclib.el b/emms-lyrics-lrclib.el
new file mode 100644
index 0000000..272f6cb
--- /dev/null
+++ b/emms-lyrics-lrclib.el
@@ -0,0 +1,113 @@
+;;; emms-lyrics-lrclib.el --- Fetch synchronized lyrics through LRCLIB -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2024 Free Software Foundation, Inc.
+
+;; Author: Daniel Semyonov <daniel@dsemy.com>
+
+;; This file is part of EMMS.
+
+;; EMMS is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; EMMS is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with EMMS; see the file COPYING. If not, write to the Free
+;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file provides a command/track initialization function which
+;; automatically fetches synchronized lyrics for tracks (the current
+;; track interactively) through an LRCLIB server.
+
+;;; Code:
+
+(require 'emms-lyrics)
+(require 'emms-later-do)
+
+(defgroup emms-lyrics-lrclib nil
+ "EMMS module for fetching synchronized lyrics through LRCLIB servers."
+ :group 'emms-lyrics
+ :prefix "emms-lyrics-lrclib-")
+
+(defcustom emms-lyrics-lrclib-url "https://lrclib.net/api/"
+ "Base URL for LRCLIB API requests."
+ :type 'string)
+
+(defconst emms-lyrics-lrclib-max-requests 250
+ "Maximum number of concurrent requests to LRCLIB.")
+
+(defvar emms-lyrics-lrclib-requests 0
+ "Current number of concurrent requests to LRCLIB.")
+
+(defun emms-lyrics-lrclib-encode-name (name)
+ "Encode (artist/album/track) NAME for an LRCLIB search."
+ (and (stringp name) (string-replace " " "+" name)))
+
+(defun emms-lyrics-lrclib-parse (_ file track interactive)
+ "Parse and save synced lyrics in FILE.
+If TRACK is the selected track in the current playlist, catch up.
+When INTERACTIVE is non-nil, display messages and confirm overwrite."
+ (unwind-protect
+ (progn
+ (search-forward "\n\n")
+ (let* ((p (json-parse-buffer))
+ (lyrics (and (hash-table-p p) (gethash "syncedLyrics" p))))
+ (if (not (stringp lyrics))
+ (when interactive (message "No lyrics found"))
+ (or
+ (and (file-exists-p file) interactive
+ (not (y-or-n-p
+ (format "Overwrite existing file (\"%s\")?" file))))
+ (with-temp-file file
+ (insert (gethash "syncedLyrics" p))
+ (when interactive
+ (message "Saves synced lyrics at \"%s\"" file))
+ (and (boundp 'emms-lyrics-display-p)
+ emms-lyrics-display-p emms-player-playing-p
+ (equal track (emms-playlist-current-selected-track))
+ (emms-lyrics-catchup file)))))))
+ (setq emms-lyrics-lrclib-requests (1- emms-lyrics-lrclib-requests))))
+
+;;;###autoload
+(defun emms-lyrics-lrclib-get (&optional track force interactive)
+ "Search for synchronized lyrics for TRACK through LRCLIB's API.
+If TRACK is omitted or nil, try the selected track in the current playlist.
+The lyrics are saved in an \".lrc\" file alongside the track, unless the
+file already exists (in which case the search isn't performed).
+With non-nil FORCE, overwrite existing \".lrc\" files.
+With non-nil INTERACTIVE, display messages and confirm overwrite."
+ (interactive (list nil current-prefix-arg t))
+ (if (> emms-lyrics-lrclib-requests emms-lyrics-lrclib-max-requests)
+ (emms-later-do #'emms-lyrics-lrclib-get track force interactive)
+ (when-let* ((track (or track (emms-playlist-current-selected-track)))
+ ((eq (emms-track-type track) 'file))
+ (file (emms-track-name track))
+ (lrc (replace-regexp-in-string "\\.[^.]+\\'" ".lrc" file))
+ ((or force (not (file-exists-p lrc))))
+ (file-writable-p lrc)
+ (title (emms-lyrics-lrclib-encode-name
+ (emms-track-get track 'info-title)))
+ (artist (emms-lyrics-lrclib-encode-name
+ (emms-track-get track 'info-artist)))
+ (album (emms-lyrics-lrclib-encode-name
+ (emms-track-get track 'info-album)))
+ (time (emms-track-get track 'info-playing-time)))
+ (setq emms-lyrics-lrclib-requests (1+ emms-lyrics-lrclib-requests))
+ (when interactive (message "Searching for lyrics..."))
+ (url-retrieve
+ (url-encode-url
+ (format "%sget?artist_name=%s&track_name=%s&album_name=%s&duration=%d"
+ emms-lyrics-lrclib-url artist title album time))
+ #'emms-lyrics-lrclib-parse (list lrc track interactive)))))
+
+(provide 'emms-lyrics-lrclib)
+
+;;; emms-lyrics-lrclib.el ends here
--
2.47.0
- Fetching synchronized lyrics from LRCLIB,
Daniel Semyonov <=
- Re: Fetching synchronized lyrics from LRCLIB, Yoni Rabkin, 2024/11/27
- Re: Fetching synchronized lyrics from LRCLIB, Daniel Semyonov, 2024/11/27
- Re: Fetching synchronized lyrics from LRCLIB, Yoni Rabkin, 2024/11/28
- Re: Fetching synchronized lyrics from LRCLIB, Daniel Semyonov, 2024/11/28
- Re: Fetching synchronized lyrics from LRCLIB, Yoni Rabkin, 2024/11/28
- Re: Fetching synchronized lyrics from LRCLIB, Daniel Semyonov, 2024/11/28
- Re: Fetching synchronized lyrics from LRCLIB, Yoni Rabkin, 2024/11/28
- Re: Fetching synchronized lyrics from LRCLIB, Daniel Semyonov, 2024/11/29