Инструкции для Claude, конфиг линтера, актуализация README

CLAUDE.md описывает конвейер задач, подвохи конфига и правило про четыре
списка колонок в репозитории sqlite.

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

README приведён к коду: эндпоинты /api/audio и /api/status/:id, состояния
задач, структура internal/, фактические колонки таблиц.
This commit is contained in:
av
2026-08-10 20:24:30 +03:00
parent 7f5c5a27e0
commit a4646c0930
3 changed files with 226 additions and 44 deletions
+101 -44
View File
@@ -1,22 +1,26 @@
# Transcriber Service
Сервис для расшифровки аудиозаписей с REST API.
Сервис расшифровки аудиозаписей. Два входа — Telegram-бот и HTTP API.
## Возможности
- Загрузка аудиофайлов любого формата
- Автоматическая генерация UUID для файлов
- Сохранение файлов на диск
- Приём аудио из Telegram: голосовые сообщения, аудиофайлы и документы с аудио
- Приём аудиофайлов через HTTP API
- Конвертация в ogg через ffmpeg
- Распознавание речи через Yandex SpeechKit
- Отслеживание статуса задач расшифровки
- SQLite база данных для хранения метаданных
- 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
- **UUID**: google/uuid
- **Метрики**: prometheus/client_golang
## Установка и запуск
@@ -25,12 +29,30 @@
```bash
go mod tidy
```
3. Запустите приложение:
3. Скопируйте образец конфига и заполните его:
```bash
go run main.go
cp config.dist.toml config.toml
```
4. Запустите приложение:
```bash
go run . -c config.toml
```
Сервер запустится на порту 8080.
Сервер запустится на порту из `[server] port`, по умолчанию 8080. Нужен
установленный `ffmpeg`.
### Белый список Telegram
Бот отвечает только тем, кто перечислен в `[server] users_while_list`. В
`config.dist.toml` этого ключа нет — добавьте его сами:
```toml
[server]
users_while_list = ["@username"]
```
Значения сверяются со строкой автора сообщения из Telegram (`@username` либо имя
с фамилией), а не с числовым id.
## Деплой
@@ -46,9 +68,9 @@ inv pl -- transcriber
## API Endpoints
### POST /api/transcribe
### POST /api/audio
Загружает аудиофайл и создает задачу на расшифровку.
Загружает аудиофайл и создает задачу на расшифровку. Отвечает `201 Created`.
**Параметры:**
- `audio` (form-data) - аудиофайл для расшифровки
@@ -56,7 +78,7 @@ inv pl -- transcriber
**Пример запроса:**
```bash
curl -X POST \
http://localhost:8080/api/transcribe \
http://localhost:8080/api/audio \
-F "audio=@/path/to/your/audio.mp3"
```
@@ -64,31 +86,34 @@ curl -X POST \
```json
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"file_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"status": "pending"
"status": "created"
}
```
### GET /api/transcribe/:id
### GET /api/status/:id
Получает статус задачи расшифровки по ID.
Получает статус задачи расшифровки по ID. Поле `transcription_text` появляется,
когда задача перешла в `done`.
**Пример запроса:**
```bash
curl http://localhost:8080/api/transcribe/550e8400-e29b-41d4-a716-446655440000
curl http://localhost:8080/api/status/550e8400-e29b-41d4-a716-446655440000
```
**Ответ:**
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"file_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "done",
"created_at": "2024-01-01T12:00:00Z",
"updated_at": "2024-01-01T12:00:00Z"
"transcription_text": "расшифрованный текст"
}
```
### GET /metrics
Метрики Prometheus с префиксом `transcriber_`.
### GET /health
Проверка работоспособности сервиса.
@@ -101,51 +126,72 @@ curl http://localhost:8080/api/transcribe/550e8400-e29b-41d4-a716-446655440000
}
```
## Статусы задач
## Состояния задач
- `pending` - задача создана, ожидает обработки
- `processing` - задача выполняется
- `completed` - задача завершена успешно
- `created` - задача создана, файл сохранён, ждёт конвертации
- `converted` - файл сконвертирован в ogg, ждёт отправки на распознавание
- `transcribe` - распознавание запущено в Yandex SpeechKit, ждём результата
- `done` - задача завершена успешно
- `failed` - задача завершена с ошибкой
Задачи двигают три фоновых воркера: `conversion_worker`, `transcribe_worker` и
`check_worker`. Каждый опрашивает базу раз в секунду и делает один шаг.
## Структура проекта
```
transcriber/
├── main.go # Точка входа приложения
├── go.mod # Зависимости Go
├── models/
── models.go # Модели данных
├── database/
── database.go # Слой работы с БД
├── handlers/
── transcribe.go # HTTP обработчики
├── migrations/
├── 001_create_files_table.sql
└── 002_create_transcribe_jobs_table.sql
├── 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/ # Директория для сохранения файлов
└── transcriber.db # SQLite база данных (создается автоматически)
```
## База данных
### Таблица `files`
- `id` (TEXT) - UUID файла
- `type` (TEXT) - MIME-тип файла
- `storage` (TEXT) - где лежит файл: `local` или `s3`
- `file_name` (TEXT) - имя файла в хранилище
- `size` (INTEGER) - размер файла в байтах
- `created_at` (DATETIME) - время создания
### Таблица `transcribe_jobs`
- `id` (TEXT) - UUID задачи
- `status` (TEXT) - статус задачи
- `file_id` (TEXT) - ссылка на файл
- `created_at` (DATETIME) - время создания
- `updated_at` (DATETIME) - время последнего обновления
- `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) - времена создания и обновления
## Разработка
Для добавления новых миграций используйте goose:
Миграции накатываются автоматически при старте сервиса — они вшиты в бинарник
через `//go:embed`. Достаточно положить новый файл в `migrations/`.
Создать файл миграции и накатить или откатить её вручную:
```bash
# Создание новой миграции
@@ -156,3 +202,14 @@ goose -dir migrations sqlite3 data/transcriber.db up
# Откат миграций
goose -dir migrations sqlite3 data/transcriber.db down
```
Проверки перед коммитом:
```bash
go build ./...
go vet ./...
gofmt -l .
go test ./...
golangci-lint run
```