Я хочу смочь сохранить название .mp3 файла каждый раз, когда я открываю песню с VLC.
Править: Как Вы парни в комментариях упомянули;
Как я могу достигнуть этой цели?Заранее спасибо.
Вы можете получить название воспроизводимой дорожки (Адрес), используя:
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"
она сохранит имя файла в [ 115].
В противном случае я предлагаю вам создать простую привязку клавиш для sh -c 'lsof -p $(pidof -s vlc) | grep -o "/.*\.mp3"'
, поэтому всякий раз, когда вы нажимаете эти клавиши, она сохраняет название воспроизводимой в данный момент песни.
Мы также можем создать сценарий и запустить его одновременно с VLC, и поддерживать его в фоновом режиме, а затем с помощью этого сценария мы можем проверить, какой трек воспроизводится прямо сейчас.
В качестве альтернативы, не внося изменений в файл .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
Выполните тестовый запуск с терминала командой:
[ 112]Откройте любую песню в VLC любым способом (cli, gui), файл журнала должен быть создан и показать записанные песни.
Если все работает нормально, добавьте пункт «Автозагрузка приложений»: «Тире»> «Автозагрузка приложений»> «Добавить». Добавьте команду:
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
Вы можете использовать подробный вывод 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
) так же, как и обычный файл. Его нигде не видно в графическом интерфейсе, но он выглядит так же, как обычный воспроизводимый файл в журнале. | grep -oP
пропускает только те строки, которые соответствуют определенному регулярному выражению в стиле Perl, и отображает только совпавшую часть этого регулярного выражения."\/.*\/\K.*(?=\.[a-zA-Z0-9-_]*\' успешно открыт)"
является регулярное выражение, которое соответствует строкам, подобным последней в приведенном выше примере журнала, и выводит только имя файла без окончания (удалите \.[a-zA-Z0-9-_]*
, если вы хотите сохранить это) и путь (замените \/.*\/
на file\:\/\/
, если вы хотите сохранить его). \/.*\/
соответствует чему-либо между двумя косыми чертами (/
) и самими косыми чертами. Например, это может быть «/путь/к/
». \K
исключает все до него из совпадения, а это означает, что оно должно быть там, чтобы вообще было совпадение, но его нет в результате. .*
просто соответствует чему угодно (кроме новых строк и т. д.). (?=…)
— это «предварительный просмотр», который делает по существу противоположное \K
, он исключает все после него (или в данном случае внутри скобок) из совпадения, но он все еще должен быть там, чтобы иметь матч. \.
соответствует точке (.
). [a-zA-Z0-9-_]*
соответствует всем буквам, цифрам, -
и _
произвольное количество раз, что должно надеюсь, охватит все окончания файлов. \' успешно открыто
соответствует концу строки из примера журнала. Особая трудность в этой задаче заключалась в том, что многие команды использовать нельзя. Например, basename
не работает со StdIn, sed
выполняется только после завершения ввода и так далее. VLC имеет интерфейсы, которые предназначены для управления и мониторинга извне, но все они кажутся очень сложными в использовании. Самым простым кажется интерфейс HTTP, но его нельзя использовать без пароля, что значительно усложняет его программное использование.