Введение
Последний год я всё чаще записываю демонстрации своих проектов, доклады, обучающие ролики и видео для YouTube.
Как и многие разработчики, сначала я думал, что самая сложная часть — записать материал. На практике всё оказалось наоборот. После записи начинается длинная и довольно однообразная работа:
- расшифровать аудио или видео;
- исправить ошибки распознавания;
- подготовить статью;
- написать описание для YouTube;
- сделать таймкоды;
- оформить текст в Markdown;
- подготовить публикацию для Telegram;
- иногда ещё и озвучить готовый текст.
Получается интересная арифметика. Запись двадцатиминутного видео занимает двадцать минут. Транскрибация — ещё две-три минуты. А вот дальнейшая обработка текста легко превращается в полчаса, а то и в час работы.
Именно тогда я понял: проблема давно не в распознавании речи. Проблема — во всём процессе обработки.
Думаю, коллегам это знакомо и за пределами YouTube: расшифровки совещаний с заказчиком, вебинары, демонстрации доработок, из которых потом нужно собрать инструкцию или статью. Задача одна и та же — превратить час речи в структурированный текст, потратив на это минимум ручного труда.
Шаг первый: не писать своё, а доработать чужое
Честно говоря, писать очередную программу для транскрибации я вообще не собирался. Сегодня есть множество хороших open-source решений, и одно из самых известных — Buzz: десктопное приложение на базе Whisper от OpenAI, с тысячами звёзд на GitHub и активным сообществом. Распознавание файлов и YouTube-роликов, запись с микрофона, экспорт в TXT/SRT/VTT — всё уже есть.
На английском языке качество меня полностью устраивало. Поэтому первой мыслью было не создавать своё, а улучшить существующее. Так появился мой форк Buzz.
Что не устраивало: русский язык
Whisper хорошо справляется с русским, но «хорошо» и «максимально качественно» — разные вещи.
Для русской речи сейчас есть специализированные открытые модели, которые на профильных бенчмарках обгоняют Whisper:
- GigaAM v3 от Сбера — CTC-модель, обученная именно на русском;
- T-one от Т-Банка — открытый ASR-проект для русской речи, из которого, помимо самой модели, можно взять n-граммную языковую модель KenLM.
Идея была простая: интегрировать GigaAM в Buzz и получить лучшее из двух миров — зрелый интерфейс Buzz и качество распознавания специализированных русских моделей.
Что пришлось сделать в форке
Звучит просто: «добавил поддержку GigaAM». По факту список работ выглядел так:
-встроен пайплайн GigaAM + T-one: акустическая модель GigaAM распознаёт речь, а её CTC-выход декодируется через beam search (публичный API `pyctcdecode`) с n-граммной языковой моделью KenLM из проекта T-one — связка «акустика + языковая модель» даёт заметно меньше ошибок в окончаниях и редких словах, чем жадное декодирование, отдельно для экспериментов T-one доступен и как самостоятельный движок;
- загрузчик GigaAM переписан без использования pip-пакета gigaam — модель ставится напрямую из репозитория, и это потянуло за собой работу с весами и словарём через обёртку transformers;
- декодирование CTC-выхода сделано через beam search с языковой моделью KenLM — на публичном API pyctcdecode; связка «акустическая модель + языковая модель» даёт заметно меньше ошибок в окончаниях и редких словах, чем жадное декодирование;
- определение CUDA — пробным прогоном модели с откатом на CPU: на части конфигураций fp16 на GPU просто падал, и надёжнее оказалось один раз «пощупать» железо, чем верить флагам;
- починены пословные таймстемпы и разбиение слишком длинных сегментов;
- из мелочей — скрыты консольные окна ffmpeg/ffprobe, которые выскакивали на Windows при каждой операции.
В результате качество распознавания русского заметно выросло, и получился вполне рабочий инструмент, которым я пользовался довольно долго.

