VEIN Music — независимая платформа для любителей музыки. Она собирает прослушивания из приложения и сайта Яндекс Музыки, браузера, десктопных плееров и облачных сервисов, строит статистику и рекомендации, превращает прослушивание в игру с уровнями и достижениями и даёт разработчикам открытый API.
Проект на бета-тестировании. Сайт работает, но возможны ошибки и изменения. Если заметили ошибку, пожалуйтесь на неё через профиль или комментарий: жалобы попадают в админку.
⚡ Ключевые возможности
🎧 1. Сбор прослушиваний из любых источников
Яндекс Музыка без расширения: после подключения аккаунта сервер держит живое соединение с плеером Яндекса (Ynison) и видит, что играет в мобильном приложении, десктопном приложении и на сайте music.yandex.ru.
Время засчитывается только по событиям плеера (пауза, перемотка, переключение), поэтому закрытая вкладка или выгруженное приложение не засчитывают недослушанный трек.
Если соединение недоступно, работает запасной опрос раз в 30 секунд.
Браузерное расширение (Chrome, Edge, Яндекс Браузер и Firefox 142+, Manifest V3):
Считывает трек и прогресс воспроизведения на вкладках Яндекс Музыки, Spotify, VK Музыки, YouTube Music, Apple Music, SoundCloud и Звука.
Офлайн-очередь: если сервер недоступен, прослушивания сохраняются в хранилище расширения (до 500 штук) и досылаются раз в минуту через chrome.alarms.
Подключение по коду: расширение показывает короткий код, пользователь подтверждает его на странице /link, и расширение получает собственный ключ. Ключ можно отозвать в настройках.
Приложение для Windows (desktop/, Tauri 2):
Сайт VEINMusic в отдельном окне и значок в трее; запускается вместе с Windows и работает в фоне.
Скробблит всё, что видно в системной панели медиа Windows: Spotify (без платного API), приложение Яндекс Музыки, AIMP, foobar2000, VLC, Apple Music, вкладки браузеров. Источники включаются по отдельности.
Подключение аккаунта по коду, как у расширения; ключ хранится в диспетчере учётных данных Windows.
Проверка обновлений через релизы GitHub, статус в Discord. Установщик собирает GitHub Actions (подробнее).
Консольный клиент (desktop_client/, Python) — для Linux:
Linux: любые плееры с поддержкой MPRIS (через playerctl); на Windows — SMTC и заголовки окон.
Discord Rich Presence с обложкой, названием трека, артистом и таймером.
Локальная очередь ~/.veinmusic/queue.json, которая досылается при восстановлении сети.
Облачный скробблинг Spotify: фоновый опрос того, что играет в Spotify, без открытых вкладок и плееров. Работает как задача воркера с распределённой блокировкой, поэтому опрос не дублируется при нескольких экземплярах сервера.
Облачный скробблинг SoundCloud: OAuth 2.1 с PKCE и официальный список недавно прослушанных треков позволяют фиксировать новые прослушивания без браузерного расширения. Первая синхронизация служит безопасной точкой отсчёта и не импортирует старую историю.
Экспорт во внешние сервисы: каждое засчитанное прослушивание можно автоматически отправлять в Last.fm, ListenBrainz и Libre.fm (настраивается через API: /api/developer/export/config).
Импорт истории из Last.fm: постраничный импорт в фоне с прогресс-баром. После сбоя импорт продолжается с той же страницы, а повторный запуск забирает только новые прослушивания.
🛡️ 2. Обработка прослушиваний и защита от накруток
Нормализация метаданных: из названий убираются пометки вроде Remastered, Live at …, Radio Edit, Deluxe Edition, Explicit, а feat. переносится к артисту.
Засчитывание прослушиваний: трек засчитывается и приносит XP, только если прослушано не меньше 85% его длительности. Повторные сигналы о том же треке обновляют одно прослушивание, а не создают дубли.
Ограничение частоты запросов на скробблинг, вход и регистрацию. Счётчики общие для всех процессов (хранятся в Redis).
Антифрод: система отмечает подозрительных пользователей по аномальному числу прослушиваний в час и в сутки и по потоку очень коротких треков. Администратор может сбросить им XP или снять отметку.
Чёрный список: блокировка треков и артистов по ключевому слову, точному имени артиста или регулярному выражению.
📊 3. Статистика и рекомендации
Графики на Recharts: активность по часам и дням недели, динамика прослушиваний; периоды — неделя, месяц, 90 дней, текущий год, всё время или произвольный диапазон дат.
Топы артистов, треков и альбомов, любимые жанры.
Музыкальный календарь: активность по каждому дню года, серии прослушиваний и подробности выбранного дня.
VEIN Wrapped для любого периода: сравнение с предыдущим периодом, новые артисты, самый активный день и вертикальная карточка для публикации. В профиле также доступны OG-карточки итогов недели или месяца для соцсетей.
Рекомендации: треки из любимых жанров, новинки знакомых артистов и то, что популярно в сообществе (/api/recommendations/me), а в профиле — артисты, которых слушают ваши «музыкальные двойники».
Музыкальная совместимость: процент совпадения вкусов с другим пользователем, общие артисты, подбор «музыкальных двойников» и поиск людей со схожим вкусом.
Настроение: определение текущего музыкального настроения по последним трекам.
🏆 4. Геймификация, профиль и социальные функции
Уровни и ранги: XP за каждое засчитанное прослушивание (x2 за любимые треки), ранги от Туриста до Божества, ежедневные серии прослушиваний. Администратор может включить множитель XP.
Рамки аватара, которые открываются по уровню (Меломан, Аудиофил, Маньяк, Легенда, Божество), плюс рамки, созданные администратором.
Достижения, которые администратор настраивает правилами: число прослушиваний, ночные прослушивания, конкретный трек, альбом или артист. О новых достижениях приходит уведомление на сайте и Web Push.
Оформление профиля: аватар и обложка с обрезкой при загрузке, страна, ссылки на Telegram, GitHub и Instagram, свой акцентный цвет сайта.
Витрина профиля: любимые артист, трек и альбом с обложками и фото исполнителя (поиск по Deezer и Яндекс Музыке, русские названия сохраняются). Менять их можно раз в 30 дней.
Подписки и лента: подписчики и подписки, лента друзей и глобальная лента с лайками и комментариями, фильтр ленты по источнику (Яндекс, Spotify, десктоп, расширение).
Лидерборд слушателей по XP.
Приватный профиль: история и статистика скрыты от посторонних.
Жалобы: на профиль или комментарий можно пожаловаться, указав причину; жалоба уходит модераторам.
🛠️ 5. Виджеты, PWA и платформа для разработчиков
SVG-виджеты для README на GitHub и сайтов:
Now Playing — что играет сейчас, с анимированным эквалайзером (/api/widgets/now-playing/{username}.svg);
Top Artists — топ-5 артистов (/api/widgets/top-artists/{username}.svg).
OG-карточки 1200×630 для соцсетей: итоги недели или месяца (/api/widgets/og/recap/{username}.svg) и полученные достижения (/api/widgets/og/achievement/{username}/{id}.svg).
PWA: сайт можно установить на телефон или компьютер (Service Worker и manifest.json).
Web Push: уведомления о новых достижениях (стандарт RFC 8291, ключи VAPID). Включаются во вкладке «Безопасность и данные».
API для разработчиков:
Личные ключи (vm_...) с правами (scopes), хранятся в виде хэша PBKDF2-HMAC-SHA256.
Вебхуки на события scrobble.created и achievement.unlocked с подписью X-VEIN-Signature (HMAC-SHA256).
Справочник по API на странице /developers.
Умная ссылка/api/redirect: открывает найденный трек в Яндекс Музыке.
Объявления и флаги функций: баннер объявлений на сайте и включение функций без перевыпуска.
Окно «Идёт обновление»: пока сервер обновляется после нового коммита, сайт показывает окно «Пожалуйста, подождите» вместо ошибки и сам перезагружает страницу, когда новая версия готова.
🔐 6. Безопасность и данные аккаунта
Сессии: выход со всех устройств одной кнопкой; забаненный пользователь сразу теряет доступ во всех сессиях.
Защита входа: пароль от 8 символов, блокировка на 15 минут после 10 неудачных попыток.
Шифрование: OAuth-токены, сессионные ключи и секреты вебхуков хранятся в базе в зашифрованном виде.
Заголовки безопасности: CSP, запрет встраивания во фреймы, nosniff, HSTS в продакшене.
Защита от SSRF: вебхуки и push отправляются только на публичные адреса, с проверкой IP на момент отправки.
Мои данные: выгрузка профиля, истории, подписок, комментариев и достижений в JSON и удаление аккаунта с подтверждением паролем.
🛡️ 7. Панель администратора (/admin)
Обзор: графики регистраций, засчитанных прослушиваний и активных слушателей за 7/30/90 дней, метрики, множитель XP, сброс кэша.
Пользователи: список и карточка пользователя — статистика, интеграции и экспорт, API-ключи (с отзывом), вебхуки, последние прослушивания, достижения и импорты; бан, роль, верификация, уровень, сброс профиля, завершение всех сессий, удаление истории или аккаунта, выдача и снятие достижений.
Жалобы: жалобы на профили и комментарии с фильтрами, удаление комментария, «Меры приняты» или «Отклонить» с заметкой.
Модерация: последние комментарии с поиском по тексту и автору, удаление.
Прослушивания: поиск по пользователю, треку, источнику и периоду; исправление трека, удаление одной записи или массовое удаление у пользователя с предварительным подсчётом.
Интеграции: подключённые Яндекс, Spotify, SoundCloud и Last.fm, живое состояние соединений с Яндексом, переподключение и отключение; обновление витрины пользователя.
Антифрод: список подозрительных пользователей, сброс XP, снятие отметки.
Каталог: поиск по всем трекам с числом прослушиваний, редактирование и удаление треков, слияние дубликатов и исполнителей, чёрный список.
Геймификация: создание, редактирование и удаление достижений и их правил, рамки аватара.
Оповещения: объявления, флаги функций (регистрация, импорт Last.fm, вебхуки) и рассылка — уведомление на сайте и/или Web Push всем или выбранным пользователям.
Система: воркер и очередь задач, последние запуски cron, бэкапы БД, размер загрузок и базы и задачи импорта Last.fm с перезапуском.
Логи: ошибки и предупреждения API и воркера с трассировками и фильтрами; ключи и токены в них скрываются.
Журнал: все действия администраторов с фильтрами по действию, администратору и объекту.
Аватары и обложки профиля при загрузке уменьшаются (аватар до 512 px,
обложка до 2000 px по длинной стороне), разворачиваются по EXIF и теряют
метаданные камеры и GPS. Файлы, загруженные раньше, один раз ужимаются на
месте (имена и ссылки не меняются; --dry-run только покажет экономию):
git clone https://github.com/Peaostrel/VEINMusic.git
cd VEINMusic
2. Настройка окружения
cp .env.example .env
# Обязательно задайте SECRET_KEY, POSTGRES_PASSWORD и REDIS_PASSWORD
Для облачного SoundCloud-скробблинга зарегистрируйте приложение в SoundCloud
и задайте SOUNDCLOUD_CLIENT_ID, SOUNDCLOUD_CLIENT_SECRET и точный callback
SOUNDCLOUD_REDIRECT_URI (для продакшена —
https://api.music.vein.guru/auth/soundcloud/callback).
Для входа и привязки через VK ID создайте веб-приложение в кабинете
id.vk.ru, укажите доверенный redirect
URL https://api.music.vein.guru/auth/vk/callback и задайте VK_CLIENT_ID
(ID приложения). Защищённый ключ не нужен: вход идёт по OAuth 2.1 с PKCE.
Пока VK_CLIENT_ID пуст, кнопки VK ID на сайте не показываются.
3. Запуск всего стека в Docker (продакшен)
docker compose up -d --build
Поднимаются PostgreSQL, Redis, API (миграции применяются автоматически при старте),
фоновый воркер arq (достижения, вебхуки, экспорт скробблов, импорт Last.fm,
живое соединение с Яндексом, опрос Spotify и SoundCloud, ночная очистка неиспользуемых
загрузок) и фронтенд.
Проверка состояния: GET /health.
Для VPS с 1–2 ГБ памяти удобнее deploy/: образы
собирает GitHub Actions, сервер только скачивает их, а Caddy сам выпускает
HTTPS-сертификаты. Сервер сам подтягивает новые коммиты, а на время
перезапуска Caddy показывает страницу «Идёт обновление».
Резервные копии. Сервис db-backup раз в сутки делает pg_dump в том
db_backups и хранит копии BACKUP_KEEP_DAYS дней (по умолчанию 7).
Восстановление:
Копии лежат на том же сервере: для защиты от потери диска периодически
забирайте их на другое хранилище.
3а. Локальная разработка без Docker для кода
Для работы по обычному http поставьте в .env значение ENVIRONMENT=development
(в продакшене должно оставаться production).
# Только базы данных
docker compose up -d db redis
pip install -r requirements.txt
python -m app.core.migrate # миграции (подхватывает и старые базы без истории Alembic)
uvicorn app.main:app --reload --port 8000
arq app.worker.WorkerSettings # фоновый воркер (в отдельном терминале)
Web Push включается ключами VAPID: python -m app.services.push_notifications
выведет пару ключей для .env.
4. Настройка и запуск фронтенда
cd frontend
npm install
npm run dev
Фронтенд будет доступен по адресу: http://localhost:3000.
5. Приложение для Windows (Опционально)
Установщик публикуется в релизах с тегом desktop-v*;
сборка из исходников описана в desktop/README.md.
5а. Консольный клиент на Python (Опционально)
cd desktop_client
pip install -r requirements.txt
python -m desktop_client.main
В Chrome, Edge, Brave и Яндекс Браузере распакуйте пакет chromium, откройте
страницу расширений, включите режим разработчика и загрузите распакованную папку.
В Firefox 142+ пакет firefox пока устанавливается временно через about:debugging;
для постоянной установки требуется подпись Mozilla или публикация на AMO.
В окне расширения включите «Передавать прослушивания в VEIN», нажмите
«Подключить через сайт» и подтвердите код. Ключ устройства можно отозвать в
настройках VEIN. «Тест связи» проверяет доступ, не добавляя треков в историю.
Для разработчиков: python scripts/package_extension.py собирает два пакета,
node --test music-extension/tests/*.test.cjs запускает тесты.
🧪 Тестирование и проверка качества
# Юнит- и интеграционные тесты бэкенда (SQLite)
pytest
# Те же тесты на PostgreSQL и с реальным Redis (как в CI)
TEST_DATABASE_URL=postgresql://USER:PASSWORD@localhost:5432/veinmusic_test \
TEST_REDIS_URL=redis://localhost:6379 pytest
# Проверка, что миграции совпадают с моделями
alembic check
# Проверка типизации и линтинга бэкенда
flake8 app tests desktop_client
mypy app/
# Проверка линтера и форматирования фронтенда
cd frontend
npm run lint
npm run format:check
npm run build
📄 Лицензия
Проект распространяется под условиями собственной лицензии. Подробнее см. в файле LICENSE.