LINUX.ORG.RU

cmus - добавление случайной музыки из библиотеки

 , , ,


0

1

HOWDY, $USER!

Я заметил, что часто слушаю одну и ту же музыку кругами, а что-то забыл и вообще слушать перестал, хотя стоило бы. Просто забыл в каком каталоге, в каком альбоме какая годнота есть.

Решил эту несправедливость исправить. И поскольку музыку слушаю исключительно из локального хранилища в консольном плеере cmus, то и скрипт будет ориентирован на него.

Идея сделать плейлист всего и выбрать режим случайного воспроизведения отпадает - мне это неудобно и долго. Поэтому выбрал однострочник для выполнения в консоли.

Ищу все музыкальные файлы -> выбираю из списка случайный -> немедленно воспроизвожу в cmus.

find "/mnt/Music/A-Z-А-Я/" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" | ( i=0; while read line; do lines[i++]="$line"; done; echo "$line"; cmus-remote -f "${lines[$RANDOM % $i]}" )

Удобнее и быстрее применять это не к всей коллекции музыки, а к дискографии отдельного исполнителя, чтобы не заслушивать одни и те же композиции, а ознакомиться с творчеством в случайном порядке:

find "/mnt/Music/A-Z-А-Я/Kraftwerk (1970-2006)/Albums/" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" | ( i=0; while read line; do lines[i++]="$line"; done; echo "$line"; cmus-remote -f "${lines[$RANDOM % $i]}" )

Вот, уже хорошо получилось!

Тоже самое, только вместо немедленного воспроизведения - добавление в плейлист:

find "/mnt/Music/A-Z-А-Я/" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" | ( i=0; while read line; do lines[i++]="$line"; done; echo "$line"; cmus-remote -C add\ "${lines[$RANDOM % $i]}" )

После N раз запуска, можно этот случайный плейлист воспроизвести:

cmus-remote -p # воспроизвести

Казалось бы, вот она мякотка. Но встал вопрос оптимизации. Каждый раз искать все файлы это очень долго. Значит нужно 1 раз найти, затем в цикле N раз добавить случайные файлы:

find "/mnt/Music/A-Z-А-Я/" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" \
| ( i=0; while read line; do lines[i++]="$line"; done; echo "$line"; for n in {1..25}; do cmus-remote -C add\ "${lines[$RANDOM % $i]}" ; done )

Ну вот, теперь можно прослушать 25 случайных песенок из огромной коллекции:

cmus-remote -p # воспроизвести

Пожалуй применю это ещё к коллекции музыки в формате SID для Commodore64, там плеер выводит ограниченное количество файлов в каталоге, и тоже слушаю одно по кругу. А так смогу формировать случайные коллекции композиций разных музыкантов для копирования на microsd.

Джедаи консоли, прошу поделиться исправлениями моего скрипта, не наговнобашил ли я, или что можно улучшить без промежуточных файлов и в формате однострочного скрипта? (как этот)

Ответ на: комментарий от cobold

Спасибо. Я как раз ловил дубли и мне эта конструкция показалась ненадёжной. А по уровню случайности, насколько shuf лучше?

upd. А как использовать args? Я не смог скормить выборку cmus-remote -C add\.

find $MUSPATH -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" | shuf | head -25 | ... cmus-remote -C add\ ...?
hikikomori ★★★
() автор топика
Последнее исправление: hikikomori (всего исправлений: 1)

Я заметил, что часто слушаю одну и ту же музыку кругами, а что-то забыл и вообще слушать перестал, хотя стоило бы.

Я вот заметил, что при случайной выборке за длительный период времени (6 лет) некоторые треки попадают в список воспроизведения чаще других:

FirstPlay           Total Artist               Year Album                       Num Title
---------           ----- ------               ---- -----                       --- -----
17.06.2019 15:25:35     8 Thomas Giles         2018 Don't Touch The Outside      12 1709
13.07.2018 09:54:04     8 Lamb                 2003 Between Darkness And Wonder   6 Wonder
27.02.2023 11:34:50     8 W.A.S.P.             2009 Babylon                       9 Promised Land
13.08.2018 10:25:37     8 P.O.D.               2015 The Awakening                 6 Get Down
10.05.2018 01:14:09     8 Angellore            2015 La Litanie des Cendres        1 A Shrine of Clouds
28.08.2018 08:57:25     9 Pink Floyd           1979 The Wall                      9 Young Lust
24.08.2019 13:49:38     9 Dezperadoz           2000 The Dawn of Dying             1 The Beginning
19.07.2018 14:53:15     9 Memories of Machines 2011 Warm Winter                   8 Lost And Found In The Digital World
17.06.2019 15:26:42     9 Thomas Giles         2018 Don't Touch The Outside      13 Exordium
29.08.2018 11:48:07     9 Pink Floyd           1979 The Wall                      7 The Show Must Go On