Форк доступен здесь: https://github.com/ivanarama/buzz
Видео про эту модернизацию тут : Превращаем видео в текст с таймкодами | Buzz + T-one
Казалось бы — задача решена
Некоторое время я действительно думал, что этого достаточно. Видео распознаётся, текст получается качественным. Что ещё нужно?
Но довольно быстро выяснилось, что транскрибация — лишь первый шаг. После неё начиналась настоящая работа. Полученный текст нужно было отправить в LLM и попросить написать статью. Потом отдельно — описание для YouTube. Потом ещё раз — таймкоды. Оформить Markdown. Иногда перевести. Иногда озвучить.
Всё это выполнялось разными программами. Конвейер выглядел примерно так:
Каждый этап — это копирование текста, переключение между окнами и повторение одних и тех же действий. Именно в этот момент пришло понимание: проблема никогда не была в транскрибации. Проблема — в отсутствии единого рабочего процесса.
Почему форка оказалось недостаточно
Buzz — отличный проект, но его задача — транскрибация. Мне же хотелось автоматизировать процесс целиком: чтобы после распознавания одной кнопкой получить статью, краткое содержание, описание YouTube, таймкоды, пост для Telegram — или любой другой результат по собственному промпту. А затем, если нужно, тут же озвучить готовый текст.
Тащить всё это в форк означало бы переписать чужое приложение до неузнаваемости и навсегда остаться в состоянии «вечного merge» с upstream. Это уже не форк и не набор патчей — это отдельное приложение.
Так появился проект «Запись» (Zapis): https://github.com/ivanarama/zapis
Ещё одна причина: 2,5 ГБ против 288 МБ
Когда работаешь с инструментом каждый день, начинаешь замечать вещи, которые сначала кажутся мелочами. Например, размер.
Мой форк Buzz со всеми зависимостями занимал около 2,5 ГБ. Для современного компьютера не критично, но меня не покидало ощущение, что большая часть этих данных конкретному пользователю никогда не понадобится: в дистрибутив упаковано всё и на все случаи жизни.
В «Записи» подход другой: в дистрибутив не пакуется ни одна модель. GigaAM, KenLM, Whisper, Silero, ruaccent, голоса Piper — всё скачивается в локальный кэш при первом использовании, и только то, что пользователь реально выбрал. В результате приложение занимает около 288 МБ, а дальше «толстеет» ровно настолько, насколько этого хочет сам пользователь.
Приятный побочный эффект: обновление приложения не заставляет заново качать гигабайты моделей — они лежат в кэше отдельно.
Архитектура «Записи»
«Запись» — это локальное десктопное приложение, устроенное как маленький веб-сервис, упакованный в один исполняемый файл:
Zapis (десктоп-приложение, один exe)
- pywebview — нативное окно, внутри обычный веб-интерфейс (HTML/CSS/JS)
- FastAPI — локальный backend
- backend/asr/ — движки распознавания
- gigaam_engine.py (GigaAM v3 CTC + KenLM из T-one)
- whisper_engine.py (faster-whisper)
- backend/llm/ — клиент LLM и управление промптами
- backend/tts/ — пять движков синтеза + конвейер подготовки текста
- transcripts.py — история транскриптов
- tts_runs.py — история озвучек
Почему такой стек, а не Qt, как в Buzz:
- Frontend на HTML/CSS/JS — это быстрая вёрстка интерфейса, простые тёмная и светлая темы через CSS-переменные и никакой боли с нативными виджетами на трёх ОС.
- FastAPI внутри — это честное разделение на API и интерфейс. Стриминг ответов LLM идёт по SSE (Server-Sent Events) — слова появляются на экране по мере генерации, как в привычных чатах.
- pywebview — тонкая прослойка, которая превращает всё это в обычное окно приложения, а не вкладку браузера.
- Каждый движок — ASR, LLM, TTS — это отдельный модуль за общим интерфейсом с фабрикой. Добавление нового движка не трогает остальной код.
Собирается всё PyInstaller'ом: на Windows build.ps1 выдаёт Zapis.exe, на Linux и macOS build.sh — соответствующие бинарники. Сборка под три платформы автоматизирована через GitHub Actions: тег в репозитории — и релиз с артефактами собирается сам.

Блок первый: транскрибация (ASR)
Из коробки два движка:
На вход — любой аудио- или видеофайл: ffmpeg приводит его к нужному формату (16 кГц, моно) автоматически. На выходе — текст с пословными таймкодами с точностью около 40 мс. Экспорт — TXT, SRT, VTT.
Точные пословные таймкоды — это не только субтитры. Именно они позволяют дальше автоматически генерировать осмысленные таймкоды для YouTube: LLM получает не «голый» текст, а текст с привязкой ко времени.
Нюанс для Windows: KenLM собирается через MSVC; если компилятора нет, приложение не падает, а откатывается на жадное декодирование — качество чуть ниже, но всё работает.
Блок второй: LLM-постобработка
Это то, ради чего всё затевалось. Готовый транскрипт не нужно никуда копировать — он уже внутри приложения, и к нему сразу применяются пресеты:
- Статья — развёрнутый текст по мотивам записи;

- Описание YouTube — готовое описание ролика;

- Таймкоды YouTube — список глав с метками времени;

- Пост для Telegram — короткая выжимка для канала.

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

Все шаблоны промптов редактируются в настройках, включая системный промпт.

С провайдерами LLM подход максимально всеядный:
- любой OpenAI-совместимый endpoint — OpenAI, Azure, OpenRouter, Qwen, DeepSeek, а также локальные Ollama и LM Studio;
- Anthropic — отдельным профилем.
Профилей может быть несколько, с приоритетами и цепочкой fallback: если основной провайдер недоступен или вернул ошибку, запрос автоматически уходит следующему. В настройках задаются температура и лимиты токенов. Ответы стримятся пословно через SSE.

