如何在waybar显示spotify当前歌曲歌词

2024-11-15

基本需求

Linux一直找不到好用的歌词工具,我希望能够在waybar中间显示一下当前播放歌曲的歌词,为此应该需要一个插件/脚本。

必要条件

waybar实现歌词的显示的脚本应当需要以下两个条件:

  1. 知道当前歌曲或者歌词(没有歌词的话应该从某处获取当前歌词,比如互联网)。
  2. 知道当前歌曲播放的进度,以确定当前显示哪句歌词。

实现思路

MPRIS协议与playerctl

  1. MPRIS (媒体播放器远程接口规范) 是一个标准的 D-Bus 接口,旨在提供用于控制媒体播放器的通用编程API。
  2. playerctl 则是使用此协议的命令行工具。 有了上述的两个工具,我们就可以简单地获取当前歌曲播放的元数据以及进度信息,具体参考相关wiki。
playerctl获取的信息不太对?

很容易遇到这个问题,原因在于其实可能浏览器也在播放某些音频,在playerctl中指定播放器就可以了。

playerctl --player=spotify play

开放的互联网歌词接口

很遗憾spotify官方API要premium,没什么办法,还得去找伟大的互联网白嫖。 在对比了几个API之后,LrcAPI提供免费服务,所以就使用了这个接口。 而API参数中需要的一些参数,均可通过playerctl metadata获取

实现

实现脚本

没什么值得描述的,看代码就是了:

#!/bin/bash

# 检查文件夹是否存在
if [ ! -d "$HOME/.cache/lrc/" ]; then
	# 如果不存在,则创建文件夹
	mkdir -p "$HOME/.cache/lrc/"
fi

player=spotify
while true; do
	title=$(playerctl --player=$player metadata title)
	album=$(playerctl --player=$player metadata album)
	artist=$(playerctl --player=$player metadata artist)

	cache_file_path="$HOME/.cache/lrc/$artist-$album-$title.lrc"

	# 检查缓存文件是否存在
	if [ ! -f "$cache_file_path" ]; then
		# 如果不存在,从API下载歌词
		url="https://api.lrc.cx/api/v1/lyrics/single?title=$(urlencode "$title")&album=$(urlencode "$album")&artist=$(urlencode "$artist")"
		# 使用 curl 下载歌词
		curl -s "$url" -o "$cache_file_path"
	fi

	position=$(playerctl --player=$player position)

	# 读入歌词文件,查找小于等于给定位置的最近歌词
	lyrics_line=$(awk -v position="$position" '
                {
                    # 解析当前行的时间
                    split($0, time_and_lyric, "]")
                    time = time_and_lyric[1]
              lyric = time_and_lyric[2]
                    gsub("[[]", "", time) # 去掉左方括号

                    # 转换时间为秒
                    split(time, min_sec, ":")
                    total_seconds = min_sec[1] * 60 + min_sec[2]

                    # 如果时间小于等于位置,更新最近的歌词
                    if (total_seconds <= position) {
                        last_lyric = lyric
                    }
                }
                END {
                    # 输出找到的最近歌词
                    print last_lyric
                }
            ' "$cache_file_path")

	# 输出找到的歌词行
	echo "$lyrics_line"
	sleep 0.2
done

配置为waybar插件

这里作出如下配置,注意路径是通过 Nix 的函数生成的。 在通常的发行版下,填入上节脚本的实际路径就可以了,比如 /home/user/.config/waybar/lrc.sh 。

 "custom/lyric": {
   "exec": "/nix/store/cbr9pj56a61haclyshgmc309zx3fq7vd-get-lyric.sh",
   "format": "{}"
 }

后续应当加上exec-if条件来使用这个脚本,这是一个优化点。

总结

得益于waybar的扩展性以及无私的互联网精神,以及伟大AI的专业指导,使得这个小插件的编写并没什么阻碍。

参考与引用

  1. MPRIS
  2. playerctl
  3. LrcAPI