基本需求
Linux一直找不到好用的歌词工具,我希望能够在waybar中间显示一下当前播放歌曲的歌词,为此应该需要一个插件/脚本。
必要条件
waybar实现歌词的显示的脚本应当需要以下两个条件:
- 知道当前歌曲或者歌词(没有歌词的话应该从某处获取当前歌词,比如互联网)。
- 知道当前歌曲播放的进度,以确定当前显示哪句歌词。
实现思路
MPRIS协议与playerctl
- MPRIS (媒体播放器远程接口规范) 是一个标准的 D-Bus 接口,旨在提供用于控制媒体播放器的通用编程API。
- 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的专业指导,使得这个小插件的编写并没什么阻碍。