Определение музыки и исполнителя в Linux

июня 10, 2013 , 0 Comments

Распознаватель музыки Linux
За что я люблю Linux? Можно долго перечислять его плюсы, но сегодня я бы хотел поговорить об опэн сорсе и свободе, которую он дает. Ни для кого не секрет, что музыка, безусловно, занимает неотъемлемую часть нашей жизни, но бывают такие ситуации, когда в процессе прослушивания, необходимо узнать название исполнителя, а под рукой нету смартфона с приложением за 5 долларов или например микрофона, или он не работает. Как быть? Ведь исполнителя узнать очень хочется. Тут нам на помощь и приходит великий мир опен сорса. Сегодня я расскажу вам как сделать свой собственный распознаватель музыки на Linux




О Echonest


Распознавать мы будем все что угодно, будь то локальный трек, либо онлайн радио. А поможет нам в этом Echo print - это набор инструментов, который запускает специальный кодогенератор, создающий отпечаток записанной части песни, который, впоследствии, передается от клиента к серверу и проходит стадию распознания. Как заявляют создатели этого чуда, ребята из Echo Nest, клиенту echoprint-codegen необходимо всего 20 секунд для того чтобы распознать трек, при этом увеличение времени отрезка существенно увеличивает шанс распознавания.

Этот процесс схож с некоторыми сервисами, о которых вы вероятно уже наслышаны, например TrackID, Shazam, MusicBrainz или Audiotag, но все они имеют закрытый исходный код, к тому же не всегда определяют композицию. Хотя и не стоит надеяться на то, что echoprint определит прямо таки любой трек


От слов к действию


Поставим необходимые компоненты. Данная статья будет рассматривать установку на Debian-based дистрибутивы, если у вас другой дистрибутив, то, думаю, вам не составит труда сделать подобные действия, тем способом, который заложен в ваш дистрибутив. Тем более, инструменты популярные и их всегда можно можно найти в исходниках.

# sudo apt-get install python build-essential git-all

Качаем клиент с гитхаба. Советую качать в папку в пути которой не используется кириллица, иначе потом придется в скрипте помучатся с кодировкой
# git clone git://github.com/echonest/echoprint-codegen.git

Перед сборкой обязательно удовлетворяем зависимости о которых написано в README.md. Для этого выполним:
# sudo apt-get install ffmpeg libboost1.42-dev libtag1-dev zlib1g-dev

(Если понадобится zlib, придется собрать его отдельно)
После того, как зависимости удовлетворены собираем командой make а затем sudo make install

Далее нам нужно поставить библиотеку для питона pyechonest. Я предлагаю поставить бинарник(хоть сам и собирал из исходников) это позволит вам сэкономить немного времени на удовлетворение зависимостей. Для этого выполним:
# sudo easy_install -U pyechonest


API ключ


После установки echoprint-codegen нужно получить API-ключ, зарегистрировавшись по адресу developer.echonest.com/account/register. Чтобы было проще сразу занесем ключ в специальный фаил. Не пугайтесь, если его нет.

# nano ~/.bash_profile и вписываем:
export ECHO_NEST_API_KEY="Наш_Ключ" сохраняем фаил по нажатию CTRL + O

# source ~/.bash_profile этой командой мы обновили окружение, чтобы не пришлось перезагружать систему, чтобы она увидела записанный ключ. В принципе можно было вписать ключ в скрипт примера lookup.py, что потом тоже понадобится, но если не вписать в bash_profile, то команда echoprint-codegen не будет работать.


Проверка


Теперь можно попробовать определить какой нибудь локальный трек на вашем компьютере, для этого воспользуемся командой, например:
# echoprint-codegen ~/Музыка/test.mp3

