我希望每次用 VLC 打开歌曲时都能保存 .mp3 文件的名称。
编辑:正如你们在评论中提到的;
- 我想在播放器窗口中直接打开 VLC。
- 我想将正在播放的歌曲名称保存到文本文件中。
我怎样才能实现这个目标?提前谢谢。
答案1
您可以使用以下方式获取当前播放的曲目名称(地址):
lsof -p `pidof -s vlc` | grep -o "/.*\.mp3"
如果您想在双击mp3
文件打开 VLC 时保存名称,这是我的想法:
打开 VLC 的桌面文件:
sudo nano /usr/share/applications/vlc.desktop
然后编辑Exec
行使其看起来像:
Exec=bash -c "{ /usr/bin/vlc --started-from-file %U; }& sleep 1; lsof -p `pidof -s vlc` | grep -o "/.*\.mp3" > /home/user/list"
它将把文件名保存在/home/user/list
。
否则,我建议您创建一个简单的键绑定,sh -c 'lsof -p $(pidof -s vlc) | grep -o "/.*\.mp3"'
这样无论何时按下该键,它都会保存当前播放的歌曲的名称。
我们还可以创建一个脚本并与 VLC 同时运行它,并使其在后台运行,然后通过该脚本我们可以检查当前正在播放哪个曲目。
答案2
自动记录所有播放过的歌曲,并带有时间戳
或者,无需更改.desktop
文件中的任何内容或手动记录歌曲,您可以运行下面的后台脚本。它将played_songs
在您的主目录中创建一个名为的日志文件:
优点是:
- 全自动记录您播放的所有歌曲
- 无需更改您的
.desktop
文件,这意味着当您从命令行启动 VLC 时它也能起作用。
缺点是:
- 虽然我无法测量或看到任何额外的处理器负载,理论上它补充说一些活动。然而,即使在石器时代的盒子上,这种现象实际上也是不存在的。
- 有时候(很长一段时间)你需要“清空”或删除日志文件,因为(目前)它没有大小限制。不过,如果你愿意,这个问题很容易解决。
剧本
#!/usr/bin/env python3
import subprocess
import os
import time
home = os.environ["HOME"]
log = os.path.join(home, "played_songs")
def_name = "VLC media player"
def get(cmd):
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except subprocess.CalledProcessError:
pass
song1 = None
while True:
time.sleep(2)
pid = get(["pgrep", "vlc"])
if not pid:
song = None
else:
# only do anything at all if vlc runs
wins = get(["wmctrl", "-lp"])
if wins:
wins = wins.splitlines()
try:
# check if any of the windows belongs to vlc
# this will not if it is closed in the meantime
match = [w.split()[0] for w in wins if pid in w][0]
except IndexError:
pass
else:
# ...if so, retrieve the song name, only log if there is a new song
song2 = get(["xdotool", "getwindowname", match])
if all([song2, song2 != song1, song2 != def_name]):
open(log, "a+").write(
time.strftime("%H:%M:%S_%d-%m-%Y")+"\n "+\
song2.replace(def_name, "").rstrip(" - ")+"\n"
)
song1 = song2
如何使用
该脚本需要
xdotool
和wmctrl
:sudo apt-get install xdotool wmctrl
将脚本复制到一个空文件中,另存为
log_vlc.py
通过以下命令从终端运行它:
python3 /path/to/log_vlc.py
以任意方式(cli、gui)在 VLC 中打开任何歌曲,都应创建日志文件并显示已记录的歌曲。
如果一切正常,请将权限添加到启动应用程序:Dash > 启动应用程序 > 添加。添加命令:
python3 /path/to/log_vlc.py
解释
每两秒一次,脚本:
检查 VLC 是否正在运行根本,如果不是,则不执行任何操作
pid = get(["pgrep", "vlc"]) if pid: # only do anything at all if vlc runs
如果 VLC 正在运行,它会找到其窗口并解析歌曲标题
wins = get(["wmctrl", "-lp"]) if wins: wins = wins.splitlines() try: # check if any of the windows belongs to vlc # this will not be the case if it is closed in the meantime match = [w.split()[0] for w in wins if pid in w][0] except IndexError: pass else: # ...if so, retrieve the song name, only log if there is a new song song2 = get(["xdotool", "getwindowname", match])
(仅)如果歌曲标题发生变化,显然播放了一首新歌曲,则歌曲名称会记录到日志文件中,并带有时间戳。
if all([song2, song2 != song1, song2 != def_name]): open(log, "a+").write( time.strftime("%H:%M:%S_%d-%m-%Y")+"\n "+\ song2.replace(def_name, "").rstrip(" - ")+"\n" ) print(song2) song1 = song2
答案3
您可以使用 VLC 的详细输出,但这有点复杂。您需要详细级别 2 才能打印任何文件名(无论出于何种原因),但这也会记录大量其他内容,因此您需要过滤输出。
以下是详细程度 2 的示例输出,但仅包含告诉您路径的文件名(vlc --verbose 2 file.mp3 | grep "file.mp3"
):
[00007f1720000c20] main input debug: Creating an input for preparsing 'file.mp3'
[00007f16d0000c80] main input debug: `file:///path/to/file.mp3' gives access `file' demux `any' path `/path/to/file.mp3'
[00007f16c4000fe0] main input source debug: creating demux: access='file' demux='any' location='/path/to/file.mp3' file='/path/to/file.mp3'
[00007f16c4001690] main stream debug: creating access: file:///path/to/file.mp3
[00007f16c4001690] main stream debug: (path: /path/to/file.mp3)
[00007f16c4000fe0] main input source debug: attachment of directory-extractor failed for file:///path/to/file.mp3
[00007f16c4000fe0] main input source debug: creating demux: access='file' demux='any' location='/path/to/file.mp3' file='/path/to/file.mp3'
[00007f16d0000c80] main input debug: `file:///path/to/file.mp3' successfully opened
这是一个示例命令,它将所有播放的文件名打印到控制台(您可以>> file.txt
在最后将其重定向到文件中):
vlc --verbose 2 file1.mp3 /path/to/file2.m4a 2>&1 | grep -v "ml.xspf" | grep -oP "\/.*\/\K.*(?=\.[a-zA-Z0-9-_]*\' successfully opened)"
解释:
vlc … file1.mp3 /path/to/file2.m4a
打开 VLC 并播放这两个曲目。您还可以在命令行上将其设置为随机或其他任何设置,有很多选项。--verbose 2
激活详细输出。您也可以使用 将其放入文件中--file-logging --log-verbose 2 --log-file file.log
,但我的其余命令也可以在命令行中使用,因此这样效果更好。2>&1 |
将错误输出(和标准输出)重定向到下一个命令。grep -v "ml.xspf"
过滤掉包含“ml.xspf
”的任何内容,因为出于某种原因,VLC 打开该文件(在我的情况下位于~/.local/share/vlc
)的方式与打开常规文件的方式相同。它在 GUI 中的任何地方都看不到,但它在日志中看起来与常规播放的文件相同。| grep -oP
只让符合特定 Perl 风格正则表达式的行通过,并且只显示该正则表达式的匹配部分。- 现在到了复杂的部分:
"\/.*\/\K.*(?=\.[a-zA-Z0-9-_]*\' successfully opened)"
是一个正则表达式,它匹配上面日志示例中的最后一行,并且只输出文件名,不带结尾(\.[a-zA-Z0-9-_]*
如果要保留,请删除)和路径(如果要保留,请更改\/.*\/
为file\:\/\/
)。
该正则表达式的解释:\/.*\/
匹配两个斜杠 (/
) 和斜杠本身之间的任何内容。例如可以是“/path/to/
”。\K
将其之前的所有内容从匹配中排除,这意味着它必须存在才能进行任何匹配,但它不在结果中。.*
匹配任何内容(除了换行符等)。(?=…)
是一种“前瞻”,其作用本质上与相反\K
,它将其后面的所有内容(或在本例中是括号内的所有内容)排除在匹配之外,但它仍然需要存在才能进行匹配。\.
匹配句点 (.
)。[a-zA-Z0-9-_]*
匹配所有字母、数字-
和_
任意次数,希望能够涵盖所有文件结尾。\' successfully opened
与日志示例中的行尾匹配。
- 我选择了“成功打开”这一行,而不是一些更容易解析的行,因为它似乎确认没有发生任何错误,例如,如果你将整个主文件夹转储到其中,它就不会输出它无法播放的文件,因为它们不是媒体文件。
这个问题的一个特殊困难是许多命令无法使用。例如,basename
无法与 StdIn 一起使用,sed
仅在输入结束后执行等等。VLC 具有用于从外部控制和监视它的接口,但它们似乎都非常复杂。最简单的接口似乎是 HTTP 接口,但如果没有密码就无法使用,这使得以编程方式使用它变得更加困难。