В таблице десять с наибольшим числом воспроизведений. Всего файлов 4939.
Здесь W.A.S.P. резко выделяется тем, что он первый раз воспроизвелся на три-четыре года позже.
Может это случайность, а может «случайный выбор» любит W.A.S.P.

dmitry237 ★★★
()
Ответ на: комментарий от anonymous

Библиотека в широком смысле - коллекция. А как ещё мне искать? Критикуете - предложите лучше. Средств cmus недостаточно. Конвееры с find самое простое решение.

hikikomori ★★★
() автор топика
Ответ на: комментарий от anonymous

Библиотека cmus — простой список файлов,

И что? Вкладок cmus не поддерживает. Без них неудобно.

так что find не нужен.

Потрудитесь аргументировать почему.

hikikomori ★★★
() автор топика
Ответ на: комментарий от cobold

Йа сделяль.

time find "/mnt/Music/Original Sound Tracks" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" -print0 | shuf -z | head -z -n100 | xargs -0 -t -i  cmus-remote -C add\ {}

Если указать . поиск от текущего каталога, то No such file or directory. Почему-то конструкция cmus-remote -C add\ "./Resident Evil/Depeche Mode - Dirt.mp3" не проходит, хотя например ls из текущей папки файл видит.

Во избежание использую #00 как индикатор конца строк. В остальном вроде бы годный скрипт вышел. Для сравнения:

$ time find "$MUSPATH" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" | ( i=0; while read line; do lines[i++]="$line"; done; echo "$line"; for n in {1..25}; do cmus-remote -C add\ "${lines[$RANDOM % $i]}" ; done )

real	0m1,092s
user	0m0,442s
sys	0m0,660s

-t из xargs убрал для ускорения

$ time find "$MUSPATH" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" -print0 | shuf -z | head -z -n25 | xargs -0 -i  cmus-remote -C add\ {}

real	0m0,110s
user	0m0,060s
sys	0m0,036s

Правда мне это стоило долгого нужного чтения и конспектирования своими словами.

Единственная понятная статья: https://tokmakov.msk.ru/blog/item/724

остальные ссылки - копипаста,не существенные дополнения, большей частью бесполезные и написаны малопонятно: https://rus-linux.net/MyLDP/consol/Linux_Xargs_Command.html https://ru.wikipedia.org/wiki/Xargs https://losst.pro/komanda-xargs-linux https://wiki.dieg.info/xargs

Либо дикое растекание мысли по древу и неудобно показанные примеры не видные целиком на экране - вебдезигнер убейся животное! https://selectel.ru/blog/xargs-mnogoobrazie-priyomov-ispolzovaniya/

В следующем сообщении поделюсь своим конспектом, может пригодится ещё кому понять эту утилиту.

hikikomori ★★★
() автор топика
Ответ на: комментарий от hikikomori

КОНШПЕКТ

С помощью утилиты xargs вывод предыдущей команды можно передать в аргументы следующей.

Передавать echo параметры слева в echo справа по 2 за раз

echo A B C D| xargs -n 2 echo

Следующая shell-процедура пересылает все файлы из каталога $1 в каталог $2 и сообщает о каждой пересылке перед тем, как её выполнить:

ls $1 | xargs -I {} -t mv $1/{} $2/{}

touch создаёт три файла, взяв имена из echo

echo "file1 file2 file3" | xargs touch

rm удаляет файлы по маске от ls

ls file* | xargs rm

КЛЮЧИ:

-t или –verbose выводит выполняемую команду, иначе выполняет тихо

echo "file1 file2 file3" | xargs -t touch

-p или –interactive запрашивает подтверждение

echo "file1 file2 file3" | xargs -p touch

-n или –max-args указывает количество аргументов, передаваемых второй команде за один раз. Вторая команда будет вызываться, пока не закончатся все аргументы.

echo 1 2 3 4 5 6 | xargs -n3 -t touch

Простая интерактивная запрашивалка на удаление каждого элемента выдачи ls

ls | xargs -n1 -p rm

