Есть неприятный момент на техническом собеседовании. Интервьюер заканчивает длинный вопрос, и ты понимаешь, что тема знакома. Ты делал это на работе, помнишь правильный подход и даже подходящий случай. Но отвечать нужно сейчас, а в голове одновременно идут четыре процесса: разобрать формулировку, вспомнить детали, выстроить ответ и не зависнуть в тишине.
Если интервью на английском, добавляется пятый — перевод.
Проблема здесь не в знаниях, а в бюджете времени. Естественная пауза после вопроса — это примерно две‑четыре секунды. Дальше собеседник считывает её как заминку. Всё, что должно уместиться в этот интервал, — распознать конец реплики, понять, о чём именно спросили, собрать структуру ответа и начать говорить.
Обычный AI‑чат в соседней вкладке в этот бюджет не помещается, и дело не в качестве модели. Посчитайте, из чего складывается задержка: услышать вопрос, переключить окно, напечатать или вставить формулировку, дождаться генерации, прочитать выдачу, найти в ней полезное, вернуться в разговор. Даже без времени на саму генерацию транспортная часть съедает больше, чем у вас есть.
Модель может быть сколь угодно хорошей — она подключается к разговору с опозданием на целую паузу.
Отсюда и постановка задачи: убрать транспорт целиком. Приложение должно само слышать реплику собеседника, само понимать, что вопрос закончился, само подтягивать контекст и выкладывать ответ на экран — без единого действия со стороны человека, который в этот момент занят разговором.
Дальше выяснилось, что почти вся сложность лежит не в вызове модели, а в трёх местах: захват звука в Windows, поведение потокового распознавания и порядок генерации. Про них и будет статья — четыре проблемы, которые не видно в красивой демонстрации, и что пришлось сделать с каждой.
Что получилось
Приложение слушает разговор с двух сторон отдельно: реальный микрофон и системный звук Windows. Распознаёт речь потоком, собирает законченный вопрос и готовит два варианта ответа — короткий, чтобы сразу начать говорить, и подробный, как план на случай, если вопрос требует разбора.
В режиме Interview подключаются резюме и описание вакансии, поэтому ответ может опираться на реальный опыт кандидата, а не быть универсальным текстом. Недавняя история разговора тоже уходит в контекст — чтобы помощник понимал продолжения вроде «а почему вы выбрали именно этот подход?».

