Тимур ТурдыевНаписать

кейс · 2026

Simple Record: запись звонков на Android без root и без облака

Написал своё приложение для записи звонков: пишет обе стороны разговора без root, честно говорит, когда запись не идёт, и расшифровывает разговоры прямо на телефоне. Ничего не уходит в облако. Открытый код, Apache-2.0.

KotlinJetpack ComposeAndroidscrcpy-serverADBsherpa-onnxGigaAMSQLite FTS4

Что было ​

Мне нужна запись звонков на своём телефоне. Телефон OnePlus 15R, звонилка по умолчанию Google Phone, и в российском регионе встроенной записи в ней нет. Звонилку OnePlus с записью поставить нельзя: её не пускает проверка целостности Google. Готовые приложения для записи звонков на современном Android либо пишут только свой голос через микрофон, либо требуют root, либо отправляют разговоры в облако для расшифровки.

Идею подсмотрел у открытого ShizuCallRecorder: звук звонка можно забрать через scrcpy-server с источником voice-call, если запустить его от имени системного пользователя shell. Механизм взял, код и архитектуру написал свои, с главным требованием: приложение не должно врать, что идёт запись, когда её нет.

Как устроено ​

Свой служебный процесс вместо root. Звук звонка Android отдаёт только системе и пользователю shell. Обычно до shell добираются через Shizuku, но на OxygenOS он не работает: его приложение не получает связь со своим же сервером. Поэтому в приложение встроен свой маленький ADB-клиент. Он один раз сопрягается с беспроводной отладкой телефона и запускает служебный процесс. Процесс живёт сам по себе: переживает перезапуски приложения, сам находит его, когда система поднимет его снова, и включает обратно беспроводную отладку в знакомых сетях, если Android её выключил при смене Wi-Fi.

Запись - машина состояний, а не флаг. Сессия записи проходит через явные состояния: ожидание, старт, запись, остановка, ошибка. Если захват оборвался посреди звонка, это переход в состояние, а не строчка в логе: запись продолжается в новую часть файла, и в списке части одного звонка показываются одной строкой и играют подряд. Если приложение упало, при следующем запуске недописанный файл восстанавливается и помечается как прерванный. Пустых файлов не остаётся. Уведомление показывает не "приложение работает", а реальное состояние записи.

Расшифровка на телефоне. Распознавание речи идёт прямо на телефоне, без сети: модель GigaAM v3 от Сбера с пунктуацией через движок sherpa-onnx. Перед выбором я прогнал восемь вариантов на своих реальных звонках и сверил результат с оригинальной реализацией GigaAM. Звук режется на куски по 15-22 секунды по паузам в речи, как это делает сам GigaAM, и под каждое слово сохраняется время. Касание слова включает запись с этого места. Минута разговора распознаётся примерно за 4 секунды на Snapdragon 8 Elite, звонок на 46 минут - за три минуты. Работа идёт в отдельном процессе: если распознавание упадёт или ему не хватит памяти, идущая запись звонка не пострадает. Новые звонки расшифровываются на зарядке, а если система прервёт работу, она продолжится с того же места.

Поиск по тому, что сказали. Тексты лежат в SQLite с полнотекстовым поиском, так что звонок можно найти по слову из разговора, а не только по имени и номеру. Плюс фильтры: период, месяцы с числом звонков, входящие и исходящие, с расшифровкой, прерванные.

Свой Мак как второе место для записей. Если дома стоит Мак с моим же приложением Simple Talk, телефон находит его в сети, сопрягается по шестизначному коду один раз и дальше сам отправляет записи после каждого звонка и при возвращении домой. Только по Wi-Fi и только на адреса домашней сети. Мак расшифровывает разговоры более крупными моделями, разделяет говорящих и присылает текст обратно на телефон.

Ничего не уходит в облако. Записи, тексты и номера не покидают телефон и домашнюю сеть. Единственный выход в интернет - скачивание файла модели распознавания (170 МБ) по кнопке, с проверкой каждого файла по контрольной сумме.

Что вышло ​

Пользуюсь каждый день. Приложение пишет обе стороны разговора чисто, начинает запись через полсекунды после начала звонка, переживает обрывы, падения и перезапуски, а запись звонка после окончания уже через секунду лежит на Маке.

Код открыт под Apache-2.0: github.com/TimurTurdyev/simple-record.

Вывод ​

Самым трудным оказалась не запись звука, а честность: на каждом шаге легко сделать вид, что всё работает. Поэтому статус записи показывает только то, что реально происходит, а каждый способ сломаться (обрыв, падение, перезапуск системой, звонок без Wi-Fi) я проверял на живых звонках, а не в тестах.

Скриншоты ​

Снято на эмуляторе на демо-данных: разговор озвучен синтезатором речи, номера вымышленные.

Список записанных звонков в Simple Record
Список звонков: статус записи, поиск по словам, фильтры, первая фраза разговора под звонком
Экран расшифровки звонка с подсветкой текущей фразы
Расшифровка на телефоне: касание слова включает запись с этого места, текущая фраза подсвечена
Статистика звонков за неделю
Статистика: число звонков, время разговоров, входящие и исходящие по дням
Выбор периода для списка звонков
Период: готовые варианты, месяцы с числом звонков, свои даты
Настройки расшифровки и отправки на Мак
Настройки: расшифровка на зарядке, отправка на Мак

Скачать ​

Что нужно:

  • Android 11 или новее. Проверено на OnePlus 15R (OxygenOS 16, Android 16); на других телефонах доступ к звуку звонка зависит от прошивки.
  • Один раз включить беспроводную отладку в настройках разработчика и ввести код сопряжения в уведомлении приложения.
  • После перезагрузки телефона - Wi-Fi, чтобы приложение снова запустило свой служебный процесс. Дальше запись работает и без Wi-Fi.
  • Для расшифровки - 230 МБ свободного места под модель.

Записывать разговоры можно не везде и не всегда без согласия собеседника: это зависит от закона вашей страны.

© 2014-2026 Тимур ТурдыевСайт и справочник работают на VPS от AdminVPS