
Я Тимур Баян, занимаюсь разработкой почти всю свою жизнь, ещё со студенческих лет. Программирование и разработка у меня в крови! Я люблю решать нерешаемые проблемы, делать людям жизнь легче, тестить гипотезы, создавать крутые продукты. Так меня позвали работать в Уралсиб помогать управлять уже не одной, а сразу тремя командами. Сложностей я не боюсь, так что ныряем в задачи с головой!
Дано: три очень разные команды разработки, каждая со своим стеком технологий. С самого второго дня на меня понеслась тонна информации: куча встреч, много новых лиц, особенности технологий, legacy (куда ж без него). Я понял, что не успеваю заниматься всем и вся, что упускаю важные детали и нюансы из головы, прежде чем успею их оформить в минутки встречи или поручения.
Первым делом начал просто записывать проведённые встречи к себе на комп. Ха! А кто будет переслушивать и, самое главное, когда? Времени не хватит, чтобы снова всё переслушивать. Читать было бы гораздо быстрее. А если это чтиво ещё и прогнать через LLM'ку, то было бы вообще огонь! Она за меня всё прочитает и выдернет лишь самые интересные моменты, и мне не придётся ничего читать! Так зародилась идея создать что-то такое, что сильно упростило бы мою жизнь, а заодно и жизнь коллег.
Для начала нужно было проверить гипотезу - создать первый рабочий MVP и убедиться, что это в целом рабочая схема. Достал самый обычный OBS Studio, записал парочку своих конференций и полез искать в интернете, чем же можно вытащить слова из записи (транскрибировать). Самый более-менее вариант на тот момент был Yandex SpeechKit. Использовал его, стоимость примерно 30р/час. Не вопрос - регистрируемся, закидываем денег на аккаунт - прогоняем аудиозапись, получаем довольно точную транскрибацию встречи!
Развернул локально ollama, выбрал YandexGPT-5-Lite (она как раз тогда вышла, начало 2025-го) - хорошая моделька, которую потянет моя старенькая GTX 1080. Попросил её проанализировать текст и составить итоги встречи, подождал 30 секунд, получил сводные результаты и вуаля! Готово! Огонь! Домашняя видеокарта с довольно простой моделькой прогнала через себя все слова конференции и выдала результат. Сразу всё перечитал - основные моменты были подчёркнуты и записаны. Даже имена местами откуда-то узнала (поняв по контексту поручения вида: «Юра, сделаешь такую задачу до выходных?» , «Да, не вопрос.»)! Проверял я этот комплекс ещё несколько раз, чтобы убедиться, что всё это стабильно воспроизводимые результаты, а не галлюцинации ИИ, и делился в письмах с коллегами. Со временем коллеги начали спрашивать, как я это делаю, и тоже захотели такое же себе. Восторг, надо масштабировать! Получив добро у Насти, я принялся за работу.
Надо автоматизировать
Имеем: серверы банка, где можно проводить созвоны, проверенную и отлаженную гипотезу, что если записать конференцию, а затем извлечь текст, то можно с этим текстом поработать. Значит, нужно:
1) Научиться подключаться к конференц-комнатам, проходить авторизацию и записывать конференцию. Желательно ещё и записывать, кто говорил.
2) Транскрибировать получившиеся записи (желательно с максимально возможным качеством), вытащив слова. Желательно ещё сопоставить говорящих.
3) Прогнать через LLM, получить результаты.
4) Найти на это время. Не забываем, что основная работа - не строить роботов-секретарей :)
Самая главная часть - получить запись, а там найдём, чем обрабатывать дальше, решим этот вопрос по пути.
Главное требование: полный офлайн. Ничего не должно требовать доступа в интернет, всё должно будет работать в закрытом контуре банка.
Подключение и запись
Это оказалась самая сложная часть. Я подумал: большинство софта под ИИ реализовано на python, значит, логично будет взять python для всего. Проводим исследование - что и как сейчас подключается, снимаем дампы, делаем описание протокола (в целом довольно популярная технология конференц-комнат по WebRTC). Берём python, просим chatgpt накидать скрипт по подключению к конференц-комнате. Получаем, запускаем... ошибки... Часть исправляем сами, часть просим gpt дальше доработать скрипт. Смогли проходить авторизацию, видеть пользователей и даже отправлять сообщения в чат. Но подключиться к аудиопотоку по WebRTC не удалось. Снова ошибки. И снова, и снова, и снова. Ах, эта любовь и ненависть к chatgpt. Браузер же как-то подключается? Да и клиентов webrtc огромное количество, как может не получаться-то? Главное - не сдаваться, продолжай!
Ни много ни мало разными попытками и подходами прошёл целый месяц проб и ошибок. Я перепробовал всё: и пробрасывал порты, и изучал WebRTC, и даже пробовал перед отправкой чистить SDP от неиспользуемых адресов - ничего не помогало! Я перепробовал все опенсорсные пакеты на python, самым более-менее рабочим из них был aiortc - все ссылки и весь интернет указывали на него как на самый лучший пакет. Но что-то не клеилось - соединение RTC так и не могло установиться, ICE-протокол не мог установить связь с сервером.
Поняв, что я хожу по кругу и зря трачу время, несмотря на достигнутые успехи, я решил переписать всё на нормальный язык программирования - на Go. Чтобы не тратить лишнее время – скидываем уже почти рабочие наработки на python в chatgpt, просим его переписать на Go, получаем 5-6 файликов, собираем, компилируем, подпиливаем под себя (пару часиков), запускаем... работает! Сказать, что я был в шоке - не сказать ничего. Я месяц (!) возился с python, чтоб заставить aiortc записывать конференцию, а здесь версия на Go заработала спустя всего 4 часа, буквально с первого раза! С одной стороны, жаль потраченного времени, с другой стороны - опыт. Главное: у нас теперь есть прога, которая может подключаться к выбранной конференции и производить запись. Так получилась первая часть: recorder.
Транскрибация
Теперь мне надо вытащить слова из звукозаписи – транскрибировать её. Уже набив руку в работе с LLM, я понял, как ей надо ставить задачи. Поискав по интернету и изучив лучшие практики, я остановился на Whisper от openai (в том числе на Хабре всё чаще натыкался на статьи про него). Опять же, зачем писать всё самому, если можно с gpt собрать всё это быстрее? Описываем ситуацию, генерируем с ним dockerfile, разворачиваем, исправляем ошибки, снова разворачиваем. Спустя 4-5 итераций имеем рабочий билд. После нескольких тестов понимаем, что эта штука в целом работает, но с нюансом: работает только на моём процессоре, скорость обработки при 100% загрузки CPU составляет примерно 1:1 к длительности конференции. Если конференция шла час, то и ждёшь час, наблюдая, как компьютер умирает... Так дело не пойдёт! Снова описываем ситуацию чату гпт, так и так, мне нужна версия whisper с поддержкой GPU. В интернете есть всё, и про всё это знает chatgpt: разворачиваем переделанный whisper: https://github.com/ggml-org/whisper.cpp. Самой стабильной моделью оказалась ggml-large-v3-turbo: если будете тоже что-то транскрибировать, не скупитесь: она кушает чуть больше памяти (1.5гб), но распознаёт гораздо лучше остальных. Прокидываем gpu в докер-контейнер, собираем, вуаля! Контейнер подтвердил, что работа с gpu теперь возможна. Закидываем часовой файл конференции, ждём... на GeForce GTX 1080 (флагман 2016) соотношение 4:1. То есть часовая конференция обрабатывается за 15 минут! Это уже вкусно. Сохраняем как сервис транскрибации. Идём дальше.
Сопоставление говорящих
Теперь нужен скрипт, который возьмёт произнесённые слова, сопоставит их с говорившими в тот момент участников и отправит всё в локальную LLM, развёрнутую на домашней видеокарте. От recorder'а у меня есть лог говорящих с точностью до секунды. Пишем скрипт сопоставления, прогоняем... получаем какой-то бред. Почему говорил я, а засчитывают моей коллеге? Оказалось, что секундной точности недостаточно: в одну и ту же секунду может говорить или издавать звук сразу 2-3 человека. А целую реплику или вопрос можно успеть произнести за полсекунды. Значит, нужно просто записывать лог говорящих с точностью до миллисекунды.
Добавил миллисекундную точность - всё равно проблемы. Разбираю лог, сверяю с аудиозаписью и вижу проблему: сервер конференц-связи сообщает о говорящих с рандомной задержкой, в то время как звук и слова уже идут. То есть у нас имеются произнесённые слова, но в этот момент, судя по логу, «никто не говорил». Что ж, кто сказал, что будет просто? Делаем эвристики, пытаемся угадать, кто говорил, в том числе по продолжающейся складной речи до следующего абзаца. Решение не идеально, туда попадают рандомные перебивания, фоновый шум и разговоры, но это максимальное качество в текущих условиях.
Агент LLM
Окей, наконец-то мы получили долгожданный, заветный текст всей конференции, да ещё и с сопоставленными по логу именами говорящих! В чём обрабатывать? Для пилота берём заветный народный уже полюбившийся мне YandexGPT-5-Lite (спасибо, Яндекс!). Пишем промптер - берёт транскрибированный текст, прогоняет через LLM, получает результаты.
В целом это оказалась самая простая часть - все api давно известны: поднимаешь llama/ollama, обращаешься по REST'у, получаешь простой понятный ответ. Ошибиться шансов практически нет.
Приём заказов
Казалось бы, все программы написаны. Но нужен ещё какой-то бот, который будет принимать заказы на запись встреч. На время пилота был выбран телеграм-бот: в этот раз я не стал себе изменять и взял привычный php, наклепал за вечер бота. Он принимал от юзеров из белого списка заказы на запись.
Раннер - оркестратор
Почти все программы написаны. Но чего-то не хватает. Я много думал над вариантами реализации всего комплекса: от получения заявки на запись до отправки результатов. Мог пойти от простого: одна программа по завершении передаёт управление другой. Но я понимал, что в любой момент что-то может пойти не так, и нужно иметь возможность в любой момент пнуть зависший/сломавшийся скрипт. Поэтому была выбрана механика с централизованным раннером-оркестратором, который будет следить за всеми программами, запускать одну за другой с нужными параметрами запуска и следить, чтобы всё работало как надо.
Его тоже решил написать на Go, всё же это очень ответственная часть. Проблем здесь не возникло, для простоты использовал обычную БД Postgres с таблицей и очередями заданий. Я разместил всё оборудование полностью на домашнем компьютере, мы собрали пилотную группу из 20 человек и начали пилот.
Кто ещё за DimaTorzok?
Пилотный проект проходил неплохо: в день записывал по 3-5 встреч, смотрел результаты и анализировал их, следил за стабильностью работы. Всё чаще стал замечать упоминания какого-то DimaTorzok. Сначала подумал, что кто-то прикалывается. Оказалось - это баг, ему даже сайт отдельный сделали: https://dimatorzok.com/ru/. Суть такова: Whisper учили русской речи по роликам на ютубе, и, чтобы сопоставить, кто что сказал - они брали субтитры от роликов. И так получилось, что определённая часть из этих материалов была подготовлена человеком с ником DimaTorzok. И в сценах, где ролик уже заканчивался и было определённое молчание (не полный мут, а звук тишины, когда кто-то молчит во включённый микрофон) - там показывалось сообщение: "Субтитры подготовил DimaTorzok". И вот такой шум, когда все молчат, но какой-то фон идёт и распознаётся whisper'ом как "DimaTorzok". Это явный баг, и, к счастью, его легко обойти. После сбора нескольких десятков конференций выяснилось, что самые частые багованные словосочетания это: «Субтитры сделал DimaTorzok», «Таскай и файди стендерка аутбуксделал» (я не знаю, откуда это, не спрашивайте), «Продолжение следует» (да, кто бы мог подумать, что такое пишут в конце роликов).
В общем, добавили такие реплики в исключения, едем дальше.
Нестабильность LLM
Получавшиеся результаты в целом соответствовали моим ожиданиям: моя LLM генерировала основные тезисы, часть из них пропускала. Бывает, путала имена (из-за исходно грязного материала). Но самое ужасное было то, что она периодически выдавала контент в .md формате! Как бы я её ни просил - через раз получался не тот формат. Со временем я нашёл закономерность - чем дольше шла конференция (1.5 часа), тем выше шанс, что робот пришлёт что-то не то. Начал копать, вся причина оказалась в маленьком контексте: 32к токенов - это примерно 15 тысяч слов, которые произносятся в среднем за 45-60 минут обычной конференции (конечно, если там не было человека, который очень быстро говорит). Из-за слишком большого контекста LLM забывала то, о чём мы её просили в начале (выдать конференцию в html с простой разметкой), и начинала выдавать то, что посчитает нужным.
Для решения этой проблемы был написан обход: если конференция получалась слишком длинной (свыше 12 000 слов) - она делилась на 2 части (или на большее количество частей с перекрытием). Затем просим ИИ разделить выбранный участок на темы с разметкой: с какой строки какую тему обсуждали, с перекрытиями. И дальше LLM'ке скармливались эти нарезанные части, одна за другой. У каждой порядка 5000 слов. С таким уже можно работать и получать довольно точные результаты.
Пора внедрять
Пилот был признан успешным, мы с Анастасией Половьян показали и рассказали о нём руководству, всем понравилось, поехали внедрять. Больше всего в банке Уралсиб мне понравилась лёгкость внедрения: мы с Настей показали наше решение архитекторам, безопасникам и коллегам, отвечающим за железки: всем всё понравилось, довольно быстро одобрили внедрение в контуре банка. Банк как раз в это же время уже закупал промышленные видеокарты Nvidia H200, на которых спокойно разворачивается и Whisper и мощные LLM'ки. Мы оформили все необходимые документы, заявки. В течение недели нам выделили новые сервера, за пару дней получили все доступы, дождались поставки видеокарт и разворачивания LLM. Помогли коллегам собрать и поднять локальный Whisper.cpp, и понеслась!
Лучший интерфейс - отсутствие интерфейса
Напомню - на время пилота коллеги заказывали транскрибацию через телеграм-бота. Это, конечно, всё прикольно (и тогда телеграм ещё не был заблокирован), но надо было делать что-то другое в контуре. Вариантов несколько:
1) Создавать внутренний сайт, где любой сотрудник мог бы заказать запись конференции
2) Создавать бота во внутреннем мессенджере
3) А может, сделать ещё проще? Может, да ну их, эти интерфейсы?
Я сторонник упрощения, а не усложнения. Чтобы придумать, как сделать пользовательский путь проще, надо самому пройти по нему. Начать нужно с вопроса: с чего начинается конференция? С её планирования. Встреча ставится через календари в Outlook, где проверяются свободные слоты и выбирается время и место встречи. А значит, самый простой путь попасть в конференцию - это чтобы робота сразу к ней добавили! Значит, нужно заделаться обычным юзером Outlook, чтобы робота можно было пригласить в конференцию. Не вопрос! Пишем заявку в SD, описываем ситуацию, нам регистрируют техучётку, выделяют ей даже почтовый ящик. Переписываем telegram-бота: вместо работы с telegram он теперь будет работать с почтой Outlook по протоколу EWS. Проблем снова не возникло, рука в php набита - бот ищет непрочитанные письма-приглашения на конференцию каждые 15 секунд (повторяя логику Outlook, так что лишней нагрузки не создаём, мы же не хотим уронить корпоративную почту?). По итогам встречи организатору/всем участникам (в зависимости от настроек) приходят результаты встречи.
Разворачивание и внедрение
Всё развернули на сервере, заказали сетевые связанности, проверили всю работу и первые дни погоняли чисто на своих тех же юзерах. Всё работает - полный цикл готов! Оркестратор следит за всеми задачами, перезапускает зависшие или сбойнувшие задания.
Опубликовали внутреннюю новость, провели небольшое демо, и народ начал пользоваться: достаточно во встречу добавить робота-секретаря, и он подключится к конференции. Поначалу с неохотой, а затем всё больше и больше людей начало узнавать о таком сервисе. Изначально мы пиарили этого бота как робота-секретаря, который очень помогает командам разработки фиксировать договорённости и двигаться по плану, а по итогу половина пользователей - коллеги из бизнеса: они тоже ведут различные проекты, и такой бот им оказался очень кстати! С ним ведут дейлики, планёрки, обсуждают результаты продаж, планы, проекты, новости и погоду. После массового распространения, я получил от коллег кучу лайков, похвалы и уважения.
Дальнейшее развитие
Первое рабочее MVP полного цикла сделал в июле 2025, в августе признали пилот успешным, а в сентябре это было уже развёрнуто в контуре банка. Я проработал во многих банках, но такую скорость, лёгкость и заинтересованность коллег во внедрении интересных фич вижу впервые.
С момента внедрения мы добавили аналитику встреч: была ли озвучена повестка встречи, были ли договорённости, сколько приглашённых реально участвовало во встрече (чтоб не звать в будущем тех, кого не обязательно было звать, отвлекая от работы). Это больше информационная аналитика для замера развития персонала.
Со временем мы заметили, что некоторые встречи, бывает, задерживаются и вместо запланированного часа могут проходить 1:05, 1:15 или даже 1:30 часа. Робот максимум досиживал 5 лишних минут и отключался. А некоторые встречи заканчивались намного раньше запланированного. Мы поняли, что бессмысленно хардкодить точное количество минут, которое должен сидеть бот. Вместо этого он остаётся в конференции до тех пор, пока основной состав участников всё ещё разговаривает: если 50-70% пользователей не меняется, значит, конференция продолжается, а значит, и боту нужно продолжать записывать (но через чат можно преждевременно остановить такое продолжение записи).
Также улучшили отправку писем: стали добавлять туда опрос о качестве анализа результатов встречи и добавили ссылку на внутренний ресурс, где можно прочитать всю транскрибацию встречи. Из недавнего: сгенерировали видеовставки с kling.ai , и, когда время встречи уже заканчивается, бот включает камеру и начинает намекать на то, что встреча скоро заканчивается/встреча вышла за рамки запланированного и пора идти работать. Это помогает не выходить за лимит времени и не опаздывать.
Заключение
Этой статьёй я хотел поделиться собственным опытом: продолжать верить в свои идеи, даже если кто-то (даже ИИ) говорит, что это невозможно: никогда не останавливайтесь и продолжайте верить в свои задачи! Если вы это придумали и можете повторить - значит, это возможно закодить! Напоминаю, что это было сделано ещё до эпохи массового внедрения кодинговых агентов, которые вполне могут реализовать такой стек за несколько вечеров. А сейчас мы в Уралсибе запускаем совсем другие проекты, подписывайтесь!

