前言
前言的前言
欢迎大家关注我的 bilibili 帐号:bili-Amazingrise
不定期直播搬砖,游戏,或者其他有趣的东西~
缘由
为了能在直播的时候,显示我正在播放的歌曲,我想了很多的方法。
看到了 KDE Connect 里面能显示正在播放的歌曲,我觉得一定可以很容易地获取到当前媒体的状态信息。
另外,这篇文章的诞生也是受到这位的启发:获取 macOS 网易云音乐的正在播放 —— 使用 LLDB 验证思路 (没错,就是这个主题的原作者。)
正文
原理
当然,我们的 Linux 没有那么复杂,用一个 Shell 脚本就能读取到当前播放的媒体。
由于 OBS Studio 支持从文本文件读取文字内容,并且显示在输出流上,我们可以用 Shell 脚本先读出当前播放的媒体信息,然后再将它写入某个文件里,最后让 OBS Studio 读取这个文件就可以了。
以我用的 Electron Netease Cloud Music 为例。
在 Linux 中,显示正在播放是通过调用 dbus mpris API 实现的。
仔细看该项目的源代码,可以找到这几行:
const i = {
name(suffix) {
if (suffix) return `org.mpris.MediaPlayer2.${suffix}`;
return 'org.mpris.MediaPlayer2';
},
path(suffix) {
if (suffix) return `/org/mpris/MediaPlayer2/${suffix}`;
return '/org/mpris/MediaPlayer2';
}
};
我们可以获取到它的 dbus 路径(?暂且这么称呼),这个在后面会有用。
那么当前媒体的元数据(metadata)的形式是怎么样的呢?
于是我们用上面获取到的 dbus 路径,来获取到当前媒体的元数据。
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.ElectronNCM /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:org.mpris.MediaPlayer2.Player string:Metadata
然后我们会得到这样一段结果:
method return time=1578801147.817851 sender=:1.89 -> destination=:1.303 serial=100 reply_serial=2
variant array [
dict entry(
string "mpris:trackid"
variant object path "/org/mpris/MediaPlayer2/1475050"
)
dict entry(
string "mpris:length"
variant int64 164000000
)
dict entry(
string "mpris:artUrl"
variant string "https://p1.music.126.net/QfpBYZjsztHjucFAIxfDgQ==/1746024464908302.jpg"
)
dict entry(
string "xesam:album"
variant string "Working Class Hero: The Definitive Lennon"
)
dict entry(
string "xesam:artist"
variant array [
string "John Lennon"
]
)
dict entry(
string "xesam:discNumber"
variant int16 0
)
dict entry(
string "xesam:title"
variant string "Oh My Love"
)
dict entry(
string "xesam:trackNumber"
variant int16 9
)
]
从结果中我们可以找到我们想要的信息:歌手,标题等等。
最后,我们只需要用正则表达式提取一下就🉑️️了。
实现
正则表达式 当时鼓捣了好久, 能用就行。
下面是具体的 Shell 脚本实现。
#/bin/sh!
echo "Song Daemon is running......"
PREFIX="Rise 正在播放:"
FILENAME="/tmp/songdaemon"
NOSONG="当前没有播放歌曲"
echo "$NOSONG" > $FILENAME
while [ : ]
do
ARTIST=$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.ElectronNCM /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:org.mpris.MediaPlayer2.Player string:Metadata | sed -n '/artist/{n;n;p}' | cut -d '"' -f 2) 2>/dev/null
NAME=$(dbus-send --print-reply --dest=org.mpris.MediaPlayer2.ElectronNCM /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:org.mpris.MediaPlayer2.Player string:Metadata | sed -n '/title/{n;p}' | cut -d '"' -f 2) 2>/dev/null
# 其中 dest 参数为我的音乐播放器的名称,这是我翻源代码翻出来的。
if [ "$NAME" == "" ]
then
CONTENT="$NOSONG"
else
CONTENT="$PREFIX $NAME - $ARTIST"
fi
if [ "$CONTENT" == "$(cat $FILENAME)" ]
then
sleep 1;
else
echo "$CONTENT" > $FILENAME
fi
done
OBS Studio 怎么设置显示文件内容,我就不在此赘述了。
后记
不禁感叹一句,Linux 下获取正在播放的媒体可比 macOS 简单多了。
其实这篇文章应该是很早就写完的(脚本是2019年10月1号写完的)。但是由于本人工作繁忙,加上事情特别多,根本顾不上水这篇博文。
当时水了一些别的文章,总之这篇文章就留到了今年。
希望对各位有所帮助。
又水完一篇博客,好开心。
上次修改於 2020-01-12