Я хотел получить на Mac простую вещь: нажать глобальную горячую клавишу, надиктовать сообщение и сразу увидеть текст в активном окне. Без отправки аудио в облако, без ежемесячной подписки и с возможностью самому сравнить несколько моделей на собственной речи.
Так появился VoiceSwitch — открытое menu bar-приложение для Apple Silicon. Сейчас оно умеет переключаться между четырьмя движками распознавания, показывать состояние записи и расшифровки, автоматически вставлять результат и локально превращать устную речь в аккуратное или краткое сообщение.
Сразу честное предупреждение: это beta. Текущая сборка подписана ad-hoc и ещё не нотарифицирована Apple, поэтому первый запуск требует стандартного обхода Gatekeeper через «Открыть», а после обновления иногда приходится повторно включать разрешение «Универсальный доступ». Developer ID и нотарификация стоят в ближайшем плане.
Зачем ещё одна диктовка
Системная диктовка Apple удобна, пока ей подходит ваш голос и словарь. В моём случае русский текст распознавался нестабильно, особенно на длинных фразах, названиях продуктов и смешанной русско-английской речи. При этом хотелось не угадывать «лучшую модель вообще», а поставить несколько кандидатов рядом и проверять их одним и тем же интерфейсом.
В VoiceSwitch вошли:
-
GigaAM v3 E2E RNNT — основной кандидат для русского языка;
-
Whisper Large V3 Turbo через MLX — для смешанной русско-английской речи;
-
Qwen3-ASR 1.7B через MLX — экспериментальный многоязычный режим;
-
Apple SpeechAnalyzer — системный локальный вариант на macOS 26+;
-
Qwen3-4B MLX 4-bit — не распознаёт звук, а редактирует готовую расшифровку.
Главное обещание проекта:
Нажмите одну клавишу, скажите мысль и получите готовое сообщение — русская речь распознаётся и редактируется прямо на Mac, без облачных API.
Демонстрация со звуком: fn + Option запускает запись, GigaAM распознаёт русскую фразу, Qwen3-4B сокращает её, после чего результат автоматически вставляется в исходное поле.
Как выглядит поток данных
Пользователь нажимает fn + Option, VoiceSwitch запоминает активное приложение и начинает запись. Повторное нажатие завершает запись и запускает выбранный движок.
fn + Option │ ▼AVAudioRecorder → временный WAV │ ├── GigaAM ├── Whisper MLX ├── Qwen3-ASR MLX └── Apple SpeechAnalyzer │ ▼ исходная расшифровка │ ├── Дословно ├── Исправить → Qwen3-4B └── Кратко → Qwen3-4B │ ▼ буфер обмена + вставка
Swift-приложение отвечает за интерфейс, глобальную клавишу, микрофон, HUD и вставку. Python-worker живёт отдельным процессом и общается со Swift через JSON Lines. Это позволило не загружать тяжёлую модель на каждый запрос: worker остаётся запущенным и меняет ASR-движок только при переключении.
Для MLX-моделей используется единый локальный runtime в Application Support. Установщик закрепляет версии Python-зависимостей, загружает ffmpeg и веса моделей. Системный Python и shell-профиль пользователя не изменяются.
Почему GigaAM стал основным
Я проверил четыре движка на восьми одинаковых фрагментах общей продолжительностью 209,5 секунды:
-
четыре рассказа и диалога;
-
научная радиозаставка;
-
русский рок;
-
смешанный русско-английский вокал;
-
быстрый русский речитатив.
Каждый WAV был один раз записан через динамики и встроенный микрофон MacBook, а затем без изменений передан всем моделям. Это не академический benchmark: для эфиров и музыки не было проверенного эталона, поэтому WER не вычислялся. Я оценивал полноту, сохранение смысла, очевидные подмены, язык и задержку.
|
Модель |
Средняя задержка |
RTF |
Наблюдение |
|---|---|---|---|
|
Apple SpeechAnalyzer |
0,42 с |
0,017 |
Очень быстро, но сильно обрезает сложный звук |
|
GigaAM v3 E2E RNNT |
0,77 с |
0,030 |
Лучший общий баланс для русского |
|
Whisper Large V3 Turbo |
2,52 с |
0,096 |
Практичный запасной режим для смешанной речи |
|
Qwen3-ASR 1.7B |
19,00 с |
0,715 |
Иногда точен, но слишком медленный и меняет язык |
Высокая скорость Apple в этой таблице обманчива: на всех речевых примерах движок вернул только 25 слов, а на четырёх музыкальных — пустую строку.
GigaAM дал наиболее стабильный русский текст, не обрывал длинные фрагменты и лучше остальных перенёс речитатив. Whisper оказался логичным запасным вариантом для настоящей смеси русского и английского. Qwen3-ASR иногда распознавал отдельные фразы лучше конкурентов и заметил английскую часть смешанного трека, но максимальная задержка дошла до 36,24 секунды. Кроме того, на русской музыке он периодически определял язык как English и начинал переписывать содержание по-английски.
Практическая конфигурация после теста:
-
GigaAM — по умолчанию для русской диктовки.
-
Whisper — для смешанной русско-английской речи.
-
Qwen3-ASR — экспериментальный режим.
-
Apple SpeechAnalyzer — быстрый системный ориентир для сравнения.
Полный воспроизводимый отчёт и числовая сводка лежат в репозитории. Исходные музыкальные файлы и полные тексты намеренно не публикуются.
Почему одной расшифровки оказалось мало
Голосовое сообщение почти всегда содержит ложные старты, «э-э», повторы и смену формулировки посреди предложения. ASR может правильно записать каждое слово, но результат всё равно приходится редактировать руками.
Поэтому в приложении появились три режима:
-
Дословно — вставить результат ASR без изменений;
-
Исправить — убрать слова-паразиты, повторы и ошибки пунктуации, сохранив содержательные детали;
-
Кратко — превратить речь в компактное естественное сообщение.
Для последних двух режимов используется Qwen/Qwen3-4B-MLX-4bit. Модель работает локально, без ChatGPT, Claude и других облачных API. В системной инструкции запрещено добавлять факты, приветствия и выводы, которых не было в исходнике. Отдельная проверка отбрасывает подозрительно короткий результат в режиме исправления. При любой ошибке VoiceSwitch вставляет исходную расшифровку, поэтому пользователь не теряет текст.
На двух реальных русских сообщениях локальная редактура заняла 4,2–4,8 секунды. Это заметная пауза, поэтому HUD показывает отдельное фиолетовое состояние «Редактирую текст», а не оставляет пользователя гадать, зависло ли приложение.
Автоматическая вставка и ловушка TCC
VoiceSwitch запоминает PID приложения, которое было активно до начала записи. После обработки текст всегда попадает в буфер обмена, затем приложение возвращает фокус целевому окну и отправляет вставку.
Для этого macOS требует разрешение:
Системные настройки →Конфиденциальность и безопасность →Универсальный доступ
Самая неприятная ошибка проявилась после очередной пересборки: распознавание работало, текст находился в буфере, но автоматическая вставка исчезла. Код вставки не менялся. Причиной оказалась ad-hoc подпись: после сборки изменился CDHash, и TCC продолжал хранить разрешение для предыдущей идентичности приложения.
Временное решение:
tccutil reset Accessibility io.github.mitimaicode.VoiceSwitch
После этого нужно заново добавить текущий VoiceSwitch.app в Accessibility. Нормальное решение — постоянный сертификат Developer ID, Hardened Runtime и нотарификация. Тогда обновления с тем же Bundle ID и командой разработчика имеют стабильную designated requirement.
Пошаговый план с командами codesign, notarytool, stapler и проверками Gatekeeper вынесен в отдельную инструкцию.
Что хранится на Mac
Во внешние API ничего не отправляется. Локально остаются:
-
runtime и веса моделей;
-
выбранные настройки;
-
журнал сравнения: движок, длительность, задержка, язык, исходный и отредактированный текст, оценка результата.
Временный WAV удаляется после обработки. Журнал нужен, чтобы сравнивать модели именно на собственной речи, но его можно удалить вместе с данными приложения.
Цена полной автономности — место на диске. Первая установка всех движков и текстовой модели требует около 12 ГБ. В будущей версии логично сделать выборочную установку: например, только GigaAM и редактор, а Whisper и Qwen-ASR загружать по запросу.
Что оказалось сложнее моделей
Основные проблемы проекта были не в вызове transcribe():
-
Удержать глобальную клавишу простой и не конфликтующей с системой.
-
Не потерять окно, в которое пользователь диктовал.
-
Показать различимые состояния записи, распознавания и редактуры.
-
Корректно выгружать MLX-модели и не занимать лишнюю память.
-
Сделать установщик воспроизводимым и не ломать системный Python.
-
Разобраться, почему разрешение Accessibility исчезает после обновления.
-
Честно объяснить пользователю, зачем приложению чувствительное разрешение.
Локальная ML-модель может быть хорошей, но продукт начинает работать только тогда, когда пользователь понимает: идёт запись, нужно подождать или произошла ошибка.
Ограничения текущей beta
-
только Apple Silicon и macOS 14 или новее;
-
Apple SpeechAnalyzer доступен на macOS 26+;
-
сборка пока ad-hoc и не нотарифицирована;
-
первая установка моделей занимает около 12 ГБ;
-
Qwen3-ASR может обрабатывать фрагмент дольше его длительности;
-
точность сильно зависит от микрофона, темпа и личного словаря;
-
для окончательного выбора движка нужен персональный тест на заранее подготовленных фразах с эталонным текстом.
Нужны тестировщики
Я ищу владельцев Mac с M1 или новее, готовых потратить около 15 минут и проверить три сценария:
-
короткое русское сообщение;
-
длинное сообщение со словами-паразитами;
-
смешанная русско-английская фраза.
Особенно интересны сравнение GigaAM и Whisper, скорость режима «Кратко» и работа автоматической вставки в Telegram, браузере и редакторах кода.
Проект открыт под лицензией MIT. Буду рад результатам тестов, сообщениям об ошибках и предложениям по более удобной локальной диктовке.
ссылка на оригинал статьи https://habr.com/ru/articles/1064046/