Давно собирался написать этот пост, но прогресс шел медленно. К ускорению темпа подтолкнул этот вопрос, где я имел неосторожность обмолвиться, что пишу такой пост, в результате чего он вызвал живой интерес, поэтому мне ничего не оставалось делать, как выполнять данное обещание, за что выражаю отдельную благодарность автору вопроса M03G, с чьей подачи и был получен мной этот ускоряющий пендель. А так как пост, похоже, увидит свет в пятницу, я позволил себе довольно вольный (извините, вышел каламбур невольный) стиль изложения. Надеюсь, все останутся довольны.
(Да, пост во многом пересекается с постом Распределенный аудиоплеер на Odroid U2, но чуть проще в настройке)
Пролог
Я начал мечтать о подобной системе году в 2003-м, как только начал жить в квартире с количеством комнат >1, и вопрос музыки на кухне (да и вообще по всей квартире) встал во весь рост. Ситуация усугублялась тем, что квартира была построена согласно архитектурному гению Никиты Сергеевича Хрущева, а компьютер помещался в “дальней” комнате, так что на кухне слышно было чуть более, чем совсем никак.
Время шло, квартиры менялись, обдумывались и отбрасывались различные варианты, мечта оставалась, то уходя в полнейший бэкграунд, то снова выплывая из глубин подсознания, но воз не двигался.
Предыстория
К тому моменту, как в широком доступе оказались замечательные одноплатные компьютеры Raspberry Pi, я сменил 3 места проживания, такое же количество работ, а также страну проживания, поэтому из-за обилия происходящего мечта не подала голоса даже слабого голоса, давно уснув летаргическим сном в пыльном чулане на задворках памяти. Малинку я, однако, все равно заказал. Зачем – еще сам не понимал, но устоять не смог: соотношение цена/потенциальные возможности все решило. “Это же в перспективе и NAS, и веб-сервер для экспериментов, и куча всего остального”, — думал я (ну, на NAS, как выясняется, она не тянет, но даже если бы я это тогда знал, меня бы все равно это не остановило).
Однако после того, как “малинка” таки попала ко мне в руки, у меня как раз организовался завал и на работе, и с личными проектами, поэтому “ягодка” легла на полку и пролежала несколько месяцев, так и не вкусив электричества.
Но однажды все изменилось.
Завязка
Теплым летним вечером делать было нечего, чего со мной не случалось уже несколько лет, и я решил не упускать такую возможность и хоть немного разобрать хлам в шкафу. Там я и наткнулся на черную коробочку, грустно смотревшую на меня прорезями пустых слотов.
“Оба на, да у меня же вот чего есть!”
— подумал я и тут же полез в интернет за образом системы для нее. Так случилось, что на стол она легла таким образом, что прямо в левый глаз мне уставился аудиовыход, задавая немой вопрос
“Ну что, будем что-нибудь делать или как?”
План созрел быстро: в usb-порт втыкаем внешний винт с музыкой, к аудиовыходу подключаем колонки, на малину ставим MPD и получаем отличный музыкальный плейер, доступный для контроля с любого компьютера в доме (благо клиентов полно под любую ОС). Итак, малинке наконец-то нашлось применение, она весело замигала разноцветными светодиодами, и это было хорошо.
Хорошо, но мало.
“Хе, есть же такая замечательная вещь, как Icecast2, который превосходно ладит с MPD и стримит музыку в сеть!”
— пронеслось у меня в голове. И тогда можно будет слушать на любом устройстве любым плейером, умеющим хватать аудиопоток из сети. Мысль эти грянула настолько громко (я бы даже сказал оглушительно), что грозные раскаты докатились до забытого пыльного чулана и разбудили безнадежно уснувшую мечту, которая тут же принялась долбить жестяной кружкой в стену:
“А кто тебе мешает взять еще пару-тройку малинок, написать простейшую софтину, которая по команде из сети включает/выключает тот же mplayer на проигрывание заданного URL (того самого, куда вещает Icecast2 с первой малины), и выпустить уже меня отсюда в конце концов??”
Но тут меня (и ее) поджидал первый облом (как оказалось впоследствии – к лучшему): мощности малины не хватало на то, чтобы на лету пережимать поток и стримить его – звук заикался. Я полез искать, можно ли “уговорить” Icecast2 не пережимать, а напрямую стримить то, что ему скармливают. И пока курил конфиг MPD, наткнулся на знакомое слово “pulseaudio”.
“Так, стоп, да это же вроде та самая хреновина, которая потенциально умеет воспроизводить по сети? А может мне и не нужно городить огород с Icecast2 и самописной включалкой/выключалкой?”
Так и вышло… А шкаф так и остался неразобранным.
Поехали!
Итак, поехали. Исходный материал: две или больше Raspberry Pi (одна будет сервером, на котором крутится MPD, остальные клиентами), такое же количество колонок для воспроизведения звука, чуть-чуть знания Linux, и вечер свободного времени. Ну и, разумеется, музыкальная коллекция с правильно прописанными тегами, т.к. MPD оперирует именно ими. Все это у меня в наличии было, поэтому я заранее известил жену о том, что ближайшим вечером меня нет, я заболел, изчез из дома, уехал в Ванкувер, и вообще эмигрировал нафиг с этой планеты, и что вернусь завтра к обеду, и с головой погрузился в гугл. Гугл не подвел.
Подготовительный этап (одинаковый для сервера и клиентов)
Я не буду детально описывать процесс установки системы на Raspberry Pi, инструкций в интернете полно. Оговорюсь лишь, что я, как любитель Debian с 8-летним стажем, использовал Raspbian, поэтому все инструкции будут даны для него. В общем, качаем образ, прошиваем, втыкаем карту, грузимся. Первоначальная настройка тоже стандартна, перечислю то, что сделал я:
- задал пароль (разумеется)
- активировал ssh-сервер
- задал таймзону
- убрал загрузку иксов
- выставил объем видеопамяти на минимум (16 мегабайт), ибо незачем ее зря расходовать за неимением иксов.
Если вы не очень уверенно чувствуете себя в консоли, то можете два последних пункта пропустить, и настраивать прямо из “малинового” гуя, я же все делал залогинившись по ssh.
Обязательный пункт: назначьте каждой “малинке” статический адрес в настройках вашего роутера (или в ее собственных сетевых настройках, без разницы) – впоследствии очень пригодится.
Ну что ж, приступим:
1. Первым делом обновим систему до свежего состояния и установим PulseAudio. Вообще, мы сейчас много чего будем делать от рута, поэтому перейдите под его учетку любимым вами способом (выбирайте на свой вкус):
$ sudo -i # aptitude update && aptitude upgrade && aptitude install pulseaudio
2. Т.к. предполагается, что работать все будет сразу же после загрузки, в идеале – без иксов и логина юзера, нам нужно, чтобы PulseAudio работал в общесистемном режиме. Для этого отредактируем файл /etc/default/pulseaudio следующим образом:
... PULSEAUDIO_SYSTEM_START=<b>1</b> ...
3. Далее, чтобы все работало, нужно добавить юзера pi в группу pulse-access:
# usermod -a -G pulse-access pi
4. Теперь разрешим прием звука по сети. Для этого в файл /etc/pulse/system.pa добавим строку
... load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.1.0/24 ...
Здесь мы авторизуем как “самого себя”, так и все устройства из локальной сети с адресами 192.168.1.* (если у вас диапазон адресов другой, поправьте соответствующим образом). В принципе, первая часть нужна только для сервера (чтобы играть на самом себе), а вторая — для клиентов (чтобы принимать из сети), но мы сделаем и то, и другое, чтобы в случае чего малинки были взаимозаменяемы с минимальными телодвижениями.
4. Собственно, запускаем сервис pulseaudio
# service pulseaudio start
На этом общая часть заканчивается. Перейдем к настройкам клиентов и сервера.
Клиент
Возможно, кому-то это покажется странным, но “клиент уже готов”, и дополнительной настройки не требуется, поэтому далее двигаемся строго на сервер порядка 50 метров займемся сервером.
Сервер
В первую очередь на сервер нужно установить MPD, и заодно консольный клиент (для первоначальной настройки):
# aptitude install mpd mpc
Теперь редактируем конфиг /etc/mpd.conf. Он, как и многие другие конфиги в линуксе, отлично прокомментирован, поэтому я обозначу лишь основные необходимые правки:
Указываем путь к коллекции
music_directory "/mnt/disk1/music/mp3/sorted"
Биндим на любой сетевой интерфейс:
bind_to_address "any"
На стандартный порт:
port "6600"
Авто-апдейтить коллекцию при изменении файлов:
auto_update "yes"
И самое главное – конфигурируем аудиовыходы. Здесь мы создаем по одному выходу на каждую из клиентских “малин”, плюс один для самого сервера – он тоже будет выступать в роли равноправного клиента. Вот тут-то и пригодятся нам статические IP-адреса, которые мы назначили каждой из малин.
audio_output { type "pulse" name "Office" server "localhost" # server } audio_output { type "pulse" name "Living Room" server "192.168.1.4" # client #1 }
Ну что ж, перезапустим MPD. Рутовую сессию на этом можно закончить.
# service mpd restart # exit
Просканируем коллекцию для создании базы данных (это займет некоторое время, в зависимости от размера коллекции):
$ mpc -w update
Собственно, на этом — все.
Рулим!
Осталось всего ничего: как всем этим делом управлять. Тут ничего сложного, в нашем распоряжении вагон и маленькая тележка клиентов под всевозможные ОС. При выборе обязательно обращайте внимание на то, умеет ли клиент переключать выходные каналы (или, как они еще называются, Output Devices) – собственно, это именно та фича, которая позволяет включать/выключать того или иного клиента. Под Маком я остановился на Theremin, под Линуксом – на Gmpc.
Кульминация
Легкими и плавными движениями пальцев, нежно касаясь тачпада, я запустил Theremin, добавил первый попавшийся трек в плейлист и нажал Play. Через секунду из колонок в зале донеслись нежные переливы старой доброй композиции “Master of Puppets” вокально-инструментального ансамбля “Metallica”. Ребенок, сидящий внутри меня, возликовал —
“Ура!!! Вот то, о чем я мечтал 10 лет!!!”
Дополнительные градусы душевного тепла генерировались от осознания факта, что никакой «rocket science» задействовано не было, и все было собрано буквально за вечер из «подручных материалов», и даже без единого куска синей изоленты. Я прислушался — из офиса наверху тоже доносился звук! Я залез в меню и снял галку с «Living Room» — звук из колонок в зале пропал, и остался только в офисе.
Победа!
Эпилог
Уже через несколько минут внутренний перфекционист потребовал унификации интерфейса между девайсами и ОСями, и поэтому в голове тут же мелькнула безумная мысль “А вот хочу веб-интерфейс, да чтобы со всеми необходимыми функциями!” Беглый осмотр интернета оставил печальное ощущение: “Этот вроде ничего, но куцый. Этот вроде фичастый, но ставится через опу. Этот вообще заброшен.” Ну и так далее. Не говоря уже о том, что все они обладали одним фатальным недостатком. В общем, самые догадливые читатели уже все поняли: я решил написать свой, “с нотными партиями и пианистками”. Тем более, что веб-разработкой я никогда толком не занимался, но всегда хотелось попробовать страшного зверя jQuery, да и вообще оценить, насколько далеко ушли веб-технологии с тех пор, как я последний раз написал и забросил свой “хомяк” на narod.ru, с джаваскриптами и крутящимися менюшками. Поэтому за три будних вечера и один выходной день на свет родилось вот такое чудо: