av 75c6f0168a учёт: закрыт переезд хранилища, заведён урожай его ревью
- storage-without-pocketbase закрыта как реализованная: приёмка сошлась по всем
  пяти критериям записи и по двенадцати приёмочным свойствам рубрики ревью
  дизайна, работа лежит коммитом c9b7765
- урожай триажа ревью развёрнут в одиннадцать записей с тегом партии
  review-2026-08-23 и расставлен по зависимости, а не в конец списка
- находка про признак живости воркера слита в stalled-pipeline-metric: у неё та
  же причина — вставший конвейер неотличим от простоя
2026-08-23 08:41:49 +03:00

Transcriber Service

Сервис расшифровки аудиозаписей. Вход один — HTTP API.

Возможности

  • Приём аудиофайлов через HTTP API
  • Конвертация в ogg через ffmpeg
  • Распознавание речи через Yandex SpeechKit
  • Отслеживание статуса задач расшифровки
  • Своё хранилище: SQLite для метаданных и каталог файлов записей рядом с ним; метрики Prometheus

Технологии

  • Язык: Go 1.26, CGO не нужен
  • HTTP: стандартная библиотека, net/http
  • Распознавание: Yandex SpeechKit + Yandex Object Storage (S3)
  • Конвертация: ffmpeg
  • База данных: SQLite через modernc.org/sqlite, CGO не нужен
  • Шаги схемы: pressly/goose/v3, библиотекой — накат при старте
  • Файлы записей: свой каталог, подкаталог на запись
  • Метрики: prometheus/client_golang

Установка и запуск

  1. Клонируйте репозиторий
  2. Установите зависимости:
    go mod tidy
    
  3. Скопируйте образец конфига и заполните его:
    cp config.example.toml config.toml
    
  4. Запустите приложение:
    go run ./cmd/transcriber -c config.toml
    

Сервер запустится на порту из [server] port, по умолчанию 8080. Нужен установленный ffmpeg.

Кого пускают

Кто пришёл, сервис узнаёт из заголовка Remote-User, который ставит обратный прокси, сходив к Authelia; своего входа у сервиса нет. Кому верить, задаёт перечень доверенных адресов в секции [auth]. Подробности — docs/security.md, «Что разграничивает доступ»; известные прорехи образца конфига — docs/conventions/config.md.

Локально прокси нет, а браузер заголовков не ставит — на место контура встаёт подставной прокси из оснастки:

go run ./cmd/devtools proxy

Приложение после этого открывают по адресу проксиhttp://localhost:9000. В перечне доверенных адресов при этом должен стоять петлевой; строки под это стоят в config.example.toml.

Деплой

Деплой запускается из pet-project-server:

inv pl -- transcriber

Плейбук сам зовёт task image (контракт роли app_image): образ собирается локально и едет на сервер через docker save/load, реестр не участвует. Локально образ можно собрать и руками — task image даст transcriber:dev.

HTTP API

Адреса приложения живут под корнем /app: POST /app/audiorecords — приём записи, GET /app/audiorecords — страница своих записей, GET /app/audiorecords/{id} — карточка, GET /app/audiorecords/{id}/text — текст названного вида, GET /app/audiorecords/{id}/file — файл записи названной копии, GET /app/me — кто пришёл, GET /app/config — пределы, которые сервис объявляет приложению. Отдельными адресами стоят GET /metrics — метрики Prometheus с префиксом transcriber_ — и GET /health — проверка живости. Своего входа у сервиса нет: кто пришёл, называет заголовок обратного прокси (access). Больше на этом порту не отвечает ничего: всякий прочий путь получает разметку приложения.

Контракт приёма и опроса нормативен и живёт в openspec/specs/intake/spec.md: поля запроса и ответа, коды и условия. Менять его — необратимое действие (CLAUDE.md, «Работа»), и второго описания у него быть не должно.

Состояния задач

Перечень состояний, переходы между ними и число воркеров — docs/database.md, разделы «Таблицы» и «Представление данных»; как сложен конвейер целиком — docs/architecture.md.

Структура проекта

transcriber/
├── cmd/
│   ├── transcriber/        # Точка входа сервиса: конфиг, миграции, сборка зависимостей, запуск
│   └── devtools/           # Оснастка разработчика: подставной прокси и возврат записи в работу
├── internal/
│   ├── entity/             # Модели: запись, файл, результат распознавания
│   ├── ident/              # Выдача и разбор идентификаторов строк (ULID)
│   ├── contract/           # Интерфейсы адаптеров и репозиториев, типы ошибок
│   ├── config/             # Разбор config.toml
│   ├── metrics/            # Метрики Prometheus
│   ├── service/            # Конвейер расшифровки
│   ├── controller/
│   │   ├── http/           # HTTP-обработчики
│   │   └── worker/         # Фоновые воркеры
│   └── adapter/
│       ├── converter/ffmpeg/    # Конвертация аудио
│       ├── metaviewer/ffmpeg/   # Длительность аудио
│       ├── recognizer/yandex/   # SpeechKit + Object Storage
│       └── repo/sqlite/         # Репозитории, подключение к базе, шаги схемы, каталог файлов
└── data/                   # Каталог данных: база и файлы записей вместе
    ├── transcriber.db      # База (создаётся автоматически)
    ├── migrate.lock        # Замок наката схемы
    └── records/            # Файлы записей: подкаталог на запись

Хранилище

Таблицы базы — аудиозапись и её приложения. Поля, ключи, правило времени и идентификаторов, раскладка файлов записи и механика захвата задачи воркером — docs/database.md. Панели владельца у сервиса нет: единственное его действие вне экранов — возврат остановленной записи в работу подкомандой оснастки.

go run ./cmd/devtools resume -c config.toml <идентификатор записи>

Разработка

Схему двигают шаги pressly/goose/v3internal/adapter/repo/sqlite/migrations, файл на шаг, версия шага — число в начале имени файла. Непринятые шаги накатываются при старте, прежде чем поднимутся входы и стартуют воркеры; отказ шага роняет старт. Применённый шаг не переписывается: изменение — только новым файлом шага.

Проверки перед коммитом — одной командой:

task gate

Что она гоняет, чем краснеет и какой отказ считается объявленным долгом — CLAUDE.md, раздел «Гейт».

S
Description
Telegram bot and API for audio transcribes
Readme
2.6 MiB
Languages
Go 96.6%
Shell 1.4%
TypeScript 1.2%
Dockerfile 0.5%
Vue 0.2%