-l или –max-lines указывает количество строк, передаваемых одной команде за раз. Она будет вызываться, пока параметры не закончатся:

ls | xargs -p -l4 rm

-i или –replace позволяет не просто передать второй команде аргументы из вывода первой команды, а вставить их в конкретное место, обозначенное двумя фигурными скобками {}.

echo Вася | xargs  -i echo Меня зовут {} Сидоров.

NOTE: вывод первой команды будет разбиваться на отдельные строки только по символам новой строки \n.

NOTE: –max-lines(-l) и –replace (-i) и –max-args (-n) являются взаимоисключающими! Использоваться будет последнее. Исключением из этого правила является указание опции -n со значением 1 после опции -i — в этом случае опция -n игнорируется.

-d или –delimiter позволяет задать другой разделитель вместо пробела.

echo -n "file1,file2,file3" | xargs -d ',' -n1 -t touch

-a или –arg-file позволяет читать аргументы из файла вместо стандартного ввода.

xargs -t -l1 -a ips.txt ping -c1

-0 или –null. заставляет считать #00 концом строки.

NOTE: Утилита xargs чаще всего используется в сочетании с командой find. Команда find позволяет найти определенные файлы, а xargs — выполнинить над ними нужные операции. NOTE: Чтобы избежать проблем с именами файлов, которые содержат пробелы, нужно использовать опцию -print0, которая заставит find выводить имя файла с нулевым символом в конце. Этот вывод может быть правильно интерпретирован xargs с помощью опции -0 или –null.

-P или –max-procs позволяет запустить параллельно нескольких команд отдельными процессами.

ls {1..3} | xargs -n1 --max-procs=3 gzip

Примеров по этим ключам ещё не записал:

-E, -e, --eof - индикатор конца файла, все символы после вхождения этой строки игнорируются;
-o, --open-tty - открывать новый терминал для дочерних процессов;
-r, --no-run-if-empty - если входной поток данных пустой, команда не будет выполнена;
--show-limits - посмотреть ограничения на длину параметров в командной строке;
hikikomori ★★★
() автор топика
Ответ на: комментарий от hikikomori

Я люблю иногда под настроение пошлифовать какую-то ерунду на баше, но делать на баше музыкальную библиотеку…

У меня есть амарок, и у него есть умные плейлисты. И они чёрт возьми хороши. Я настроил (выбор случайного трека из (не отстойные && игрались больше месяца назад)) и счастлив. Повторять это-же на баше мне не хочется.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

В моём последнем варианте я много -exec не добьюсь:

time find "$MUSPATH" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" -print0 | shuf -z | head -z -n25 | xargs -0 -i  cmus-remote -C add\ {}

shuf нужен список для работы, если его вызывать через -exec, он каждый раз будет получать только одну строку)

^^^ Буду рад выслушать возражения.

hikikomori ★★★
() автор топика
Последнее исправление: hikikomori (всего исправлений: 2)
Ответ на: комментарий от legolegs

Я раньше пользовался clementine, но как узнал про cmus, забыл про него напрочь. Единственный плюс - вкладки. В одной можно аудиокнигу мучать, в другой музыку слушать.

На баше у меня только дополнительные фичи, то, чего не хватает в cli cmus.

Не меньше пользы при формировании порции случайных .sid для c64. Он у меня фоном часто рнаботает как аппаратный плеер 8битной музыки)

Польза мне от этого - ачивка xargs, и levelup в find и баше.

Правда память дырявая, стоит не попользоваться неделю другую как забываю, приходится лезть в конспекты (храню на диске и блог пишу) Может есть какое usermenu для терминала? вызываешь команду, рисуется текстовое меню с твоими пунктами как в нортоне было. плюс смена текущего каталога в стиле millerview, как в vifm, но не шел, а выбрал каталог и она завершилась в нём. часто нужно муваться, а таскать команды из помойки в history такое себе удовольствие.

hikikomori ★★★
() автор топика

Ищу все музыкальные файлы -> выбираю из списка случайный -> немедленно воспроизвожу в cmus.

cmus-tutorial (7)

Step 3: Playing Tracks From The Library
Press 2 to go to the simple library view. You should see something like this:

+---------------------------------------------------------------------+
| Library ~/.cmus/lib.pl - 31 tracks sorted by artist album discnumbe |
| Flying Lizards         . Money (That's What I Want)           02:31 |
| Jason Woofenden        . VoR Theme                       2009 01:20 |
| Keali'i Reichel      06. Wanting Memories                1994 04:28 |
| Molly Lewis            . Tom Cruise Crazy                     03:13 |
| NonMemory              . pista1                          2009 03:18 |
| NonMemory            01. pista1                    2009-04-21 04:13 |
| Ray Charles          06. Halleluja I Love Her So              02:33 |
|                                                                     |
| . 00:00 - 2:16:25 vol: 100                   all from library | C   |
|                                                                     |
+---------------------------------------------------------------------+
Use the up and down arrow keys to select a track you'd like to hear, and press Enter to play it. Here's some keys to control play:
Press c to pause/unpause Press right/left to seek by 10 seconds Press </> seek by one minute

cmus has some great options to control what plays next (if anything) when the track ends. The state of these settings are shown in the bottom right corner. The first of these shows what collection of tracks (currently "all from library") we are playing. Press m to cycle through the different options for this setting. To the right of that (past the "|") cmus shows the state of three toggles. Only toggles which are "on" are shown, so now we only see the C. Here are the toggles:

[C]ontinue

When this is off, cmus will always stop at the end of the track. You can toggle this setting by pressing shift-C.

[R]epeat

If this is on (and continue is on), when cmus reaches the end of the group of tracks you're playing (selected with the m key) it will start again from the beginning. Press r to toggle this setting.

[S]huffle

When this is on, cmus will choose a random order to play all the tracks once. Press s to toggle this option.
LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 1)
Ответ на: комментарий от LamerOk

s - toggle shuffle (read about the m key below if you’re going to use shuffle)

m - toggles the «aaa mode.» aaa stands for artist, album, or all. Controls whether cmus shuffles between songs from an artist, album, or from all your songs. You can see the currently set «aaa mode» in the bottom right, next to where the display of the continue, repeat, and shuffle settings.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

cmus мне настолько понравился, что в своё время я полностью с гугл-транслитом прочитал его ман от корки до корки. И конечно знаю про БАЗОВЫЕ ф-ции.

Мне это не годится.
Сперва нужно что-то случайное добавить, чтобы случайно его воспроизводить. Сейчас вы скажитее про view5 (file browser). Как я уже сказал, у меня дохрена каталогов с музыкой, поэтому ни добавлять сразу весь хуллиард файлов, ни блуждать по лабиринтам fs я не хочу. Я хочу, чтобы компьютер сам выполнил рутинную задачу - добавить каталог с альбомом случайного исполнителя, или из всей коллекции случайно добавить сотку песен.

Если вы изучите view5, то обнаружите, что там нет никаких подобных инструментов. Поэтому свою задачу я могу решить только так:

# Поиск в библитеке музыкальных файлов, и добавление 25 случайных композиций в cmus:

find "$MUSPATH" -type f -regex ".*\.\(mp3\|wma\|Mp3\|flac\|ape\|m4a\)$" -print0 |\
 shuf -z | head -z -n25 | xargs -0 -t -i  cmus-remote -C add\ {}
hikikomori ★★★
() автор топика
Ответ на: комментарий от legolegs

То есть чтобы единовременно вывести 50 файлов, понадобится такая громоздкая конструкция:

find /tmp/abc/ -name 'a*' -exec printf '%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n' {} +

В моём случае это бессмыслица - найти первые 50 файлов. Я же хочу оперировать всеми файлами. Работает кстати не быстро. И всё равно потом вызывать shuf.

Пытаюсь осмыслить, а зачем вообще это может быть нужно, может объясните?

так

$ find /tmp/abc/ -name 'a*' -exec printf '%s %s %s\n' {} +

/tmp/abc/ /tmp/abc/ac /tmp/abc/ab
/tmp/abc/aa  

или так

find /tmp/abc/ -name 'a*' -print

/tmp/abc/
/tmp/abc/ac
/tmp/abc/ab
/tmp/abc/aa

выхлоп одинаков, а убрать в одну строку можно и $(засунув сюда) .

p.s. что-то у меня с firefox: http://0x0.st/Xor_.png На разных сайтах артефакты линий рендеринга страницы. меняют форму при сроллинге. Создавать новую тему?…

hikikomori ★★★
() автор топика
Ответ на: комментарий от legolegs

Увы, я туго соображаю. Ты меня просто запутал) Ты писал, что «в 80% случаев find -exec … + лучше и проще», но мой случай — это те оставшиеся 20%.

Но спасибо, для чего другого -printf может в будущем пригодится. В любом случае.

hikikomori ★★★
() автор топика