Подсказки выводятся в отдельную компактную панель поверх окна звонка. Размер и прозрачность настраиваются, в режиме AI Only транскрипт скрывается и остаются только ответы.
Отдельная история — когда вопрос не проговаривают, а показывают. Интервьюер выводит на экран схему, кусок кода или условие задачи и спрашивает «что здесь не так?». Звук в этот момент бесполезен: распознавание слышит два слова, а вся суть вопроса на картинке. Поэтому есть разовый снимок экрана по нажатию средней кнопки мыши — снимается монитор под курсором и уходит в модель, которая умеет работать с изображениями.
Здесь важны три решения. Снимок делается по явному действию, а не потоком: постоянный захват экрана — это и лишний трафик в модель, и совсем другой уровень доверия, которого приложению на чужом компьютере лучше не требовать. Снимок разовый — он прикладывается к текущему запросу и не превращается в постоянный контекст. И он не сохраняется: в историю звонка попадает пометка, что снимок был сделан, а не сам файл.
Есть перевод обеих сторон разговора на 27 языках, с возможностью вернуть переведённую речь обратно в звонок — в том числе голосом самого пользователя, если добавить локальный голосовой профиль из образца на 10–60 секунд.
Разговор при этом пишется и расшифровывается сам, конспектировать по ходу ничего не нужно. Сессия сохраняется целиком: транскрипт с таймкодами, обе языковые стороны, ответы ассистента, краткий итог и аудиозапись — по отдельной дорожке на каждое направление. Транскрипт выгружается в текстовый файл одной кнопкой, запись можно переслушать, сессию — открыть через неделю. Всё это лежит локально, в каталоге приложения, а не в облаке.
Работает с Zoom, Meet, Teams, Discord и любыми браузерными (и не только) звонками, потому что живёт на уровне аудиоустройств Windows, а не как расширение к конкретному сервису.
Почему не хватило AI в соседней вкладке
Модели доступны всем, никакой секретной внутри нет. Разница не в модели, а в том, доходит ли нужный контекст до тебя вовремя.
В чате ты сам себе транспорт: услышал, переключился, напечатал, дождался, отфильтровал, вернулся. Каждый шаг стоит секунд, и все они вычитаются из того времени, пока пауза в разговоре ещё выглядит естественной. Помощник убирает транспорт целиком: вопрос он слышит сам, контекст резюме и вакансии у него уже есть, короткий вариант ответа появляется раньше подробного, а подробный догружается, пока ты говоришь первую фразу.
Отдельно про встроенные субтитры, потому что вопрос возникает сразу. Перевод в Zoom, Teams и Meet решает другую задачу: он показывает текст того, что сказали, внутри своей платформы. Здесь три технических отличия, а не оценки. Субтитры живут в одном сервисе — переехали в Discord или в браузерный звонок, и их нет. Они текстовые: обратно в звонок голосом ничего не уходит, собеседник по‑прежнему слышит вас на вашем языке. И они ничего не знают о вашем резюме и вакансии, потому что это переводчик, а не помощник в формулировании ответа. Захват на уровне аудиоустройств Windows нужен ровно для первого пункта: он не зависит от того, чем именно звонят.
Четыре проблемы, которые незаметны в красивой демонстрации
На Хабре уже проверяли ИИ ассистентов на собеседованиях и довольно точно описали то, о чём обычно молчит реклама: приложение не слышит интервьюера в наушниках, теряет контекст, заставляет постоянно нажимать кнопки и создаёт неловкие паузы. Это ровно тот список, который я и разгребал.
Похожие продукты на рынке есть — Cluely, Beyz, Parakeet AI и другие. Устроены они схоже между собой: облачный сервис с аккаунтом и подпиской, а главным аргументом в рекламе идёт незаметность для платформы созвона. Я сознательно сделал три вещи иначе, и это не про «лучше», а про другой набор решений.
Обработка идёт с ключами пользователя, а не через мой сервер. У меня нет бэкенда, через который проходят чужие звонки, и нет аккаунта. Распознавание и модели подключаются собственными ключами — плата идёт напрямую провайдеру, а история, транскрипты и записи остаются на машине.
Перевод в обе стороны — не побочная функция, а половина продукта. Помощник ответов и переводчик решают разные задачи. Здесь они в одном приложении: 27 языков, оригинал и перевод рядом, а переведённая речь при желании возвращается в звонок — в том числе синтезированная голосом самого пользователя.
Невидимость. Флаг исключения окна из захвата в приложении есть, ниже я подробно разбираю, как он устроен и в каких случаях не работает.
1. Интервьюер говорит не в микрофон кандидата
Если звонок идёт через наушники, обычная запись микрофона получает только мой голос. Собеседника в ней нет вообще.
Поэтому захват идёт двумя независимыми потоками на уровне аудиоустройств Windows, а не плагином к конкретному сервису: микрофон берётся напрямую, вторая сторона — петлёй с устройства вывода. Два потока, две сессии распознавания, два языка. Побочный эффект приятный: сценарий вообще не привязан к приложению для звонков.
Технически здесь три неочевидных места.
Устройства меняются посреди звонка. Пользователь втыкает гарнитуру, Windows переключает вывод по умолчанию — и поток, открытый на старом устройстве, замолкает, не сообщая об ошибке. Движок должен пережить смену устройства и переоткрыть поток, а не тихо отдавать тишину до конца разговора.
Тишину надо отличать от неработающего захвата. Симптомы одинаковые: транскрипта нет. Поэтому по каждому направлению логируется, какое устройство фактически открыто и какой уровень сигнала на него приходит. Без этих двух строк диагностика превращается в гадание, а показания микшера Windows тут обманчивы: индикатор в районе единиц процентов — это нормальная речь, а не отсутствие звука.
Виртуальный аудиокабель нужен не всегда. Для подсказок и перевода на экране он не требуется вовсе — достаточно петли с вывода. Он появляется только в более сложном сценарии, когда переведённую речь надо вернуть обратно в звонок: тогда приложение должно отдать синтезированный звук в устройство, которое сервис связи считает микрофоном.
2. Потоковое распознавание дробит один вопрос
Это оказалось важнее выбора модели.
Потоковое распознавание не отдаёт готовую реплику. Оно присылает промежуточную гипотезу, потом переписывает её, уточняя предыдущие слова, и только затем помечает фрагмент как финальный. Одна произнесённая фраза приходит несколькими кусками, причём границы кусков определяются паузами в речи, а не смыслом: «How would you test authorization» и «in a multi‑tenant API» вполне могут стать двумя разными финальными сегментами.
Наивная реализация отправляет в модель каждый финальный фрагмент. Результат — три ответа на три половины одного вопроса, и все три висят на панели одновременно.
Что понадобилось:
Сборка сегментов в эпизод. Финальные фрагменты не уходят в модель сразу, а накапливаются, пока не появится признак завершённости реплики. Ориентир — пауза, а не знак препинания: пунктуацию распознавание расставляет уже после, и полагаться на неё для принятия решения поздно.
Отмена устаревшего запроса. Если распознавание переписало реплику, пока модель ещё генерирует, старый запрос отменяется, а его карточка убирается с панели, а не остаётся висеть с пометкой об ошибке. Пользователь не должен выбирать между двумя ответами на разные версии одного вопроса.
Отсев хвостов. Обрывок предыдущей реплики, догнавший распознавание с опозданием, легко принять за новый вопрос и запустить генерацию заново — уже после того, как ответ на этот же вопрос показан. Такие фрагменты приходится сравнивать с уже обработанным эпизодом и отбрасывать.
Отдельная обработка коротких реплик. «Ага», «понятно», приветствия проходят по укороченному пути и получают один короткий ответ вместо двух развёрнутых, иначе панель забивается разбором на пустом месте.
Сильная модель отвечает плохо, если получила только хвост реплики. Качество ответа на живом звонке определяется тем, что вы ей отдали, а не тем, какую модель выбрали.
3. Универсальный ответ не похож на ответ живого человека
«Расскажите о вашем сложном проекте» без личного контекста почти провоцирует модель сочинить правдоподобную историю. Читать её вслух — гарантированный провал на первом уточняющем вопросе.
Поэтому в режиме Interview используются резюме и вакансия, а ответ формируется от первого лица только на основании переданных фактов. Если в резюме нет личного кейса, помощник не должен выдумывать, что кандидат якобы находил такую уязвимость в проде.
Методику предложить может, чужой опыт приписать — нет.
Для технических тем есть ещё локальный слой готовых ответов: по нормализованному тексту вопроса подбирается заготовка из локальной базы по направлениям — авторизация, API, токены, GraphQL, мобильная безопасность и так далее. Срабатывает он не всегда, а по порогу уверенности: точное совпадение термина или алиаса даёт около 0.9, набор ключевых слов — от 0.82 и минимум два совпадения, иначе вопрос уходит в модель как обычно. Никакого обучения здесь нет: это детерминированный поиск по заранее заполненной базе, а не модель, дообученная на разговорах пользователей. Разговоры вообще никуда не уходят на обучение.
Сколько разговора помнит ассистент. В контекст запроса попадают последние 30 реплик диалога, с общим потолком в 12 000 знаков и обрезкой каждой строки до 1 200 — иначе одна длинная реплика вытесняет весь остальной разговор. Дальше контекст ещё раз ужимается под конкретный запрос: около 2 000 знаков для короткого ответа и до 6 000 для подробного, потому что короткому нужна скорость, а не полнота. Отдельно живёт окно маршрутизации: последние 8 сообщений за 5 минут, по которым выбирается, как вообще обрабатывать реплику. Именно эта память и позволяет понимать продолжения вроде «а почему именно так?» — без неё каждый уточняющий вопрос выглядит как новый.
4. Хороший ответ через десять секунд — уже плохой ответ
На живом интервью нельзя молча ждать эссе.
Короткая и подробная подсказки поэтому генерируются независимо: первая нужна, чтобы начать фразу, вторая догружает структуру. У AI‑провайдеров есть резервная цепочка, чтобы один сбой не остановил помощника целиком.
Как это выглядит во время разговора

