IT-инфраструктура для бизнеса и творчества
Разработка
CodeX

Делаем AirPlay-станцию из старых колонок

Рассказываем, как мы в CodeX слушаем музыку с телефонов или ноутбуков, не подключая к ним никаких проводов.

Конечно, можно просто купить колонку с Bluetooth или AirPlay, но, если у вас есть обычные старые колонки и Raspberry, то можно создать станцию самим. Мы сделали из Raspberry Pi аудио-ресивер и подключили его к локальной сети по Ethernet-кабелю, а колонки к ней — через обычный AUX.

Для настройки станции будем использовать AirPlay-аудиоплеер Shairport Sync.

Подготовка

Самая важная часть системы — одноплатный компьютер Raspberry Pi. В нашем случае Raspberry Pi 2 Model B. Подойдёт и любая другая версия, к которой при необходимости можно будет подключить 3,5 мм разъём, например, с помощью платы расширения.

Raspberry Pi 2 Model B

Для работы самого микрокомпьютера потребуется microSD-карта объемом от 4 ГБ, на которую необходимо установить операционную систему.

Установка ОС

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

Более подробная инструкция по установке ОС на Raspberry — на официальном сайте.

Подключение по SSH

Чтобы иметь возможность подключаться к Raspberry с рабочего компьютера через терминал, после установки системы вам потребуется создать пустой текстовый файл с названием ssh (иногда ssh.txt) в корневой директории карты памяти.

Теперь подключаем Raspberry к локальной сети (вставляем Ethernet-провод) и включаем питание.

Давайте попробуем подключиться к Raspberry через терминал с другого компьютера. Для начала нужно узнать IP-адрес Raspberry, например, в панели администратора роутера — в разделе подключенных к сети устройств (Devices).

Обычно панель администратора роутера доступна по адресу http://192.168.1.1 или http://192.168.0.1, дефолтные логин и пароль указаны на роутере. Спросите параметры подключения к роутеру у вашего системного администратора.

Устройство Raspberry доступно по адресу 192.168.1.100

Для установки SSH-подключения потребуется найти в интернете стандартные логин и пароль для пользователя системы, которую вы установите на Raspberry.

Пусть IP-адрес — 192.168.1.100, а логин и пароль от ОС — pi / raspberry. Тогда подключиться к станции можно с помощью команды

ssh pi@192.168.1.100

Установка

Первым делом рекомендуется обновить список репозиториев пакетов и установить все обновления.

sudo apt-get update sudo apt-get upgrade -y

Теперь активируем обновлённый аудио-драйвер.

printf "\n# Set audio output to headphone jack\naudio_pwm_mode=2\n" | sudo tee -a /boot/config.txt

Устанавливаем зависимости для сборки и установки Shairport Sync.

sudo apt install -y \ build-essential \ git \ xmltoman \ autoconf \ automake \ libtool \ libdaemon-dev \ libpopt-dev \ libconfig-dev \ libasound2-dev \ libpulse-dev \ avahi-daemon \ libavahi-client-dev \ libssl-dev \ libsoxr-dev

Загружаем исходные файлы пакета.

git clone https://github.com/mikebrady/shairport-sync.git

Настраиваем и подготавливаем пакет к сборке.

cd shairport-sync autoreconf -i -f ./configure --sysconfdir=/etc \ --with-alsa \ --with-pa \ --with-pipe \ --with-avahi \ --with-ssl=openssl \ --with-metadata \ --with-soxr \ --with-systemd

Теперь приступим к компиляции и установке пакета.

make sudo make install

Остается только активировать автозагрузку и запустить сервис.

sudo systemctl enable shairport-sync.service sudo service shairport-sync start

Настройки Shairport Sync хранятся в файле /etc/shairport-sync.conf.

// Sample Configuration File for Shairport Sync // Commented out settings are generally the defaults, except where noted. // General Settings general = { // name = "%h"; // This means "Hostname" -- see below. This is the name the service will advertise to iTunes. // The default is "Hostname" -- i.e. the machine's hostname with the first letter capitalised (ASCII only.) // You can use the following substitutions: // %h for the hostname, // %H for the Hostname (i.e. with first letter capitalised (ASCII only)), // %v for the version number, e.g. 3.0 and // %V for the full version string, e.g. 3.0-OpenSSL-Avahi-ALSA-soxr-metadata-sysconfdir:/etc // Overall length can not exceed 50 characters. Example: "Shairport Sync %v on %H". ...

Например, можно задать имя, которое поможет идентифицировать этот ресивер. Для этого нужно раскомментировать строку и заполнить параметр name:

name = "CodeX Speaker";

После внесения правок в конфигурационный файл потребуется перезагрузить сервис Shairport Sync.

sudo service shairport-sync restart

Теперь устройства на iOS или macOS могут увидеть колонку в списке доступных аудиовыходов.

Остаётся подключить к Raspberry колонки и наслаждаться беспроводной трансляцией музыки.

Настройка громкости

Изначально громкость звука на Raspberry установлена не на самый максимум. Кому-то этого может не хватать. Давайте установим громкость ОС на 100%, чтобы управлять громкостью воспроизведения можно было только на телефоне или ноутбуке.

Список интерфейсов можно увидеть, выполнив команду amixer controls:

pi@raspberrypi:~ $ amixer controls numid=3,iface=MIXER,name='PCM Playback Route' numid=2,iface=MIXER,name='PCM Playback Switch' numid=1,iface=MIXER,name='PCM Playback Volume' numid=5,iface=PCM,name='IEC958 Playback Con Mask' numid=4,iface=PCM,name='IEC958 Playback Default'

Нас интересует интерфейс PCM Playback Volume. Задаём ему максимальное значение: amixer cset numid=1 100%

pi@raspberrypi:~ $ amixer cset numid=1 100% numid=1,iface=MIXER,name='PCM Playback Volume' ; type=INTEGER,access=rw---R--,values=1,min=-10239,max=400,step=0 : values=400 | dBscale-min=-102.39dB,step=0.01dB,mute=1

Теперь максимальная громкость музыки увеличится.

Надеемся, статья будет полезной. Подписаться на нас можно во «ВКонтакте» или Telegram — там мы делимся опытом и пишем небольшие заметки о веб-разработке.

(function () { let cdnUrl = `https://specialsf378ef5-a.akamaihd.net/SelectelBranding/images/` let previousArticleNumber = null let currentArticleNumber = 0 let platform = 'Desktop' let articles = [ { name: 'camera', url: `${cdnUrl}CameraCat`, text: 'умную камеру для\u00A0наблюдения за\u00A0котиками', link: 'https://vc.ru/selectel/306690', num: 3 }, { name: 'chill', url: `${cdnUrl}ChillCat`, text: 'трекер, который подскажет, когда пора отдохнуть', link: 'https://vc.ru/promo/288561-eye-tracker', num: 1 }, { name: 'cloud', url: `${cdnUrl}CloudCat`, text: 'котика: даёшь ему «пять», а\u00A0он делает бэкап в облако', link: 'https://vc.ru/dev/294799-maneki-neko', num: 2 } ] let buttonCycle = document.querySelector('.button--cycle') let buttonChoose = document.querySelector('.button--choose') let buttonMobile = document.querySelector('.button--mobile') let textField = document.querySelector('.selectel-footer-subtitle') let imageAgent = document.querySelector('.image--agent') let banner = document.querySelector('.selectel-footer') buttonCycle.addEventListener('click', cycleClick) buttonChoose.addEventListener('click', () => sendEvent(`Promo ${articles[currentArticleNumber].num} Left`, 'Click')) buttonMobile.addEventListener('click', () => sendEvent(`Promo ${articles[currentArticleNumber].num} Left`, 'Click')) let media = window.matchMedia("(max-width: 570px)") media.addEventListener('change', matchMedia) function matchMedia() { if (media.matches) { platform = 'Mobile' } else { platform = 'Desktop' } update() } matchMedia() function cycleClick(event) { sendEvent(`Promo ${articles[currentArticleNumber].num} Right`, 'Click') if (event) { event.preventDefault() event.stopPropagation() } window.open('https://vc.ru/tag/selectelDIY', '_blank') //cycle(event) } function cycle(event) { // incrementArticleNumber() textField.innerHTML = generatedText() imageAgent.src = articles[currentArticleNumber].url + platform + '.svg?3' imageAgent.setAttribute("class", "") imageAgent.classList.add('image--agent', articles[currentArticleNumber].name) banner.href = articles[currentArticleNumber].link } function update() { banner.href = articles[currentArticleNumber].link imageAgent.src = articles[currentArticleNumber].url + platform + '.svg' textField.innerHTML = generatedText() } function incrementArticleNumber() { previousArticleNumber = currentArticleNumber if (currentArticleNumber >= articles.length - 1) { currentArticleNumber = 0 } else { currentArticleNumber++ } } const sendEvent = (label, action = 'Click') => { const value = `SelectelDIY — loc: Footer — ${label} — ${action}`; if (window.dataLayer !== undefined) { window.dataLayer.push({ event: 'data_event', data_description: value, }); } }; function generatedText() { let defaultText if (platform === 'Desktop') { defaultText = `Мы тут собрали %text%. Хотите научим?` } else { defaultText = `Мы тут собрали %text%.` } return defaultText.replace('%text%', articles[currentArticleNumber].text) } function getRandom(min, max) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } (function create() { currentArticleNumber = getRandom(0, articles.length - 1) cycle() let page = document.querySelector('.page--entry') if (page) { function insertAfter() { let parents = page.querySelectorAll('[data-id="7"]') let referenceNode = parents[0] referenceNode.parentNode.insertBefore(banner, referenceNode.nextSibling); loaded() } setTimeout(() => insertAfter(), 0) } }()) function loaded() { banner.classList.add('loaded') } loadImages([ `${cdnUrl}CameraCatDesktop.svg`, `${cdnUrl}ChillCatDesktop.svg`, `${cdnUrl}CloudCatDesktop.svg`, `${cdnUrl}CameraCatMobile.svg`, `${cdnUrl}ChillCatMobile.svg`, `${cdnUrl}CloudCatMobile.svg?3`, ]) function loadImages(urls) { return Promise.all(urls.map(function (url) { return new Promise(function (resolve) { var img = document.createElement('img'); img.onload = resolve; img.onerror = resolve; img.src = url; }); })); } }())
0
12 комментариев
Популярные
По порядку
Написать комментарий...

vc мимикрирует в habr. Ностальжи..

11

Проще Apple TV 3 купить

2

Вы не поняли, тут удовольствие от процесса. Купить можно все что угодно как вы помните из одного рекламного лозунга.

3

Вот именно! Можно взять старую советскую колонку и сделать эйр плей) вот бы ещё время свободное было на это...

1

DIY для тех у кого много свободного времени :)

0

Ребят, а Spotify Connect ещё как-то таким способом можно подвязать?

0

не пользуюсь spotify, поэтому не могу проверить, но, кажется, это то, что нужно

3

Сделал наконец-то, проверил - работает на ура!

0

Комментарий удален

sudo amixer cset numid=3 1

1

Комментарий удален

Класс! Времени бы еще побольше или прокрастинации поменьше)

0

цап встроенный в пи только говно и звук такой же

0

Приколько получилось) Спасибо!

А можно сделать как на яблочной колонке, чтобы аудиопоток не переключался, а параллельно играл на ноуте и на малинке ? ред.

0
Читать все 12 комментариев
Глава американской компании Better.com уволил 900 сотрудников одним видеозвонком Статьи редакции

«Если вы сейчас смотрите это, значит вы в той невезучей группе, которую увольняют», — сказал работникам директор.

Я пришёл к вам с плохой новостью. Рынок изменился, как вы знаете, и мы должны двигаться за ним вперёд, чтобы выжить, процветать и исполнять нашу миссию. [...] Я делаю это второй раз в своей карьере и не хочу повторять. В последний раз, я плакал, но на этот раз надеюсь быть сильнее. [...] Если вы сейчас смотрите это, значит вы в той невезучей группе, которую увольняют.

Вишал Гарг
И сотрудников тоже касается: кибербуллинг на рабочем месте
Design vector created by pikisuperstar - www.freepik.com
«Неслучайная случайность», или как рождаются крипто стартапы на примере Freya

Статья носит сугубо ознакомительный характер и не призывает к инвестированию в какие либо активы.

re:Store продал Macbook Pro с раскладкой azerty и серийный номер ноутбка не совпадает с серийным номером на коробке
Продавец eBay из Кургана стала победителем в финале Всероссийского конкурса «Молодой предприниматель России 2021»

27 ноября в Москве состоялся финал ежегодного конкурса «Молодой предприниматель России 2021». В нём приняли участие предприниматели и самозанятые в возрасте до 35 лет. Всего было подано более 300 заявок из 43 регионов страны.

Хоум кредит про меня забыли. Долг с 2009года

Решил я значит проверить свою кредитную историю на одном из известных ресурсах. И что я обнаружил? Действующий долг в #хоум_кредит с 2009 года и как следствие краснющую историю! Я конечно же позвонил в эту контору, говорю каким образом банк забыл про меня? - а вы знаете? Мы вам звонили звонили... но не дозвонились ... Так же как и вашим…

Как обманывает Учи.ру, пытаясь заработать больше денег

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

Откуда берут взрослые деревья для парков и улиц

А также сколько они стоят и почему выращивать их — неплохой бизнес.

Агрегатор "Яндекс.Еда" не возвращают оплату за заказ, которого не было

Здравствуйте! Ситуация следующая, 22.10.2021 г. я сделала заказ у агрегатора доставки "Яндекс.Еда". Доставка из Магазина "Магнит". В момент списания оплаты с банковской карты за заказ заметила, что адрес доставки товара указан с ошибкой. В заказ проставился рабочий адрес, а не домашний, ехать на автомобиле от дома до работы мне 10 минут, пешком…

SkillFactory раздает подарки: повышенная ставка и новогодний марафон для вебмастеров

В преддверии Нового года мы решили порадовать своих настоящих и будущих партнеров — участников партнерской программы школ Skillfactory, Contented и Product LIVE. Это возможность получить денежный бонус и заодно увеличить прибыль от продажи наших курсов.

Дайджест новостей Сбера: сайт Digital Пётр, сценарии для умного дома и платина от Forbes

Прошлый дайджест мы целиком посвятили 180-летию Сбера, поэтому новостей накопилось много. Среди них — запуск сайта по распознаванию рукописей Петра I, большое обновление на платформе умного дома Sber и другие. Рассказываем всё самое интересное.

Картинка, сгенерированная ruDALL-E по запросу «рыжий котик»
null