Лента
Мои рекомендации Б
Лента
Мои рекомендации
Коллекция
?Залайканное A
Рекомендации по «»
Коллекция
?Залайканное Б
Рекомендации по «»
Music discovery
Рекомендации по группе
Похожие группы
0Music discovery
Рекомендации по группе Б
Похожие группы
0Новые релизы
Новое в Б
Конфигурация
Настройки
Справка
О программе
Персональный музыкальный помощник на Node.js + Express. Использует Playwright + Chromium для работы со стриминговыми сервисами и Gemini (через Kie.ai) для AI-задач.
Логин и антибот-защита
Приложение не использует официальные API сервисов A и Б напрямую. Вместо этого запускается постоянный браузер Chromium (Playwright) с сохранённым профилем (backend/.zvuk-profile). Пользователь логинится один раз через встроенный noVNC-браузер — куки и токены сохраняются в профиле и переиспользуются при каждом запросе.
Все обращения к сервисам идут через этот реальный браузерный контекст (withContext()), что делает трафик неотличимым от обычного пользователя. OAuth-токен Б кешируется на 50 минут и обновляется автоматически.
Как работают рекомендации
Из коллекции берётся случайная выборка треков (до 40 штук) — это «seed». Треки перемешиваются перед каждым запросом, поэтому последовательные батчи дают разнообразие даже из одной коллекции. Seed передаётся в Gemini с запросом предложить похожие треки, которых нет в коллекции. Модель возвращает список { artist, title }.
Каждый предложенный трек затем ищется на целевом сервисе (A или Б) через внутренний поиск — и только найденные треки с реальным ID попадают в финальный список. При нажатии «Загрузить ещё» уже показанные треки передаются в следующий запрос как exclude-список, чтобы модель не повторялась.
Коллекция на бэкенде кешируется на 5 минут — за это время каждый новый запрос делает новую случайную выборку из одного пула, без повторного обращения к сервису.
Отсечение нейрослопов
После загрузки коллекции Б все уникальные имена исполнителей прогоняются через двухэтапную фильтрацию.
Этап 1 — регулярные выражения: очевидные имена (Suno, Udio, Boomy, Mubert, Aiva и т.д.) отсеиваются мгновенно без обращения к AI.
Этап 2 — Gemini: оставшиеся имена батчами по 40 штук отправляются в модель с агрессивным промптом: «выяви AI-генерацию, ложные срабатывания допустимы». Все батчи выполняются параллельно (Promise.allSettled). Результаты объединяются и треки помеченных исполнителей переносятся в список «Нейрослопы».
Поиск трека и сопоставление с ID
Для A-треков нет прямого публичного поиска по названию — используется Google Programmable Search Engine (CSE), настроенный на домен сервиса A. Запрос вида «Artist — Track» отправляется в CSE прямо из браузера пользователя (без прокси через наш сервер). Google возвращает URL трека на A, из которого извлекается числовой trackId.
Используется не платный JSON API (который стоит денег после 100 запросов/сутки), а бесплатный JavaScript-виджет — тот же <script src="cse.google.com/cse.js?cx=...">, который вставляют на любые сайты. Виджет работает полностью в браузере пользователя: Google видит обычный поисковый запрос с реального IP и cookie браузера, никакого API-ключа нет, счётчик запросов не тикает. Найденные ID треков кешируются в localStorage, поэтому повторный поиск того же трека вообще не обращается к Google.
Для Б-треков поиск идёт напрямую через API сервиса: метод search вызывается из браузерного контекста Playwright (тот же авторизованный профиль), результат содержит готовый trackId и albumId.
Оверрайд нейрослопов
AI ошибается в обе стороны — иногда помечает живых музыкантов или пропускает реальную генерацию. Поэтому у каждого трека есть кнопки ручной коррекции: «Нейрослоп» переносит в AI-список, «Настоящий» — обратно в чистый.
Пометки хранятся в localStorage браузера в двух ключах: yandex_manual_ai и yandex_manual_clean. Они имеют приоритет над автоматической классификацией и применяются при каждой перерисовке списков. Для переноса на другой компьютер предусмотрены кнопки «Экспорт оверрайдов» / «Импорт оверрайдов» — сохраняют и загружают JSON-файл с обоими наборами.
Стриминг музыки
Браузер запрашивает аудио не напрямую у CDN сервиса, а через наш прокси /api/stream и /api/yandex/stream. Это нужно потому что CDN-ссылки требуют подписи и действуют ограниченное время.
Для A: через браузерный контекст Playwright запрашивается API стриминга с x-auth-token — возвращается подписанная CDN-ссылка высокого (или среднего) качества. Ссылка кешируется, повторные запросы идут из кеша.
Для Б: трёхшаговый процесс: ① /tracks/{id}/download-info → список форматов с downloadInfoUrl; ② GET этого URL возвращает XML с полями host, path, ts, s; ③ финальный MP3-URL подписывается через MD5-хеш (md5(SECRET + path + s)). Подписанная ссылка кешируется на несколько минут.
Полученный URL проксируется через Express с поддержкой заголовка Range — браузерный <audio> умеет перематывать без перекачки всего файла.
Проброс лайков
Для A: лайк ставится через GraphQL-мутацию addItemToCollection / removeItem на внутренний API сервиса. Запрос выполняется из браузерного контекста Playwright — с настоящим x-auth-token залогиненного пользователя. Ответ проверяется на GraphQL-ошибки.
Для Б: используется REST API: POST /users/{uid}/likes/tracks/add-multiple или .../remove с телом track-ids={trackId}:{albumId} в формате application/x-www-form-urlencoded. OAuth-токен и uid берутся из текущего браузерного сеанса Playwright. Изменение отражается в коллекции Б мгновенно.
В обоих случаях при нажатии ♡ состояние сразу фиксируется в localStorage (список Избранного), а API-запрос уходит асинхронно — UI не блокируется.
Новое в Б
Раздел показывает новые релизы на платформе Б от всех исполнителей из вашей коллекции. При открытии или нажатии «Загрузить новинки» система перебирает всех уникальных исполнителей коллекции, для каждого ищет artist ID через поиск Б, затем запрашивает список альбомов (/artists/{id}/direct-albums) и оставляет только вышедшие за выбранный период (30 / 90 / 180 / 365 дней). По умолчанию — последние 30 дней.
Релизы группируются по исполнителю или по дате (переключатель «По группе» / «По дате»). Для каждого альбома показывается обложка, кнопка «▶ Слушать» и ссылка открыть в Б. Если у альбома больше одного трека — кнопка «↕ Треки» раскрывает полный трек-лист с отдельными кнопками воспроизведения и лайка. У синглов (1 трек) ♡ стоит прямо на строке альбома.
Чекбокс «Исключить нейрослопы» фильтрует список без повторного запроса — используются те же данные классификации, что и в «Залайканное Б». В строке тулбара отображается итоговое количество релизов и треков. Результат кешируется в localStorage на 6 часов.
Настройки
API-ключ, URL и модель Kie.ai хранятся в backend/.env и редактируются в разделе . Изменения применяются немедленно (обновляется process.env) и записываются в файл для сохранения при перезапуске контейнера.
A/B тест