В ответ получим что то наподобие:
{"metadata":{"artist":"Cypher", "release":"Need For Speed: Porsche Unleashed", "title":"Choose Your Enemy", "genre":"Soundtrack", "bitrate":320,"sample_rate":32000, "duration":141, "filename":"/home/censured/Музыка/ ...}

Если по какой то причине, команда не сработала, не волнуйтесь, мы все равно будем делать с помощью скрипта, кстати пришло время попробовать определить им. Для этого оправимся в папку скачанного с гитхаба echoprint-codegen в папку examples.
Сначала выполним команду # whereis echoprint-codegen и скопируем путь, который впишем в редактируемый скрипт получится так:

# nano lookup.py в нем расскоментируем строчку config.ECHO_NEST_API_KEY='и впишем сюда ключ'
и впишем путь который мы узнали выше config.CODEGEN_BINARY_OVERRIDE = os.path.abspath("/usr/local/bin/echoprint-codegen")
# chmod +x lookup.py данной командой даем ему право на исполнение.

А теперь скопируем в эту папку какой нибудь музыкальный фаил и с помощью скрипта определим его исполнителя
# ./lookup.py test.mp3

В ответ получим: Got result: [] Artist: The Prodigy (AR4L4WQ1187FB51996) Song: Voodoo Beats (SODBCPN1338A5D4F13)



Определение с захватом


Итак, мы подошли к самому интересному. Как я и говорил музыку мы будем распознавать - удаленную, например, которая играет в онлайн радио в реальном времени. Для этого понадобится захватить поток со звуковой карты. Но сразу это сделать у нас не получится, хотя вы конечно можете попытать счастье командой:

# arecord -d 30-v -f cd -t raw | lame -r -b 192 - ~/output.mp3 и затем воспроизвести фаил output.mp3 из домашней папки
Если проигрывается тишина или очень тихий звук даже на 200% громкости, то берем бубен и начинаем танцевать :)

Для начала создадим псевдоустройство
# nano ~/.asoundrc
такого содержания

pcm.copy {
type plug
slave {
pcm hw
}
route_policy copy
}


Теперь вводим
# amixer contents
и ищем номер устройства у которого будет iface=MIXER,name='Capture Source' (на всякий случай так можно посмотреть список всех устройств amixer controls)

В моем случае это оказалось:

numid=24,iface=MIXER,name='Capture Source'
; type=ENUMERATED,access=rw------,values=2,items=8
; Item #0 'Mic'
; Item #1 'CD'
; Item #2 'Video'
; Item #3 'Aux'
; Item #4 'Line'
; Item #5 'Mix'
; Item #6 'Mix Mono'
; Item #7 'Phone'
: values=2,2

Обычно, по дефолту там используется Item #0 то есть микрофон, поменяем схему захвата на с Mic на Mix:
amixer cset numid=24,iface=MIXER,name='Capture Source" 5

После данных манипуляций, звук от # arecord -d 30-v -f cd -t raw | lame -r -b 192 - ~/output.mp3 появлялся но был очень тихим, даже после того как я поигрался с уровнем звука в alsamixer. Оказалось, что всему виной pulseaudio. Решение было довольно простым - покрутить настройки pulseaudio:

# pavucontrol везде выставляем ползунки на 100% при этом с низу выбираем вкладку All Streams и All Output Devices

Повторим выполнение команды, теперь звук должен быть громче # arecord -d 30-v -f cd -t raw | lame -r -b 192 - ~/output.mp3
Поздравляю, теперь остается лишь упростить процесс идентификации


Костыли


Делаем скрипт который будет записывать 30 секундный отрывок. Советую не парится и создать его в папке по соседству с lookup.py
# nano echoprint.sh пишем:

# /bin/bash

rm -rf ~/Scripts/Python/echoprint-codegen/examples/output.mp3
arecord -d 30-v -f cd -t raw | lame -r -b 192 - ~/Scripts/Python/echoprint-codegen/examples/output.mp3

Обратите внимание ~/Scripts/Python/echoprint-codegen/examples/ это путь, где у меня хранится скрипт, у вас он может быть свой(скорее всего)

Сделаем alias'ы грубоговоря алиасы это какой то набор любых команд, который сводится к одной, имя которой мы придумываем сами. Редактируем:

# nano ~/.bashrc

alias recechosample='bash ~/Scripts/Python/echoprint-codegen/examples/echoprint.sh && alert'
alias getechosample='python ~/Scripts/Python/echoprint-codegen/examples/lookup.py ~/Scripts/Python/echoprint-codegen/examples/output.mp3'

Заметили, что в конце первого алиаса у меня стоит && alert? Это вывод оповещения, после выполнения операции, если у вас нигде нет такого алиаса то ниже впишите
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' либо можете удалить && alert.

Обновляем переменные окружения
# source ~/.bashrc

Ура! Теперь все сводится к двум простым командам. В любой момент пишем recechosample, чтобы записать отрезок музыки и получить уведомление + getechosample, чтобы идентифицировать, записанный отрезок.


P.S.


Реализация с алиасами была придумана "на коленке", если у вас есть более гуманное решение, то прошу поделится им в комментариях.
Если использовали кириллицу в путях то в lookup.py добавляем после #!/usr/bin/env python пишем # -*- coding: utf-8 -*-
+ Был обнаружен странный баг, при использования скайпа данный метод не работает, пока не перезагрузить систему.


Ресурсы


http://echoprint.me
https://echonest.github.io/pyechonest/contents.html
https://habrahabr.ru/post/122969/
http://carthick.wordpress.com/2007/11/26/linux-recording-soundcard-output-using-arecord/
https://echonest.github.io/remix/keysetup.html
http://mocha.freeshell.org/audio.html
http://manual.audacityteam.org/man/Tutorial_-_Recording_Computer_Playback_on_Linux


0 коммент.: