[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-105331":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":9,"pushedAt":9,"updatedAt":28,"readmeContent":29,"aiSummary":9,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":30,"discoverSource":31},105331,"spotiya","klockky\u002Fspotiya","klockky","Spotify Connect, voice control and terminal UI for Yandex Stations",null,"Rust",53,7,51,5,0,2,6,43.91,"MIT License",false,"main",true,[24,25,26,27],"librespot","rust","spotify-connect","yandex-station","2026-11-01 00:14:26","# spotiya\n\n[![Build and test](https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Factions\u002Fworkflows\u002Fci.yml)\n\nSpotify Connect для Яндекс Станций: музыка, голосовое управление и TUI в одном\nбинарнике на Rust. Воспроизведение и подключение к Spotify обеспечивает\n[librespot](https:\u002F\u002Fgithub.com\u002Flibrespot-org\u002Flibrespot\u002Ftree\u002Fv0.8.0).\n\n> [!CAUTION]\n> **Использование дополнения PlayPlay — на ваш страх и риск. Возможна блокировка аккаунта Spotify.**\n> Есть [сообщения о блокировках](https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Fissues\u002F4) у пользователей,\n> использовавших PlayPlay. Точная причина блокировок пока не установлена;\n> безопасность аккаунта с этим дополнением не гарантируется.\n\n## Быстрая установка и обновление\n\nВ **root-терминале самой колонки** (SSH или `adb shell`) вставьте строку целиком,\n**вместе со скобками**, и нажмите Enter:\n\n```sh\n(set -e; d=$(mktemp -d \u002Ftmp\u002Fspotiya.XXXXXX); trap 'rm -rf \"$d\"' EXIT; cd \"$d\"; echo 'Downloading Spotiya...'; get() { LD_LIBRARY_PATH=\u002Fsystem\u002Fvendor\u002Fquasar\u002Flibs \u002Fsystem\u002Fvendor\u002Fquasar\u002Fmaind --gst-launch \"souphttpsrc location=https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Freleases\u002Flatest\u002Fdownload\u002F$1 ssl-strict=true ssl-ca-file=\u002Fetc\u002Fssl\u002Fcerts\u002Fca-certificates.crt iradio-mode=false timeout=15 retries=1 ! filesink location=$1\" >log 2>&1 && grep -Fq 'EOS: end of stream' log && ! grep -Fq 'ERROR from ' log && [ -s \"$1\" ]; }; get INSTALL_SHA256SUMS && get install.sh || { echo 'Installer download failed.' >&2; exit 1; }; [ \"$(wc -l \u003CINSTALL_SHA256SUMS)\" -eq 1 ] && grep -Eqx '[0-9a-f]{64}  install\\.sh' INSTALL_SHA256SUMS && sha256sum -c INSTALL_SHA256SUMS || { echo 'Installer checksum mismatch.' >&2; exit 1; }; sh install.sh)\n```\n\nКоманда открывает интерактивное меню: установка или обновление до последнего\nстабильного [релиза GitHub](https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Freleases\u002Flatest),\nпроверка совместимости без установки и полное удаление. Выберите пункт цифрой\nи нажмите Enter; Enter без выбора или конец ввода отменяет действие.\nПри установке и обновлении вход в аккаунт, настройки, профили и дополнения\nсохраняются. При первой установке добавляются команда `spotiya` и автозапуск;\nпри обновлении сохраняется состояние\nслужбы. Во время загрузки команда выводит сообщение — дождитесь результата.\n\nПосле установки откройте интерфейс:\n\n```sh\nspotiya tui\n```\n\nPlayPlay, AirPlay и YouTube можно установить через `spotiya addons`. Нужны root-доступ и\nSpotify Premium. Быстрый способ проверен на **Мини 2**; для прошивок без подходящего\n`maind --gst-launch` доступна [установка через ПК](#через-пк).\n\n## Поддерживаемые устройства\n\nПроект поддерживает **первую Мини (YNDX-0004, `yandexmini`)** с glibc 2.23\nи **Мини 2** с glibc 2.30. Обе используют Buildroot и 32-битный ARM\nuserspace. Имя в Spotify берётся из hostname колонки. Для других моделей нужны\nсовместимая сборка, ALSA и проверка локального протокола Алисы; поддержка всех\nмоделей не заявляется.\n\n## Возможности\n\n- Spotify Connect, вход через приложение или короткий код на `spotify.com\u002Fpair`.\n- Голосовой поиск треков и исполнителей, пауза, продолжение и смена трека.\n- Общая громкость Spotify и колонки через ALSA Master.\n- Плавное приглушение Spotify на время обращения к Алисе и её ответа.\n- TUI с поиском, текущим треком, прогрессом и управлением воспроизведением.\n- Кнопки, жесты, подсветка, громкость и музыкальный спектр на дисплее Мини 2.\n- Автозапуск, восстановление процесса после сбоя и сохранение входа.\n- Остановка серии неудачных загрузок с явным повтором из TUI.\n- Профили устройства: ALSA, локальный IPC Алисы, кнопки, кольцо и дисплей.\n- Диагностика с отчётом без токенов и обновление из GitHub Releases с откатом.\n- Дополнения: AirPlay 2, PlayPlay и YouTube (каст из приложений и ссылки из TUI).\n\nНужны Spotify Premium и уже работающий root-доступ к колонке. Получение root,\nпрошивка и первоначальная активация станции в проект не входят.\n\n## Установка\n\nДля установки или обновления прямо на колонке используйте [быструю команду](#быстрая-установка-и-обновление)\nв начале README. Если Spotiya уже установлена, достаточно:\n\n```sh\nspotiya update\n```\n\nКоманда использует последний стабильный релиз из GitHub Releases. Если версия\nуже актуальна, переустановка и перезапуск приёмника не выполняются.\n\n### Удаление\n\nВ root-терминале колонки выполните:\n\n```sh\nspotiya uninstall\n```\n\nВведите `uninstall` для подтверждения. Приёмник и дополнения остановятся;\nбудут удалены автозапуск, команда `spotiya`, все дополнения, сохранённый вход,\nнастройки, профили, бэкапы и журналы Spotiya. Штатная Алиса и её данные сохраняются.\nЕсли остановить процессы не удалось, файлы установки не удаляются.\n\nДля автоматизации: `spotiya uninstall --yes` (без запроса подтверждения).\nПолное удаление также доступно в меню быстрой настройки. Для старых версий без\nкоманды удаления установщик скачает текущий пакет и запустит из него удаление,\nне устанавливая его поверх старого.\n\nСкачанный `install.sh` без аргументов открывает меню. Для запуска без меню:\n`sh install.sh --install`, `sh install.sh --check` или\n`sh install.sh --uninstall --yes`.\n\n### Через ПК\n\nГотовые ARMv7-сборки доступны в [GitHub Releases](https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Freleases)\nи [артефактах Actions](https:\u002F\u002Fgithub.com\u002Fklockky\u002Fspotiya\u002Factions\u002Fworkflows\u002Fci.yml).\n\nНа ПК распакуй архив и передай каталог на колонку:\n\n```sh\nsha256sum -c SHA256SUMS\ntar -xzf spotiya-armv7-linux-gnueabihf.tar.gz\nadb -s SPEAKER_IP:5555 push spotiya \u002Ftmp\u002F\nadb -s SPEAKER_IP:5555 shell sh \u002Ftmp\u002Fspotiya\u002Fscripts\u002Finstall.sh\n```\n\nУстановщик запускается от root на колонке. Он проверяет бинарник, профиль и свободное место, сохраняет предыдущие бинарник,\nскрипты и встроенные профили в `backups\u002F`, устанавливает автозапуск и команду\n`spotiya`. Если корневая файловая система была read-only, после установки она\nвозвращается в read-only. При ошибке установки или запуска восстанавливается\nпредыдущая версия. Данные входа и пользовательские профили сохраняются.\nПри первой установке служба запускается; при обновлении сохраняется её состояние:\nработающий приёмник перезапускается, остановленный остаётся остановленным.\n\nИсполняемый файл и скрипты находятся в `\u002Fdata\u002Fopt\u002Fspotify-connect`, состояние —\nв `receiver-state\u002F`, журнал — в `\u002Ftmp\u002Fspotify-connect.log`.\n\n### Экспериментальный PlayPlay\n\nНачиная с 0.9.3 готовый декодер устанавливается из GitHub Releases: откройте\n`spotiya addons`, выберите **PlayPlay** и нажмите Enter. Либо выполните:\n\n```sh\nspotiya addon install playplay\n```\n\nAPK и ручное копирование файлов для установки не нужны. После проверки SHA-256,\nманифеста и протокола декодер попадает в `playplay\u002Fbin\u002Fplayplay-decoder`.\nВ TUI появится `Ready (on demand)`. Приёмник подхватывает дополнение без перезапуска;\nесли предыдущая загрузка трека завершилась ошибкой, повторите воспроизведение.\nРанее вручную установленный `playplay-decoder` рядом с `spotiya` также поддерживается.\n\nОбычный AES-путь используется первым; PlayPlay запрашивается только при явном\nотказе AP. При успешном обычном ключе, сетевой ошибке или таймауте дополнительный\nпроцесс не запускается. Параметры декодера запрашиваются при первом отказе и\nсохраняются в памяти между сеансами Spotify. В журнале появляются\n`AP audio key refused; trying PlayPlay`, `PlayPlay decoder configured on demand`\nи `PlayPlay decoder ready`.\nМатериал ключей и ответы сервера в журнал не выводятся.\n\nДекодер работает отдельным процессом для каждого загружаемого трека. Чтение и\nперемотка передаются через локальный бинарный канал с ограничением размера и\nтаймаутами. При освобождении трека или ошибке процесс завершается. Ошибка\nполучения ключа для музыкального трека останавливает загрузку до аудиодекодера;\nзашифрованный поток больше не разбирается как незашифрованный MP3.\n\nЭкспериментальный `playplay-decoder` содержит выделенные фрагменты Spotify APK\nи запускает их через Unicorn. Он распространяется отдельным дополнением\n`spotiya-playplay-armv7.tar.gz`; основной бинарник Spotiya их не содержит.\n[Описание сборки и происхождения пакета](decoder\u002FREADME.md).\nБез дополнения приёмник использует обычные аудиоключи.\nРезервный путь проверен запросом ключа проблемного аккаунта и побайтным сравнением\nрасшифрованного образца без запуска воспроизведения. На Мини 2 также подтверждён\nслышимый звук с проблемного аккаунта; в журнале проверено использование PlayPlay.\nЭто не проверка всех треков или всех аккаунтов. На Мини 1 этот путь пока не проверялся.\n\n## Профили устройств\n\n`spotiya profiles` показывает встроенные и пользовательские профили, `spotiya profile` — выбранную\nконфигурацию и обнаруженные возможности. Эти команды доступны без запуска\nприёмника; профиль работающего приёмника также виден в TUI.\n\n- `mini1` — первая Мини: штатная ALSA, общая громкость `Master` и Quasar IPC.\n  Допустим также выбор по имени `yandexmini`.\n- `mini2` — проверенный профиль Мини 2 с Quasar IPC и драйвером её кнопок,\n  шестисегментного RGB-кольца и четырёхразрядного дисплея.\n- `generic` — Spotify Connect через ALSA без штатного IPC и физического управления.\n- `auto` — использует `receiver-state\u002Fprofile.json`, если файл существует;\n  иначе использует `common.deviceType` из системного `quasar.cfg` и device tree.\n  `yandexmini` выбирает `mini1`, `yandexmini_2` — `mini2`; неизвестные модели получают `generic`.\n\nУ первой Мини отдельный драйвер датчика жестов и подсветки пока не включён.\nКнопка микрофона и штатные жесты остаются у Алисы; изменение общего `Master`\nподхватывается приёмником. Экрана у этой модели нет. Фирменная ALSA-библиотека\nреализует виртуальный `default`, поэтому профиль не подменяет его прямым `hw`.\n\nКнопки, кольцо и дисплей проверяются независимо. Для кольца и дисплея должны\nсуществовать все нужные sysfs-каналы; для кнопок Мини 2 проверяется имя input-устройства.\nОтсутствующая возможность отключается. Голосовое управление в общем профиле\nпоказывается как `unavailable`; команды паузы штатному плееру не отправляются.\n\nВ TUI нажми `d`, выбери профиль стрелками или `j`\u002F`k` и подтверди Enter.\nИз терминала: `spotiya profile select mini1`, `spotiya profile select mini2`, `spotiya profile select generic`\nили `spotiya profile select auto`. Выбор сохраняется при обновлениях и перезагрузках.\nРаботающий приёмник перезапускается; воспроизведение при этом прекращается.\nОстановленный приёмник остаётся остановленным. При неудачном запуске возвращается\nпредыдущий выбор и выполняется попытка восстановить приёмник.\n\nДля другой колонки положи JSON в `\u002Fdata\u002Fopt\u002Fspotify-connect\u002Fprofiles\u002F`:\nон появится в меню. Его можно выбрать по `id` или командой\n`spotiya profile select \u002Fпуть\u002Fк\u002Fпрофилю.json`. Выбранный файл сохраняется\nкак копия в `receiver-state\u002Fprofile-selection.json`, поэтому удаление исходника\nне ломает запуск. После редактирования исходного JSON выбери его повторно.\nВстроенные варианты имеют приоритет над одноимёнными пользовательскими `id`.\n\nДля прежней настройки через `receiver-state\u002Fprofile.json` выбери `auto`.\nПараметр бинарника `--profile ID_OR_JSON` переопределяет сохранённый выбор только\nдля текущего запуска. Новый профиль описывает ALSA, Quasar IPC и поддерживаемый\nдрайвер; для другой схемы кнопок или дисплея может потребоваться новый драйвер.\nОшибки JSON и неизвестные поля останавливают запуск; скрытого перехода к другому\nпрофилю при ошибке нет.\n\nПример собственного аудиопрофиля; значения ALSA выбираются на целевой колонке:\n\n```json\n{\n  \"version\": 1,\n  \"id\": \"my-station\",\n  \"name\": \"My Station\",\n  \"audio\": {\n    \"device\": \"plughw:0,0\",\n    \"format\": \"S16\",\n    \"mixer_device\": \"hw:0\",\n    \"mixer_control\": \"PCM\",\n    \"mixer_index\": 0,\n    \"mixer_channel\": \"mono\"\n  },\n  \"voice\": null,\n  \"controls\": null\n}\n```\n\nЕсли станция использует совместимый Quasar IPC, поле `voice` задаётся как\n`{\"protocol\":\"quasar\",\"address\":\"127.0.0.1:9875\"}` с её локальным адресом.\nВ профиле Мини 2 вынесены `input_device`, `input_name`, коды трёх кнопок,\n`ring_prefix` и `display_prefix`. Неиспользуемый путь можно заменить на `null`;\nвизуализация работает и без input-устройства. Драйвер `mini2` предполагает\nсовместимые жесты, отдельное input-устройство кнопок и ту же геометрию светодиодов.\nДля другого протокола экрана, подсветки или голосового IPC потребуется новый\nдрайвер. Профили сами по себе не добавляют поддержку Android Audio HAL или\nсовместимость ARM-сборки с любым userspace.\n\nДля ручного запуска можно выбрать встроенный профиль или файл без изменения\nсохранённой конфигурации:\n\n```sh\n\u002Fdata\u002Fopt\u002Fspotify-connect\u002Fspotiya --profile generic --profile-info\n\u002Fdata\u002Fopt\u002Fspotify-connect\u002Frun.sh --profile \u002Fabsolute\u002Fpath\u002Fprofile.json\n```\n\nВыбор передаётся дочернему процессу при автоматическом перезапуске.\nВстроенные профили находятся внутри бинарника; JSON-файлы в пакете служат\nготовыми образцами. Имя в списке Spotify по-прежнему берётся из hostname.\n\n## Управление\n\nВнутри `adb shell`:\n\n```sh\nspotiya                    # TUI\nspotiya login              # вход по коду\nspotiya play \"No Surprises\"\nspotiya pause\nspotiya resume\nspotiya retry              # повтор после серии ошибок\nspotiya next\nspotiya previous\nspotiya volume 25\nspotiya voice off\nspotiya voice on\nspotiya spectrum on\nspotiya spectrum off\nspotiya release            # освободить сеанс для штатной музыки\nspotiya status\nspotiya profile\nspotiya profiles\nspotiya profile select auto\nspotiya restart\n```\n\nКоманды `start`, `stop` и `version` тоже доступны. `OK` означает постановку\nкоманды в очередь; поиск и загрузка трека выполняются асинхронно.\n\nДля управления с ПК используй `bin\u002Fspotiya`: нужны Python 3 и adb.\n\n```sh\npython3 bin\u002Fspotiya --device SPEAKER_IP:5555 tui\npython3 bin\u002Fspotiya --device SPEAKER_IP:5555 login\n```\n\nУстройство можно задать через `SPOTIYA_DEVICE` или в\n`~\u002F.config\u002Fspotiya\u002Fconfig.json`:\n\n```json\n{\"device\": \"SPEAKER_IP:5555\"}\n```\n\nЕсли устройство не задано, выбирается единственное подключённое через adb.\nПри нескольких подключениях нужно указать устройство явно.\n\n### TUI\n\n| Клавиша | Действие |\n| --- | --- |\n| `Space` | Пауза \u002F продолжение |\n| `n` \u002F `p` | Следующий \u002F предыдущий трек |\n| `+` \u002F `-` | Громкость |\n| `\u002F` | Поиск |\n| `l` | Вход по короткому коду |\n| `v` | Голосовое управление вкл\u002Fвыкл |\n| `e` | Визуализация спектра вкл\u002Fвыкл |\n| `r` | Повтор после серии ошибок, когда закончится пауза |\n| `x` | Освободить сеанс для Алисы |\n| `q` | Закрыть TUI, оставив музыку |\n\nВход по коду ждёт подтверждения до десяти минут. До подтверждения и проверки\nнового входа текущий аккаунт продолжает работать. Токены не выводятся в TUI,\nстатус или журнал приложения.\n\n### Голос и кнопки\n\nПримеры: «Алиса, включи Radiohead», «включи песню No Surprises», «останови\nмузыку», «Алиса, хватит», «продолжи музыку», «продолжай», «следующий трек».\n\nПриёмник получает окончательный текст распознавания из локального IPC Алисы\nна `127.0.0.1:9875`, отменяет штатный музыкальный ответ и передаёт запрос\nсуществующему сеансу librespot. Собственное распознавание микрофона не используется.\nПока играет Spotify, штатный музыкальный плеер периодически ставится на паузу,\nчтобы дорожки не накладывались. Голосовые фразы в журнал не записываются.\n\nБыстрые команды без слова «Алиса» приходят из штатного `CommandSpotterCapability`:\n«хватит», «стоп», «пауза», «играй», «продолжай» (также «продолжи»), «дальше», «назад»\nи «следующий» управляют воспроизведением. «Громче» и «тише» меняют громкость\nштатными средствами; Spotiya подхватывает общий Master без второго шага громкости.\nДоступность конкретной фразы зависит от прошивки и штатной модели распознавания.\nSpotiya назначает действия уже распознанным фразам; добавление слова в её обработчик\nсамо по себе не учит штатную модель распознавать новую быструю фразу.\nВ приложении «Дом с Алисой» должны быть включены быстрые команды для музыки\n(Настройки → Ассистент → Быстрые команды).\n\nПри активации Алисы Spotify плавно приглушается до 20% амплитуды за 80 мс.\nПриглушение сохраняется во время распознавания, ожидания и озвучивания ответа;\nпосле возврата Алисы в ожидание звук восстанавливается за 300 мс. Это обработка\nтолько PCM Spotify. Выбранная громкость музыки сохраняется отдельно от временных\nзначений Master, которые штатная система выставляет для речи. Они не передаются\nобратно в Spotify; через 750 мс после завершения диалога Master возвращается\nк выбранному уровню. Изменения ползунком или кнопками во время диалога также\nсохраняются. Для распознанных команд «громче», «тише», «громкость…» и других\nкоманд управления звуком принимается новый уровень, выставленный Алисой.\nВ TUI появляется `Alice: ducked`. При разрыве локального соединения\nприглушение снимается; если завершающее событие потерялось, оно снимается через\n60 секунд после последнего события активности. Команда `voice off` отключает\nперехват музыкальных фраз, сохраняя приглушение для обычных вопросов Алисе.\n\nНа Мини 2 центральная кнопка управляет паузой; `+`\u002F`−` меняют громкость;\nжесты Алиса → `+`\u002F`−` переключают треки. Есть короткие эффекты кольца и вывод\nгромкости `0–100` на дисплей. Профиль включается только при наличии sysfs-интерфейса\nМини 2. Кнопка отключения микрофона не перехватывается.\n\n### Спектр на дисплее\n\nНа Мини 2 клавиша `e` в TUI или команда `spotiya spectrum on` включает четыре\nстолбца спектра: басы слева, высокие частоты справа (100, 400, 1600 и 6400 Гц).\nОни обновляются 20 раз в секунду по звуку Spotify. Это визуализация;\nэквализация и сами аудиоданные не меняются.\n\nИзменение громкости на две секунды показывает проценты поверх спектра.\nНа паузе, при отключении визуализации и завершении Spotify возвращаются часы.\nШтатные анимации имеют приоритет. Настройка сохраняется после перезапуска;\nпри первой установке визуализация выключена. Для других моделей TUI показывает\n`unavailable`, пока для их дисплея не добавлен профиль. При выключенной\nвизуализации анализ звука не выполняется.\n\nРазбор музыкальных фраз экспериментальный. Необычные имена устройств умного\nдома могут быть приняты за музыкальный запрос. Альбомы и плейлисты пока\nобрабатываются как текстовый поиск. После перезапуска «включи музыку» запускает\nпоследний трек сначала; очередь и позиция не сохраняются.\n\n## Проверка устройства и отчёт\n\n```sh\nspotiya doctor\nspotiya doctor report                       # новый JSON-файл в \u002Ftmp\nspotiya doctor report \u002Ftmp\u002Fmy-report.json\n```\n\n`doctor` проверяет процесс и наблюдение за ним, актуальность статуса, сохранённый\nпрофиль, ALSA-микшер, громкость и mute, Quasar IPC, свободное место и RAM,\nналичие сохранённого входа, DNS и HTTPS для Spotify, входа и обновлений.\nКоманда не запускает приёмник, не меняет громкость и не открывает PCM-устройство.\nПроверка HTTPS не запускает воспроизведение и не требует входа в Spotify.\n`FAIL` даёт ненулевой код завершения; `WARN` указывает, например, на остановленную\nслужбу или отсутствие сохранённого входа.\n\nДля отчёта из последних 64 КиБ каждого журнала берутся только счётчики категорий:\nключ аудио, сеть, декодер, аудиоустройство, авторизация и другие предупреждения.\nИсторическая ошибка в журнале не означает, что она продолжается сейчас.\nИсходные строки логов, токены, содержимое credentials, имя аккаунта, hostname,\nназвания треков и пути пользовательских профилей в JSON не копируются.\nФайл создаётся с правами `0600`; существующий файл не перезаписывается.\nОтчёт можно приложить к issue после копирования с колонки.\n\nС ПК доступны те же проверки; путь отчёта относится к колонке:\n\n```sh\npython3 bin\u002Fspotiya --device SPEAKER_IP:5555 doctor report\n```\n\n## Обновление\n\n```sh\nspotiya update check                         # проверить последний стабильный релиз\nspotiya update                               # установить более новую версию\nspotiya update v0.8.0                         # выбрать опубликованный стабильный релиз\n```\n\nКоманда скачивает ARMv7-архив и `SHA256SUMS` из GitHub Releases по HTTPS,\nпроверяет SHA-256, структуру архива и соответствие версии бинарника тегу.\nЧерновики и предварительные релизы не устанавливаются. Равная или более старая\nверсия пропускается. Артефакты Actions не считаются опубликованным релизом;\nесли релизов ещё нет, `update check` сообщает об этом без изменения устройства.\nКонтрольная сумма сверяется с файлом из того же релиза; отдельной подписи релиза нет.\n\nОбновление использует тот же установщик с проверкой профиля и места, что и\nручная установка. При ошибке копирования или неготовности работающего приёмника\nвосстанавливаются предыдущие бинарник, скрипты и встроенные профили, затем\nвыполняется попытка запуска старой версии. Готовность проверяется локально;\nотсутствие Интернета само по себе не вызывает откат. Обновление прерывает текущую\nмузыку и не возобновляет её автоматически. Остановленная служба остаётся остановленной.\nХранятся до двух последних новых копий `backups\u002Fmanaged-*`; старые ручные и\nсозданные прежними установщиками копии автоматически не удаляются.\n\nДля установки архива, уже переданного на колонку, в том числе из Actions:\n\n```sh\nspotiya update file \u002Ftmp\u002Fspotiya-armv7-linux-gnueabihf.tar.gz \u002Ftmp\u002FSHA256SUMS\n```\n\nЛокальный вариант тоже проверяет сумму и выполняет установку с откатом;\nон допускает повторную установку и возврат к более старой совместимой версии.\nФормат `SHA256SUMS` должен содержать имя `spotiya-armv7-linux-gnueabihf.tar.gz`.\nС ПК команды доступны через `python3 bin\u002Fspotiya --device SPEAKER_IP:5555 update …`;\nпути локального варианта относятся к файлам на колонке.\n\n## Диагностика воспроизведения\n\nЗагрузка трека отображается как `LOADING`: кнопки и спектр переходят под\nуправление Spotify после события воспроизведения. При `Unavailable` для текущего\nтрека захват снимается, прогресс останавливается, а TUI показывает `UNAVAILABLE`.\nОшибка предзагрузки следующего трека не сбрасывает текущий.\n\nПосле трёх последовательных неудачных загрузок spotiya закрывает сеанс Spotify,\nчтобы остановить автоматические пропуски. TUI показывает `RETRY REQUIRED`,\nпричину последней серии ошибок и отсчёт 15 секунд. Затем клавиша `r` или\n`spotiya retry` подключает приёмник заново и повторяет последний неудачный трек.\nПо окончании отсчёта автоматического повтора нет. Вход по новому коду также\nсбрасывает блокировку. Ошибки предзагрузки и повторы одного события не считаются;\nуспешная загрузка для воспроизведения или паузы сбрасывает счётчик.\n\nПричина определяется по предупреждениям и ошибкам librespot: ключ аудио,\nзагрузка по сети, декодирование или аудиоустройство. Это диагностическая\nподсказка; отказ выдачи ключа сам по себе не доказывает несовместимость аккаунта.\n\nПредупреждения и ошибки librespot, включая загрузку аудио, декодер и ALSA,\nпопадают в `\u002Ftmp\u002Fspotify-connect.log` по умолчанию. Для подробной диагностики\nплеера запусти приёмник в терминале:\n\n```sh\nspotiya stop\nRUST_LOG=warn,librespot_playback=debug \u002Fdata\u002Fopt\u002Fspotify-connect\u002Frun.sh\n```\n\nПосле диагностики останови его через `Ctrl+C` и выполни `spotiya start`.\n\n## Восстановление службы\n\n`spotiya start` запускает режим наблюдения `--supervise` того же бинарника.\nОн перезапускает приёмник после выхода с паузами 2, 4, 8, 16, 32 и максимум\n60 секунд. После минуты стабильной работы задержка снова начинается с двух\nсекунд. Отсутствие сети не отменяет последующие попытки запуска.\n\n`spotiya stop` останавливает и наблюдение, и приёмник; после ручной остановки\nслужба сама не запускается. Повторный `start` не создаёт второй экземпляр.\nПосле сбоя самого наблюдения следующий `start` останавливает оставшийся\nдочерний процесс и запускает службу заново. `run.sh` без `--supervise`\nпо-прежнему подходит для диагностики в переднем плане.\n\nЖурнал наблюдения — `\u002Ftmp\u002Fspotify-connect-supervisor.log`. Журнал приёмника\nсохраняется между перезапусками; перед очередным запуском файл от 256 КиБ\nперемещается в `\u002Ftmp\u002Fspotify-connect.log.1`. Новые скрипты устанавливаются\nвместе с бинарником через `scripts\u002Finstall.sh`.\n\n## Память\n\nПриёмник использует однопоточный асинхронный runtime и до двух вспомогательных\nпотоков для блокирующих операций. Они освобождаются после двух секунд простоя;\nих стеки ограничены 512 КиБ. Внутренний runtime плеера librespot использует\nодин рабочий поток; это значение можно переопределить переменной\n`TOKIO_WORKER_THREADS` перед запуском. ALSA-микшер открывается один раз и обновляется\nпо событиям, а буферы статуса и локального IPC используются повторно.\nПри ошибке микшера дескриптор открывается заново при следующем обращении.\n\nglibc использует одну арену выделения памяти; каждые 30 секунд без\nвоспроизведения свободные страницы возвращаются системе через `malloc_trim`.\nПриглушение изменяет существующий PCM-буфер без дополнительной копии.\nБитрейт, предзагрузка следующего трека и качество декодирования сохранены.\nRSS включает страницы бинарника и библиотек, разделяемые между процессами;\nдля сравнения расхода полезно учитывать также PSS и Private Dirty из\n`\u002Fproc\u002FPID\u002Fsmaps`. Расход во время воспроизведения зависит от трека и очереди.\n\nВ сравнении 0.5.0 и 0.6.0 на Мини 2 с подключённым Spotify без воспроизведения\nчисло потоков приёмника уменьшилось с 8 до 5, виртуальное адресное пространство —\nс 24,2 до примерно 14,2 МиБ. RSS остался примерно 6,6–6,8 МиБ: сокращение\nзарезервированного адресного пространства не означает такую же экономию ОЗУ.\nПиковый расход при воспроизведении в этом сравнении не измерялся.\n\n## Сборка\n\nДоработки Login5 и Zeroconf, а также экспериментальный резервный путь PlayPlay\nнаходятся в [форке librespot](https:\u002F\u002Fgithub.com\u002Fklockky\u002Flibrespot\u002Ftree\u002Fdev).\nCargo загружает его по точному коммиту из `Cargo.toml`; `Cargo.lock` фиксирует\nзависимости. Все внутренние крейты librespot берутся из одной ревизии форка.\nОписание изменений и проверки: [SPOTIYA.md](https:\u002F\u002Fgithub.com\u002Fklockky\u002Flibrespot\u002Fblob\u002Febacab525375858be6932cbc6c9867d74c957f7a\u002FSPOTIYA.md).\n\n\nНа Linux с x86_64 нужны Rust\u002Frustup, Git, C-компилятор, make, pkg-config, curl, bzip2 и xz.\nДля локальных Rust-тестов нужны заголовки ALSA (`libasound2-dev` в Debian\u002FUbuntu).\n\n```sh\ncargo fmt --all -- --check\ncargo clippy --locked --all-targets -- -D warnings\ncargo test --locked\nmake -C controls\u002Fmini2 check\n\nscripts\u002Fbootstrap-arm.sh\nscripts\u002Fbuild-arm.sh\nscripts\u002Fpackage.sh\n```\n\nARM-сборка использует Linaro GCC 6.5 \u002F glibc 2.23 и ALSA 1.1.8.\n`scripts\u002Fbuild-arm.sh` проверяет, что бинарник не требует более новой glibc. Загрузки\nпроверяются по SHA-256; Rust и зависимости зафиксированы в `rust-toolchain.toml`\nи `Cargo.lock`. На колонке используются её системные `libasound.so.2` и glibc;\nALSA из сборочного sysroot в пакет не включается.\n\nПо умолчанию собирается ARMv7 hard-float с настройкой CPU Cortex-A53.\nПути можно переопределить через `SPOTIYA_CACHE`, `SPOTIYA_TOOLCHAIN`,\n`SPOTIYA_ALSA_SYSROOT`; CPU — через `SPOTIYA_TARGET_CPU`. Это не гарантирует\nсовместимость с другой моделью или Android\u002Fbionic.\n\nCI проверяет core\u002Faudio\u002Fdiscovery форка на закреплённой ревизии и выполняет Rust\nfmt\u002Fclippy\u002Ftests, C-тесты с ASan\u002FUBSan, ShellCheck, проверку Python launcher,\nARM-сборку и создание установочного архива.\n\n## Лицензия\n\n[MIT](LICENSE). Librespot распространяется под MIT; системная ALSA — под LGPL.\n\n\n## AirPlay 2\n\nНачиная с 0.9.0 Spotiya может управлять дополнительным приёмником AirPlay 2\nна основе Shairport Sync. Он использует системное имя колонки и объявляет модель\n`AudioAccessory5,1` для иконки HomePod mini в меню AirPlay. Набор возможностей\nAirPlay остаётся прежним. Иконка зависит от отправителя и его кеша. В TUI клавиша\n`a` открывает отдельный экран дополнений. Из терминала — `spotiya addons`.\nВ нём Enter скачивает отсутствующее дополнение из GitHub Releases. Для AirPlay\nустановка также включает службы; Enter у установленного AirPlay включает или\nвыключает их. PlayPlay работает по необходимости и не имеет отдельной службы.\nОтдельные команды — `spotiya airplay on` и\n`spotiya airplay off`. Настройка сохраняется после перезагрузки.\n\nAirPlay устанавливается отдельным пакетом `spotiya-airplay2-armv7.tar.gz`.\nЭкран показывает список дополнений, их состояние и ход загрузки. Стрелки или\n`j`\u002F`k` выбирают пункт, `Esc`\u002F`q` возвращают к плееру, `c` отменяет установку.\nМожно вернуться к плееру, пока идёт загрузка; выход из TUI отменяет её.\nУ установленного дополнения `u` скачивает пакет текущей версии заново и заменяет\nстарый, если он отличается. Новый PlayPlay подхватывается сразу; после обновления\nAirPlay перезапустите приёмник (`spotiya restart`). Двойное нажатие `x` удаляет дополнение; AirPlay сначала\nнужно выключить. Из терминала: `spotiya addon install ID` также обновляет,\n`spotiya addon remove ID` удаляет.\nКаталог дополнений задаётся в `src\u002Faddons.rs`, интерфейс работает со всем списком.\n\nПакет берётся из релиза **той же версии**, что запущенная Spotiya. Перед установкой\nпроверяются SHA-256 архива, манифест и отдельные бинарники. Установка не перезапускает\nSpotify и не копирует файлы AirPlay в основной бинарник. При выключенном AirPlay\nего четыре службы остановлены. Для прямой установки: `spotiya addon install airplay`.\nБез опубликованного релиза с AirPlay экран покажет причину и позволит повторить попытку.\n\nБазовый пакет Spotiya сохраняет прежний размер и работает без него. Внутри\nAirPlay-пакета находятся Shairport Sync, NQPTP, Avahi и приватный D-Bus;\nсистемный D-Bus и его настройки не меняются. Avahi не публикует обратные\nадресные записи, чтобы не конфликтовать со штатным mDNS станции. Все процессы запускаются и\nостанавливаются вместе с приёмником Spotiya. При сбое одного из них стек\nперезапускается с задержкой. Обновление основной Spotiya сохраняет AirPlay-пакет.\n\nСборка на Linux:\n\n```sh\nscripts\u002Fbootstrap-arm.sh\nscripts\u002Fbuild-airplay.sh\n```\n\nНужны инструменты сборки C\u002FC++, Python 3, CMake, Autoconf, Automake, Libtool,\ngettext, pkg-config, flex, bison, xxd, patch и host-программа `plistutil`.\nИсходники зависимостей закреплены в `airplay\u002Fsources.json` с SHA256;\nревизии Shairport Sync и NQPTP закреплены в `airplay\u002Ffetch.py`.\n\nСобранный пакет ставится той же командой, что и пакет из релиза; версия Spotiya\nна станции должна совпадать с версией пакета:\n\n```sh\nadb -s DEVICE push dist\u002Fspotiya-airplay2-armv7.tar.gz dist\u002FAIRPLAY_SHA256SUMS \u002Ftmp\u002F\nadb -s DEVICE shell spotiya addon file airplay \u002Ftmp\u002Fspotiya-airplay2-armv7.tar.gz \u002Ftmp\u002FAIRPLAY_SHA256SUMS\nadb -s DEVICE shell spotiya airplay on\n```\n\nВыберите системное имя станции в меню AirPlay на iPhone, iPad или Mac в той же\nлокальной сети. При начале AirPlay Spotify освобождает аудиовыход. При запуске\nSpotify AirPlay-сессия завершается, а приёмник снова становится доступен.\nГромкость AirPlay меняет общий уровень колонки. `release`\u002F`x` и пауза в TUI\nзавершают AirPlay-сессию; продолжение и смена трека управляются на отправителе.\nСпектр на дисплее пока обрабатывает только Spotify.\n\nЛог дополнительных служб: `\u002Ftmp\u002Fspotiya-airplay.log`. В `spotiya status` есть\nполя `airplay_available`, `airplay_enabled`, `airplay_running`, `airplay_active`\nи `airplay_error`. Отдельная ошибка AirPlay не останавливает Spotify Connect.\n\nОсновной пакет собран для ARMv7 hard-float с glibc 2.23 и системной ALSA;\nон подходит для первой Мини и Мини 2. Опциональные AirPlay-компоненты\nнеобходимо отдельно проверять на конкретной станции.\n\n## YouTube\n\nДополнение `youtube` принимает каст из приложений YouTube и YouTube Music (колонка\nвидна в меню трансляции под своим системным именем) и играет ссылки: их можно вставить в обычный поиск TUI (`\u002F`) или в отдельную строку\n`y`, из терминала — `spotiya youtube ССЫЛКА` или `spotiya play ССЫЛКА`. Ссылка\nYouTube в поиске никогда не уходит в Spotify. Понимаются\n`youtu.be\u002F…`, `watch?v=…`, `\u002Fshorts\u002F…` и голый идентификатор видео. Звучит только\nаудиодорожка.\n\nУстановка и включение — через экран дополнений или командами\n`spotiya addon install youtube` и `spotiya youtube on`\u002F`off`. Пакет\n`spotiya-youtube-armv7.tar.gz` занимает около 1,5 МБ; пока дополнение выключено,\nего процесс не запущен.\n\nАккаунт YouTube на колонке не нужен и не используется: выбирает видео телефон, а\nзвук колонка получает как анонимный мобильный веб-клиент, то есть так же, как\nразлогиненный браузер. Чтобы YouTube не обрывал поток на первой минуте, колонка сама\nполучает PO-токен: проверка BotGuard и расшифровка ссылок из плеера YouTube\nвыполняются во встроенном QuickJS. Подготовленный плеер кешируется в\n`receiver-state\u002Fyoutube\u002Fcache` и пересобирается только при смене его версии.\nВидео, для которых нужен вход (приватные, для участников, с возрастным\nограничением), так не воспроизводятся.\n\nКолонку YouTube делит со Spotify и Алисой так же, как AirPlay: с первым звуком\nтрека Spotify останавливается, а Алиса ставится на паузу; запуск Spotify, наоборот,\nостанавливает YouTube. Пауза, продолжение и смена трека работают с кнопок колонки,\nиз TUI (пробел, `n`, `p`) и голосом; громкость кнопками и с телефона меняет общий\nALSA Master. TUI показывает состояние `YOUTUBE` и название ролика, спектр работает в TUI и на дисплее так же, как для Spotify. Остановка всегда идёт через\nштатное закрытие ALSA: процесс, убитый посреди записи, может оставить общий\nмикшер dmix в состоянии, в котором замолкает вся колонка вместе с Алисой.\n\nТяжёлый JS-контекст плеера освобождается после обработки ссылки. На диске остаются\nподготовленный скрипт и скомпилированный байткод QuickJS: следующие треки загружают\nбайткод без повторного разбора JS. Кэш привязан к исходнику и сборке аддона;\nпри несовпадении или повреждении он пересоздаётся. На тестовом плеере кэш байткода\nзанимает около 9 МиБ на диске.\n\nВ локальном тесте обработчика на ПК после обработки оставалось 11–12 МиБ RSS.\nПик составлял около 33 МиБ при готовом кэше и около 43 МиБ при первой компиляции;\nобработка с готовым кэшем занимала примерно 0,12 секунды.\nЭто не замер полного аддона на станции: её расход ОЗУ ещё нужно проверить.\nПервый трек после запуска требует подготовки токена и плеера; следующие используют\nсохранённый скрипт и готовый минтер токенов.\n\nСборка на Linux:\n\n```sh\nscripts\u002Fbootstrap-arm.sh\nscripts\u002Fbuild-youtube.sh\n```\n\nКод DIAL, SSDP и Lounge адаптирован из [ytcast-open](https:\u002F\u002Fgithub.com\u002FmthwJsmith\u002Fytcast-open)\n(MIT). Уведомления ytcast-open, BgUtils, jsdom, quickjs-ng и libopus лежат в\n`youtube\u002Flicenses` и входят в пакет.\n","2026-10-31 04:26:27","CREATED_QUERY"]