← Мои проекты

Собственный продукт · Windows

UntypeПишите голосом.
В нужном окне.

Голосовой ввод и ИИ-помощник для Windows. Нажали Ctrl + Space, сказали, и текст появился там, где стоит курсор. Продукт я придумал и сделал целиком: от перехвата клавиш до оплаты и сайта.

Моя роль
Автор и разработчик продукта
Основа
.NET 10, WinUI 3, ASP.NET Core
Сайт
untype.ru

Александрарабочий чат

Когда обсудим новую идею?

Вы говорите, Untype слушает. Текст вставляется разом, после распознавания.

Ctrl + Space начать диктовку

Плашка внизу экрана повторяет настоящую. Нажмите Ctrl + Space или кликните по ней, и она «продиктует» пример в ближайшее поле. Микрофон не включается, буфер обмена страница не трогает.

Мысль готова за секунду. Набор отнимает минуты.

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

  • 01

    Голосовые сообщения никто не любит слушать.

  • 02

    Вежливый ответ начальнику занимает полчаса.

  • 03

    Запрос к ИИ проще рассказать, чем набрать.

Презентация продукта, 74 секунды. Как она собрана, рассказываю ниже.

Одна клавиша, два способа говорить.

По умолчанию Ctrl + Space работает как переключатель: первое нажатие начинает запись, второе её останавливает. Если держать клавиши дольше 0,6 секунды, они становятся рацией: отпустили, и запись ушла на распознавание. В режиме удержания касание короче 0,2 секунды возвращается в приложение, поэтому подсказки редактора кода продолжают работать.

Нажмите Ctrl + Space на клавиатуре или подержите кнопку. Страница измерит нажатие так же, как Untype.

Нажмите и отпустите, чтобы увидеть, как поступит Untype.

  • Свой низкоуровневый хук.RegisterHotKey не сообщает об отпускании клавиш, поэтому удержание на нём не сделать. Хук WH_KEYBOARD_LL видит и нажатие, и отпускание.
  • Хук в отдельном потоке.Windows молча снимает хук, который отвечает слишком долго. Поэтому у него свой цикл сообщений, а раз в пять минут он переустанавливается.
  • Пробел не утекает в текст.Space проглатывается, Ctrl уходит в приложение. Короткое касание Untype повторяет через SendInput со своей меткой, чтобы не принять его за новое нажатие.

Звук уходит на сервер, пока вы говорите.

Микрофон открывается только на время диктовки. Звук сводится в моно, приводится к 16 кГц и режется на кусочки по 100 мс. Они сразу уходят по WebSocket, поэтому к моменту, когда вы отпустили клавишу, запись уже на сервере.

  1. МикрофонWASAPI в общем режиме, обычно 48 кГц стерео
  2. 16 кГц, моноPCM, кусочки по 100 мс, 3 200 байт
  3. WebSocketstart, кадры звука, end
  4. Серверready, затем итоговый текст

Если связь подвела. Звук параллельно копится в памяти. Не открылся сокет или упал посреди речи: после записи то же аудио уходит одним запросом.

Настоящая плашка Untype в двух состояниях: «Слушаю вашу мысль…» с полосками уровня и «Превращаю голос в текст…»
Настоящая плашка: запись и распознавание. Это не XAML, а layered-окно Win32: оно рисуется через GDI+ и не забирает фокус у приложения, в которое вы диктуете.
  • Полоски слушают вас.Уровень звука из RMS переводится в децибелы, а дальше те же правила, что у плашки внизу этой страницы: девять полосок, быстрый подъём, медленный спад.
  • Две минуты на запись.Тонкая полоска внизу плашки отсчитывает время и после 85% становится терракотовой.
  • Отмена в любой момент.Esc, крестик на плашке или голосом. Отмена во время распознавания ничего не вставит.

Модель расставляет знаки, Untype наводит порядок.

