[PR #921] [CLOSED] Added feature to fetch song lyrics #1091

Closed
opened 2026-02-28 14:54:25 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/Rigellute/spotify-tui/pull/921
Author: @giorgioskij
Created: 12/2/2021
Status: Closed

Base: masterHead: lyrics


📝 Commits (7)

  • e7de1cf add basic lyrics implementation
  • 8ba01f8 first working implementation
  • e47f526 refactor and clean code
  • 7a2448f remove unnecessary stuff - mostly comments
  • 02f377b bugfix
  • 4b0c088 removed every comment marking new features
  • de9516a added help entry for the new shortcut

📊 Changes

11 files changed (+743 additions, -460 deletions)

View changed files

📝 Cargo.lock (+497 -460)
📝 Cargo.toml (+1 -0)
📝 src/app.rs (+4 -0)
📝 src/handlers/common_key_events.rs (+3 -0)
📝 src/handlers/empty.rs (+2 -0)
src/handlers/lyrics.rs (+96 -0)
📝 src/handlers/mod.rs (+25 -0)
📝 src/network.rs (+48 -0)
📝 src/ui/help.rs (+5 -0)
📝 src/ui/mod.rs (+58 -0)
📝 src/user_config.rs (+4 -0)

📄 Description

Support for fetching song lyrics

I've been using this great tool for a while, and I was curious whether it would be possible to add a section that displays the lyrics of the song that's currently playing, so I decided to implement it: even if it's not one of the most important missing features listed on the readme, I thought that it would have been a pretty nice addition to improve the overall experience for many users like me.

Approach to the implementation

My main concerns and goals about the implementation of this feature were:

  • First of all, not to damage in any way the current behaviour of the program: if a user doesn't want to use the lyrics function, the TUI needs to function in the exact same way as before. I made sure therefore that my code doesn't slow down any operation and can never panic. Every error is handled and results in a message saying "No lyrics were found for the current song".
  • Secondly, not to introduce any overhead in the installation process: many lyrics APIs, like Genius or Musixmatch, require an authorization token. This means that during installation, a user would need to provide both the Spotify token and the token for the lyrics provider. To avoid this, I used the open source lyrics APIs provided by lyrics.ovh. The project is available here. In my opinion, since lyrics are not an essential feature, it was much better to use an archive not as complete as commercial ones, but that doesn't require authentication nor impose request limits.

Something to consider, and its solution.

Any API to fetch the lyrics is obviously not guaranteed to be available forever, and may interrupt its service at any time, just as Spotify could. Therefore, unless Spotify provides their personal API to fetch lyrics, this separation is unavoidable. What we can do to be prepared for any circumstance is to have an implementation that is easy to adapt and extend. Anything that is related or specific to the API we are currently using is contained in a single small function: to replace the api provider or just disable the lyrics service, it is only needed to modify that function.

How it works

The way to implement this that I found to be most cohesive and unobtrusive was to add a block just like the welcome, album or artist view, that integrates in the navigation_stack. In this way, the shorcut (I opted for <ctrl+l>) brings up the new lyrics window, that can be scrolled with the usual keys. Just like a playlist, album, or artist section, it stays in view until a new window is opened, or until q is pressed to go back in the stack.

Final result

Lyrics found

spotify-tui-lyrics

Lyrics not found (in this case, it is an instrumental song)

spotify-tui-lyrics-not-found

Summary of the new code

In line with the principles defined previously, I did not change anything of the previously existing code. I am not an experienced Rust developer, but thanks to a perfectly robust and scalable implementation (for real, the quality of the code was amazing and very easy to understand and integrate!), I was able to add the new window by following the same exact patterns used for the other windows and sections, so basically I didn't write any new logic, I only extended what was already present.

What I added to project structure

  • The only actual logic I added was in the function send_lyrics_request inside network.rs. Here, I send the http request, parse the received json, and return an Option<String> with the fetched lyrics. This could have been done in a separate module kept in a separate file, but I thought that in this case, since it is only a single function, it is probably better to avoid introducing unnecessary complications.
  • The only external dependency I added was ureq, which was obviously needed to perform the http request.
  • I only added one file, which is lyrics.rs containing the handler for the lyrics component.

I hope you find this contribution useful, once again thanks a lot for bringing to life this great project. I sure had a lot of fun putting my hands on it! As i said, I am not very experienced with Rust, so I am definitely willing to put some time in to adjust the implementation in any way you think might be needed.

Giorgio


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/Rigellute/spotify-tui/pull/921 **Author:** [@giorgioskij](https://github.com/giorgioskij) **Created:** 12/2/2021 **Status:** ❌ Closed **Base:** `master` ← **Head:** `lyrics` --- ### 📝 Commits (7) - [`e7de1cf`](https://github.com/Rigellute/spotify-tui/commit/e7de1cfdb093f2ad13e0322f465cc31b265c3ede) add basic lyrics implementation - [`8ba01f8`](https://github.com/Rigellute/spotify-tui/commit/8ba01f8338fa2233015bcc296c6285e91b5224e6) first working implementation - [`e47f526`](https://github.com/Rigellute/spotify-tui/commit/e47f526e75ab4d781983c63635ce58698b2780d3) refactor and clean code - [`7a2448f`](https://github.com/Rigellute/spotify-tui/commit/7a2448fee9bf390494f76f374146c3df8d37958e) remove unnecessary stuff - mostly comments - [`02f377b`](https://github.com/Rigellute/spotify-tui/commit/02f377bc782ce2b4703f9ba67b3204a89a10e5d5) bugfix - [`4b0c088`](https://github.com/Rigellute/spotify-tui/commit/4b0c08850e13c09c2368495abbc2c318220ef40a) removed every comment marking new features - [`de9516a`](https://github.com/Rigellute/spotify-tui/commit/de9516a1cf1e70a45f798725a696710d5df55cf9) added help entry for the new shortcut ### 📊 Changes **11 files changed** (+743 additions, -460 deletions) <details> <summary>View changed files</summary> 📝 `Cargo.lock` (+497 -460) 📝 `Cargo.toml` (+1 -0) 📝 `src/app.rs` (+4 -0) 📝 `src/handlers/common_key_events.rs` (+3 -0) 📝 `src/handlers/empty.rs` (+2 -0) ➕ `src/handlers/lyrics.rs` (+96 -0) 📝 `src/handlers/mod.rs` (+25 -0) 📝 `src/network.rs` (+48 -0) 📝 `src/ui/help.rs` (+5 -0) 📝 `src/ui/mod.rs` (+58 -0) 📝 `src/user_config.rs` (+4 -0) </details> ### 📄 Description # Support for fetching song lyrics I've been using this great tool for a while, and I was curious whether it would be possible to add a section that displays the lyrics of the song that's currently playing, so I decided to implement it: even if it's not one of the most important missing features listed on the readme, I thought that it would have been a pretty nice addition to improve the overall experience for many users like me. ## Approach to the implementation My main concerns and goals about the implementation of this feature were: - First of all, not to damage in any way the current behaviour of the program: if a user doesn't want to use the lyrics function, the TUI needs to function in the exact same way as before. I made sure therefore that my code doesn't slow down any operation and can never panic. Every error is handled and results in a message saying "No lyrics were found for the current song". - Secondly, not to introduce any overhead in the installation process: many lyrics APIs, like *Genius* or *Musixmatch*, require an authorization token. This means that during installation, a user would need to provide both the Spotify token and the token for the lyrics provider. To avoid this, I used the open source lyrics APIs provided by [lyrics.ovh](https://lyrics.ovh/). The project is available [here](https://github.com/NTag/lyrics.ovh). In my opinion, since lyrics are not an essential feature, it was much better to use an archive not as complete as commercial ones, but that doesn't require authentication nor impose request limits. ### Something to consider, and its solution. Any API to fetch the lyrics is obviously not guaranteed to be available forever, and may interrupt its service at any time, just as Spotify could. Therefore, unless Spotify provides their personal API to fetch lyrics, this separation is unavoidable. What we can do to be prepared for any circumstance is to have an implementation that is easy to adapt and extend. Anything that is related or specific to the API we are currently using is contained in a single small function: to replace the api provider or just disable the lyrics service, it is only needed to modify that function. ## How it works The way to implement this that I found to be most cohesive and unobtrusive was to add a block just like the welcome, album or artist view, that integrates in the `navigation_stack`. In this way, the shorcut (I opted for `<ctrl+l>`) brings up the new lyrics window, that can be scrolled with the usual keys. Just like a playlist, album, or artist section, it stays in view until a new window is opened, or until `q` is pressed to go back in the stack. ## Final result #### Lyrics found ![spotify-tui-lyrics](https://user-images.githubusercontent.com/46194839/144444012-7daa435b-dd07-4fd4-8e72-94df0732b32c.png) #### Lyrics not found (in this case, it is an instrumental song) ![spotify-tui-lyrics-not-found](https://user-images.githubusercontent.com/46194839/144444027-fac6e5f3-634e-477d-80da-9ee45cb99ca2.png) ## Summary of the new code In line with the principles defined previously, I did not change anything of the previously existing code. I am not an experienced Rust developer, but thanks to a perfectly robust and scalable implementation (for real, the quality of the code was amazing and very easy to understand and integrate!), I was able to add the new window by following the same exact patterns used for the other windows and sections, so basically I didn't write any new logic, I only extended what was already present. ### What I added to project structure - The only actual logic I added was in the function `send_lyrics_request` inside `network.rs`. Here, I send the http request, parse the received json, and return an `Option<String>` with the fetched lyrics. This could have been done in a separate module kept in a separate file, but I thought that in this case, since it is only a single function, it is probably better to avoid introducing unnecessary complications. - The only external dependency I added was `ureq`, which was obviously needed to perform the http request. - I only added one file, which is `lyrics.rs` containing the handler for the lyrics component. <hr> I hope you find this contribution useful, once again thanks a lot for bringing to life this great project. I sure had a lot of fun putting my hands on it! As i said, I am not very experienced with Rust, so I am definitely willing to put some time in to adjust the implementation in any way you think might be needed. Giorgio --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-02-28 14:54:25 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/spotify-tui#1091
No description provided.