Отдельно отмечу возможность работать полностью локально: связка «GigaAM + Ollama» позволяет прогнать через весь конвейер запись, которая вообще не должна покидать периметр компании. Для расшифровки совещаний с заказчиком это бывает принципиально.
Блок третий: озвучка (TTS) — из текста в аудиокнигу
Третий этап конвейера — обратное преобразование: из текста в речь. Кладёте .txt или .md — получаете аудиокнигу.
Движков синтеза пять, на выбор:
Yandex SpeechKit мне понравился больше всех, но он платный (правда при регистрации и привязывании карты дают 4000р на эксперименты, этого при моём использовании хватит на долго)
Sber SaluteSpeech приостановили регистрацию, жаль, не смог проверить.
edge-tts - мой фаворит из бесплатных, по ощущениям чуть-чуть хуже яндекса
Но сам синтез — это меньшая половина дела. Если отдать движку сырой текст, на выходе будет «двадцать три ноль один» вместо «двадцать третье января» и неправильные ударения через слово. Поэтому перед синтезом текст проходит целый конвейер подготовки:
Отдельно отмечу нормализацию через LLM: правила покрывают типовые случаи, но когда в тексте встречается «ЗУП 3.1.28.150», аккуратно развернуть это в произносимый вид проще силами языковой модели. Результаты нормализации кэшируются, чтобы не гонять одни и те же фрагменты повторно.
Формат m4b — это «настоящая» аудиокнига: главы из текстового файла превращаются в главы аудиокниги, по которым можно перемещаться в любом плеере. Длительности пауз между предложениями, абзацами и главами настраиваются.

История операций
И транскрипты, и результаты озвучек сохраняются в историю. Это решает бытовую, но важную проблему: «а где тот текст, который я распознавал в прошлый вторник?»
Распознали видео месяц назад — открываете его из истории и просите LLM сделать из него новый материал. Исходное видео повторно прогонять не нужно. По сути, история превращает приложение в маленькую базу знаний из всего, что вы когда-либо записывали.

Как выглядит рабочий процесс теперь
Мой типовой сценарий после записи двадцатиминутного ролика:
1. Перетащил видеофайл в «Запись», выбрал GigaAM — через пару минут готов транскрипт с таймкодами.
2. Нажал пресет «Статья» — черновик статьи готов, осталось вычитать. (потом ещё обработка скилом, но это отдельная тема)
3. Пресет «Описание YouTube» — готово описание.
4. Пресет «Таймкоды YouTube» — готовы главы для ролика.
5. Пресет «Пост для Telegram» — готов анонс.
6. При необходимости — отправил текст в озвучку и получил аудиоверсию.
То, что раньше требовало пяти программ и часа ручной работы с копированием текста туда-сюда, теперь укладывается в несколько минут в одном окне. Схема из начала статьи схлопнулась в одну:
Установка
Самый простой путь — готовые сборки со страницы релизов:
https://github.com/ivanarama/zapis/releases
- Windows — Zapis.exe;
- Linux — бинарник Zapis;
- macOS (Apple Silicon) — Zapis.app в zip-архиве.
Единственное внешнее требование — ffmpeg в PATH (им декодируются аудио и видео). Модели скачиваются в кэш при первом использовании — при первом запуске распознавания нужен интернет, дальше офлайн-движки работают без сети.
Для запуска из исходников: Python, pip install -r requirements.txt, при этом GigaAM v3 ставится напрямую из GitHub-репозитория (в PyPI его нет). Все настройки живут в человекочитаемом settings.json — его можно править как из UI, так и руками.
Недавно вышел первый стабильный релиз v1.0.0. Лицензия — MIT, код полностью открыт.
Итоги
Главный вывод из этой истории для меня даже не про конкретное приложение.
Сначала кажется, что проблема — в качестве инструмента («Whisper недостаточно хорош для русского»), и её решает точечная доработка. Но настоящая проблема часто лежит уровнем выше — в процессе, в стыках между инструментами. Форк Buzz честно решил задачу качества распознавания. А сэкономленное время съедалось на копировании текста между окнами.
Поэтому:
- если вам нужна просто качественная транскрибация русской речи в привычном интерфейсе — возможно, вам хватит форка Buzz с GigaAM: https://github.com/ivanarama/buzz
- если же вы, как и я, из каждой записи делаете несколько артефактов — статью, описание, таймкоды, пост, озвучку — посмотрите на «Запись»: https://github.com/ivanarama/zapis
Оба проекта открыты. Буду рад вопросам, замечаниям и предложениям в комментариях — и особенно рад issue и pull request'ам на GitHub. Интересно услышать, какие сценарии автоматизации работы с речью актуальны у вас: протоколы совещаний, расшифровки вебинаров, озвучка инструкций?
Ссылка ютуб, на видеоверсию (можно скачать, если тут не открывается).
Вступайте в нашу телеграмм-группу Инфостарт