Пунктуацию даёт модель распознавания. Дальше на компьютере работает предсказуемая обработка: убирает служебные метки вроде [музыка], отбрасывает известные галлюцинации whisper вроде «Субтитры сделал DimaTorzok», ставит кавычки-ёлочки и заглавную букву. Смысл не меняется.

Вы говорите

«Помоги составить план запуска сайта. У нас два человека и три недели. Сначала задай вопросы, чтобы уточнить задачу»

  • «антайп»Untype
  • «мой емейл»hello@example.com
  • «спасибо за помощь смайлик»Спасибо за помощь 😊

Нажмите Ctrl + Space или кликните по плашке внизу: текст появится в этом поле.

  • Словарь работает дважды.Термины уходят модели подсказкой, до 700 символов, а после распознавания срабатывают точные замены. Заменённые фразы прячутся за символами из личной области Unicode, чтобы эмодзи и заглавные буквы их не задели.
  • Двадцать эмодзи голосом.Около 190 формулировок собраны в одно регулярное выражение с ограничением по времени. Слово «смайлик» не сработает внутри «смайлик с моноклем».
  • Шлюз выбирает модель.Сервер вызывает основного провайдера и умеет переключаться на запасного при временной ошибке. Обрывы связи с OpenAI раньше срывали диктовки, теперь шлюз повторяет запрос через 250 мс и не списывает минуты дважды.

Текст появляется там, где стоял курсор.

Окно запоминается в момент нажатия. Пока вы говорите, можно переключиться куда угодно: Untype вернёт фокус и вставит текст туда, откуда начали. Сначала текст надёжно кладётся в буфер обмена, потом нажимается Ctrl + V.

Обычное окно

Чат, документ, запрос к ChatGPT. Окно активируется, текст вставляется разом.

Готово

Старт из трея или Пуска

Если при нажатии активна панель задач, текст уйдёт в последнее настоящее окно: его помнит системный хук.

Готово

Окно администратора или рабочий стол

Вставлять в случайно активное окно нельзя. Текст остаётся в буфере, и плашка честно об этом говорит.

В буфере обмена

Буфер занят другой программой

Untype пробует открыть буфер 40 раз через 25 мс. Не вышло: вставка не начинается, текст сохраняется в истории.

Не удалось скопировать текст

  • Каждая диктовка на виду.Главный экран показывает, за сколько миллисекунд текст распознан и вставлен. Метрики считаются от нажатия до записи и от отпускания клавиши до вставки.
  • Запасной способ вставки.Если Ctrl + V не сработал, текст набирается через Unicode-ввод пачками по 512 событий.
  • Без «специальной вставки».Перед Ctrl + V зажатые Shift и Alt отпускаются, иначе редактор открыл бы другое меню.

Текст уже есть? Скажите, что изменить.

Выделите фрагмент в любом приложении и нажмите Ctrl + Shift + Space или просто скажите «Джарвис, сократи до главного». Ответ появляется в отдельном окне и сразу лежит в буфере обмена: проверьте и вставьте сами.

Коллеги, добрый день!

Привет! По запуску сайта: макеты уже согласованы. Разработку заканчиваем в пятницу. Давайте встретимся в понедельник в 11:00, чтобы всё проверить и решить, когда запускаемся.

Спасибо!

Ctrl + Shift + Space или по имени, если включено в настройках

Помощник

Текст. По-вашему.

Переведите, сократите или найдите точные слова.

Что сделать с текстом?

«Джарвис, сократи до главного»

Готовый текст

Макеты согласованы, разработку закончим в пятницу. В понедельник в 11:00 проверим сайт и выберем дату запуска.

Готовые ответы с сайта untype.ru, текст никуда не отправляется.

Текст и инструкция отправляются ИИ для обработки. В историю Untype они не записываются.