Тот самый вопрос:
How would you test authorization in a multi‑tenant API?
Пока интервьюер договаривает, приложение собирает законченную реплику из системного звука. Затем на панели появляются два уровня.
Короткий старт:
Я бы начал с карты ролей, ресурсов и границ tenant, а затем проверил горизонтальное и вертикальное повышение привилегий на каждом endpoint.
Развёрнутая опора:
Зафиксировать роли, владельцев объектов и ожидаемую матрицу доступа.
Повторить запросы с идентификаторами объектов другого tenant.
Проверить массовые операции, вложенные ресурсы, GraphQL‑узлы и косвенные ссылки.
Сравнить поведение разных ролей и отдельно проверить серверную фильтрацию.
Объяснить влияние найденной ошибки и предложить проверку авторизации на уровне объекта.
Это иллюстрация формата, а не обещание идеального ответа на любой вопрос. Смысл короткой подсказки — помочь начать говорить без мёртвой паузы. Подробная нужна как план, а не как текст для чтения вслух.
И честно про промахи: на вопросах вроде «расскажите про ваш самый сложный проект» подсказка регулярно оказывается слишком общей. Она не знает того, чего нет в резюме, и правильно делает, что не выдумывает. Но выглядит это бледно, и тут помощник бесполезен.
Что под капотом
Упрощённо путь вопроса выглядит так:
микрофон кандидата ─┐ ├─> захват аудио Windows (Rust) системный звук ─────┘ │ v потоковое распознавание речи │ v сборка законченного вопроса │ ┌───────────────┴───────────────┐ v v короткая подсказка подробная структура └───────────────┬───────────────┘ v плавающая панель
Аудиодвижок написан на Rust. За процессом следит Elixir‑супервизор и перезапускает его при сбое. Локальный Python/Flask‑сервис хранит настройки и историю, интерфейс работает в Electron.
Почему панель — отдельное окно
Подсказки живут не внутри основного окна, а в самостоятельном окне поверх остальных: без рамки, без кнопки на панели задач, с регулируемой прозрачностью от 20 до 100 процентов. Причина не в эстетике.
В Windows есть механизм исключения окна из захвата экрана — SetWindowDisplayAffinity. Он ставит окну флаг, из‑за которого композитор не отдаёт его содержимое тем, кто снимает экран через графические API системы: скриншотеры, записывающие программы, демонстрация экрана в звонке. В Electron это доступно как setContentProtection, и в приложении оно включено для панели подсказок по умолчанию. На основное окно флаг не ставится — оно обычное.
Смысл здесь простой и вполне бытовой: когда вы сами демонстрируете экран, ваши рабочие заметки не должны уезжать собеседнику вместе с презентацией.
Поэтому правильный порядок такой: открыть панель, записать экран своим обычным способом и отдельно расшарить экран в звонке самому себе — и посмотреть, что получилось именно в вашей связке.
Где данные и кто слышит разговор

Приложение устанавливается на компьютер. У меня нет обязательного облачного аккаунта и своего сервера, через который проходят чужие звонки. Локально остаются настройки, история, транскрипты, необязательные записи, загруженное резюме и голосовой профиль.
Но продукт не полностью офлайн, и говорить «данные вообще не покидают компьютер» было бы неправдой. Аудио уходит в Deepgram для распознавания, текст — в настроенные пользователем сервисы перевода и AI, по его собственным ключам и на его условиях с этими провайдерами.
Запись и анализ разговора могут требовать согласия участников. Требования работодателя и законы конкретной страны важнее возможностей программы.
Кому это может помочь, а кому точно нет
Помощник рассчитан на человека, который знает свою профессию, но на интервью теряет структуру ответа, нервничает, забывает подходящий пример или проходит собеседование не на родном языке.
Он не сделает джуна сеньором за один звонок. Может ошибиться в факте, неправильно распознать термин, предложить слишком общий ответ. Если слепо читать незнакомый текст, первый уточняющий вопрос это покажет. Я отношусь к нему как к интерактивному конспекту и второму экрану памяти, а не к замене знаниям.

