Files
transcriber/README.md
T
av a4646c0930 Инструкции для Claude, конфиг линтера, актуализация README
CLAUDE.md описывает конвейер задач, подвохи конфига и правило про четыре
списка колонок в репозитории sqlite.

.golangci.yml включает стандартный набор плюс errorlint; осознанные
непроверенные вызовы вынесены в исключения.

README приведён к коду: эндпоинты /api/audio и /api/status/:id, состояния
задач, структура internal/, фактические колонки таблиц.
2026-08-10 20:24:30 +03:00

8.0 KiB
Raw Blame History

Transcriber Service

Сервис расшифровки аудиозаписей. Два входа — Telegram-бот и HTTP API.

Возможности

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

Технологии

  • Веб-фреймворк: gin-gonic/gin
  • Telegram: go-telegram-bot-api
  • Распознавание: Yandex SpeechKit + Yandex Object Storage (S3)
  • Конвертация: ffmpeg
  • SQL Builder: doug-martin/goqu
  • Миграции БД: pressly/goose
  • База данных: SQLite
  • Метрики: prometheus/client_golang

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

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

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

Белый список Telegram

Бот отвечает только тем, кто перечислен в [server] users_while_list. В config.dist.toml этого ключа нет — добавьте его сами:

[server]
users_while_list = ["@username"]

Значения сверяются со строкой автора сообщения из Telegram (@username либо имя с фамилией), а не с числовым id.

Деплой

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

inv pl -- transcriber

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

API Endpoints

POST /api/audio

Загружает аудиофайл и создает задачу на расшифровку. Отвечает 201 Created.

Параметры:

  • audio (form-data) - аудиофайл для расшифровки

Пример запроса:

curl -X POST \
  http://localhost:8080/api/audio \
  -F "audio=@/path/to/your/audio.mp3"

Ответ:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "created"
}

GET /api/status/:id

Получает статус задачи расшифровки по ID. Поле transcription_text появляется, когда задача перешла в done.

Пример запроса:

curl http://localhost:8080/api/status/550e8400-e29b-41d4-a716-446655440000

Ответ:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "done",
  "created_at": "2024-01-01T12:00:00Z",
  "transcription_text": "расшифрованный текст"
}

GET /metrics

Метрики Prometheus с префиксом transcriber_.

GET /health

Проверка работоспособности сервиса.

Ответ:

{
  "status": "ok",
  "message": "Transcriber service is running"
}

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

  • created - задача создана, файл сохранён, ждёт конвертации
  • converted - файл сконвертирован в ogg, ждёт отправки на распознавание
  • transcribe - распознавание запущено в Yandex SpeechKit, ждём результата
  • done - задача завершена успешно
  • failed - задача завершена с ошибкой

Задачи двигают три фоновых воркера: conversion_worker, transcribe_worker и check_worker. Каждый опрашивает базу раз в секунду и делает один шаг.

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

transcriber/
├── main.go                 # Точка входа: конфиг, миграции, сборка зависимостей, запуск
├── internal/
│   ├── entity/             # Модели: задача, файл, результат распознавания
│   ├── contract/           # Интерфейсы адаптеров и репозиториев, типы ошибок
│   ├── config/             # Разбор config.toml
│   ├── metrics/            # Метрики Prometheus
│   ├── service/            # Конвейер расшифровки
│   ├── controller/
│   │   ├── http/           # HTTP-обработчики
│   │   ├── tg/             # Telegram-бот
│   │   └── worker/         # Фоновые воркеры
│   └── adapter/
│       ├── converter/ffmpeg/    # Конвертация аудио
│       ├── metaviewer/ffmpeg/   # Длительность аудио
│       ├── recognizer/yandex/   # SpeechKit + Object Storage
│       ├── telegram/            # Отправка сообщений
│       └── repo/sqlite/         # Репозитории
├── migrations/             # Миграции goose, вшиты в бинарник через go:embed
└── data/
    ├── files/              # Директория для сохранения файлов
    └── transcriber.db      # SQLite база данных (создается автоматически)

База данных

Таблица files

  • id (TEXT) - UUID файла
  • storage (TEXT) - где лежит файл: local или s3
  • file_name (TEXT) - имя файла в хранилище
  • size (INTEGER) - размер файла в байтах
  • created_at (DATETIME) - время создания

Таблица transcribe_jobs

  • id (TEXT) - UUID задачи
  • state (TEXT) - состояние задачи
  • source (TEXT) - откуда пришла задача: api, telegram или unknown
  • file_id (TEXT) - ссылка на текущий файл задачи
  • delay_time (DATETIME) - не брать задачу раньше этого времени
  • acquisition_id, acquire_time - захват задачи воркером
  • recognition_op_id (TEXT) - ID операции распознавания в Yandex Cloud
  • transcription_text (TEXT) - результат распознавания
  • is_error (BOOLEAN), error_text (TEXT) - признак и текст ошибки
  • tg_chat_id, tg_reply_message_id - куда отправить результат в Telegram
  • created_at, updated_at (DATETIME) - времена создания и обновления

Разработка

Миграции накатываются автоматически при старте сервиса — они вшиты в бинарник через //go:embed. Достаточно положить новый файл в migrations/.

Создать файл миграции и накатить или откатить её вручную:

# Создание новой миграции
goose -dir migrations create migration_name sql

# Применение миграций
goose -dir migrations sqlite3 data/transcriber.db up

# Откат миграций
goose -dir migrations sqlite3 data/transcriber.db down

Проверки перед коммитом:

go build ./...
go vet ./...
gofmt -l .
go test ./...
golangci-lint run