Настоящее окно помощника Untype: выделенный текст и поле для задачи
Окно помощника с готовым текстом и кнопкой «Копировать»
Настоящее окно помощника до и после. Кнопки «Короче», «Деловой стиль» и «На английский» подставляют готовые инструкции.
  • Выделение через UI Automation.Свой небольшой COM-клиент поднимается по родителям до 16 уровней: в браузере выделение принадлежит документу, а не полю. На это отведено 900 мс.
  • Ctrl + C как запасной путь.Сначала полный снимок буфера: текст, HTML, RTF, файлы, картинки. Потом всё возвращается, если вы не успели скопировать что-то новое. Поля паролей пропускаются.
  • Текст не превращается в команду.Выделенное уходит модели отдельным сообщением как недоверенная JSON-строка, команды внутри него не выполняются. Запросы не сохраняются ни на сервере, ни в истории.

Можно даже без клавиш.

В настройках включается обращение по имени. Небольшая модель Vosk слушает прямо на компьютере и реагирует только на фразу целиком. Пока имя не прозвучало, звук никуда не уходит.

  • «Джарвис, запись»начать диктовку
  • «Джарвис, стоп»остановить и вставить
  • «Джарвис, отмена»отменить без распознавания
  • «Джарвис, отправь»вставить и нажать Enter

ИмяVosk на компьютере ждёт фразу «имя + команда» целиком.

КомандаВыполняется сразу. Слово «стоп» внутри обычной речи ничего не остановит.

ДиктовкаТолько этот звук уходит на распознавание, а «Джарвис, стоп» вырезается из конца текста.

  • Своя обвязка libvosk.Готовая обёртка из NuGet передаёт строки в ANSI и портит кириллицу, поэтому вызовы библиотеки написаны заново на UTF-8.
  • Строгое совпадение.Команда срабатывает, только если вся фраза равна «имя + команда», а уверенность распознавания не ниже 0,6. Имя проверяется по словарю модели при запуске.
  • Модель внутри установщика.vosk-model-small-ru ставится вместе с приложением и работает без интернета.

Работает тихо и не мешает.

Untype живёт в трее и не просит внимания. Всё, что связано с текстами, остаётся на вашем компьютере.

Главное окно

Горячая клавиша, микрофон, последняя диктовка и сколько слов вы надиктовали за день и неделю. Для счётчика хранятся только числа по дням.

Главное окно Untype: «Мысли вслух. Текст на экране.», горячая клавиша и счётчик надиктованных слов

История только у вас

Последние 500 диктовок лежат в SQLite на этом компьютере, без аудио. Историю можно выключить или очистить.

Раздел «История» в Untype

Исключения для игр

До ста приложений. Пока игра активна, микрофон освобождается, а горячая клавиша проходит в игру. Проверка идёт прямо из хука клавиатуры, без блокировок.

Настройки исключений Untype для приложений

Ключи под защитой Windows

Токены на компьютере зашифрованы через DPAPI, ключей распознавания в клиенте нет. Телеметрию можно выключить, и тексты она не содержит никогда.

voiceapp.db · settings · dictionary · history · usage_daily

Звуки без файлов

Сигнал «готово» синтезируется в памяти: 880 и 1 318 Гц. В установщике нет ни одного звукового файла.

Stream Deck и AutoHotkey

Запуск с флагом --toggle передаёт команду уже работающему Untype через именованные события Windows.

Несколько мониторов

Плашка появляется на экране активного окна, в его масштабе, и запоминает место, куда вы её перетащили.

Плашка в режиме перетаскивания: «Перетащите меня, куда удобно»

Не только программа, а весь продукт.

Сервер, аккаунты, оплата, обновления, сайт и аналитика. Всё это я сделал сам, чтобы Untype можно было найти, скачать, попробовать и купить без моего участия.

Сайт untype.ru: первый экран «Пишите голосом. В нужном окне.», помощник для текста и примеры
Сайт untype.ru на телефоне
  1. Объявлениеметки визита
  2. СкачиваниеUntypeSetup-482913.exe
  3. Установкакод из имени файла в реестре
  4. Первый запусккод уходит на сервер
  5. Аккаунт и оплатався цепочка в админке

