YaBooks Sync
Неофициальное приложение для Garmin Connect IQ: скачивает главы аудиокниг Яндекс Книг на часы по Wi-Fi и играет их офлайн, без телефона. Часы продолжают с того места, где остановился телефон, а прослушанное на часах уходит обратно в Яндекс Книги.
- Роль
- Полный цикл
- Стек
- Monkey C · FastAPI · ffmpeg
- Срок
- 3 дня до беты
- Год
- 2026

Задача
Аудиокниги слушают на пробежке и в дороге, где телефон брать не хочется, а часы Garmin умеют играть звук сами. Клиента Яндекс Книг для Connect IQ нет. Отдельная сложность — позиция: начал главу на телефоне, продолжил на часах, вернулся к телефону — и везде должно быть одно и то же место.
Решение
Часы скачивают главы по Wi-Fi с запасом на несколько часов вперёд — от 1 до 12, по умолчанию 3 — и играют без телефона. Позиция синхронизируется в обе стороны с точностью до секунды, дослушанные главы удаляются сами.
Вход по коду через OAuth Device Flow — пароль на часах не вводится; перемотка на 30 секунд вперёд и на 15 назад, качество 64 или 192 кбит/с. Это второе приложение линейки после YaMusic Sync: общий каркас и знак того же жёлтого цвета.
Как шла работа
Сделал всё сам: разобрал закрытый API, написал приложение на Monkey C и прокси на FastAPI, подготовил графику и тексты для стора. От первого коммита до рабочей беты 0.1.6 — около 3 дней и 6 бета-сборок; перед первым запуском код прошёл состязательное ревью, 11 дефектов исправлено.
Подводные камни
Ответ на часах не больше примерно 21 КБ, а оглавление «Войны и мира» — 475 КБ на 321 главу: прокси сжимает его до 7,8 КБ. CMAF в симуляторе принимался, а на реальных часах не играл: сервер перепаковывает главы через ffmpeg, и книга на 13 часов худеет с 378 до 201 МБ. REST-запись позиции отвечала 200, но ничего не меняла — позицию двигает только GraphQL-мутация.
На чём сделано
На часах — Monkey C и Connect IQ SDK 9: Toybox.Media, SyncDelegate, вход по OAuth 2.0 Device Flow. Сервис — Python 3.12 и FastAPI с httpx: ходит в REST API Яндекс Книг, пишет прогресс GraphQL-мутацией, перепаковывает CMAF в MP4 (моно, 32 кбит/с) через ffmpeg и держит LRU-кэш до 2 ГБ. На сервере Docker, nginx и Let's Encrypt; 117 тестов на pytest.