У каждого скачивания свой шестизначный код в имени установщика. Так путь от объявления до оплаты виден без сторонних SDK. Если файл переименовали, загрузка сопоставляется по хешу адреса в пределах 48 часов и помечается как вероятная.

Минуты в аренду

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

Вебхуку не верим

Получив уведомление ЮKassa, сервер заново запрашивает платёж и сверяет магазин, сумму и заказ. Статус меняется только вперёд, двойной клик не создаёт второй платёж. Пока оплата работает в тестовом режиме.

Пробный период без карты

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

Раздел подписки в приложении Untype: пробный период и тарифы

Подписанные обновления

Манифест подписан ECDSA, открытый ключ зашит в приложение: даже взлом сервера не позволит подсунуть чужую программу. Перед установкой сверяется SHA-256.

Сайт и поиск

16 сценариев использования, 35 статей блога, микроразметка без ошибок на 38 страницах. Установщик пока не подписан: сертификат для ИП из России сейчас не выпустить, поэтому сайт заранее объясняет предупреждение SmartScreen.

Админка с воронкой

Путь от посетителя до оплаты, когорты удержания, расходы на ИИ и ошибки, сгруппированные по отпечатку. Каждое действие администратора пишется в журнал.

Даже видео собраны кодом.

Презентацию и видеоинструкцию я не монтировал руками. Ролик собирается из HTML-страницы с детерминированной временной шкалой: Chrome снимает её кадр за кадром, ffmpeg склеивает видео. Окна Untype в кадре повторяют настоящие и сверены с кодом.

Ролик для соцсетей: письмо с корпоративного на человеческий. Письмо и участники придуманы для ролика, ожидания сокращены при монтаже.
  1. ГолосОзвучка синтезирована, каждая реплика проверена распознаванием, неточные перегенерированы.
  2. СценыHTML и timeline.js: функция renderAt(t) выставляет каждый кадр по времени.
  3. СъёмкаChrome через puppeteer снимает кадр за кадром, без пропусков и рывков.
  4. Сборкаffmpeg, звуковые эффекты синтезированы скриптом, главы для плеера из той же разметки.

Что внутри

Клиент

WinUI 3 на .NET 10. Ядро без платформенного кода: оркестратор диктовки и обработка текста. Отдельно инфраструктура Windows:

  • хуки клавиатуры и смены окон;
  • WASAPI, буфер обмена, UI Automation;
  • плашка, трей, автообновление, 117 вызовов WinAPI.

Сервер

ASP.NET Core: 59 маршрутов, WebSocket для звука, SQLite для аккаунтов и аналитики. Служба systemd с жёсткими ограничениями, nginx и Let’s Encrypt.

Выпуски

Установщик Inno Setup без прав администратора. Обрыв обновления не ломает старую версию. Сайт выкладывается узкими пакетами со сверкой хешей и автоматическим откатом.

≈ 22 000строк C# в клиенте

≈ 12 000строк C# на сервере

467тест-методов, около 790 проверок с параметрами

704/704тестов в последнем полном прогоне

Что я вынес из своего продукта

  1. Проверять на себе.Я пользуюсь Untype каждый день, и самые полезные правки пришли из обычной работы, а не из списка задач.
  2. Сначала надёжность.Обрыв связи, занятый буфер, окно администратора: у каждого такого случая своё понятное поведение и свой тест.
  3. Программа лишь часть продукта.Скачивание, оплата, обновления и поддержка должны работать без автора, иначе продукт не масштабируется.
Следующий проектFit-AI

Давайте знакомиться

Хорошие проекты
начинаются
с разговора.

Нужен технический партнёр, помощь команде или решение для рабочего процесса? Расскажите, что хотите изменить — обсудим, чем я могу помочь.

@work_ilyaЛично мне в Telegram
Илья Болясов
Илья БолясовРазработчик. Технический партнёр.