- пришедшего называет заголовок Remote-User от прокси, и верят ему только с адреса из перечня trusted_proxies; своего входа у сервиса не осталось — ни корня /auth, ни кук, ни срока сессии, ни секрета клиента в конфиге и в базе - учётная запись заводится первым обращением: EnsureUser в пакете хранилища, шаг схемы 202608220001 с колонкой provider_login и снятыми правилами users - cmd/oidcstub заменён на cmd/devtools с подкомандой proxy; заодно закрыт унаследованный DL3066 — пользователь образа назван числом
146 lines
8.0 KiB
Markdown
146 lines
8.0 KiB
Markdown
# Transcriber Service
|
|
|
|
Сервис расшифровки аудиозаписей. Вход один — HTTP API.
|
|
|
|
## Возможности
|
|
|
|
- Приём аудиофайлов через HTTP API
|
|
- Конвертация в ogg через ffmpeg
|
|
- Распознавание речи через Yandex SpeechKit
|
|
- Отслеживание статуса задач расшифровки
|
|
- Встроенная PocketBase для метаданных, файлов и панели владельца; метрики Prometheus
|
|
|
|
## Технологии
|
|
|
|
- **Язык**: Go 1.26, CGO не нужен
|
|
- **Веб-фреймворк**: gin-gonic/gin
|
|
- **Распознавание**: Yandex SpeechKit + Yandex Object Storage (S3)
|
|
- **Конвертация**: ffmpeg
|
|
- **Хранилище, файлы и панель**: встроенная PocketBase
|
|
- **База данных**: SQLite внутри PocketBase (через modernc.org/sqlite, CGO не нужен)
|
|
- **Метрики**: prometheus/client_golang
|
|
|
|
## Установка и запуск
|
|
|
|
1. Клонируйте репозиторий
|
|
2. Установите зависимости:
|
|
```bash
|
|
go mod tidy
|
|
```
|
|
3. Скопируйте образец конфига и заполните его:
|
|
```bash
|
|
cp config.example.toml config.toml
|
|
```
|
|
4. Запустите приложение:
|
|
```bash
|
|
go run ./cmd/transcriber -c config.toml
|
|
```
|
|
|
|
Сервер запустится на порту из `[server] port`, по умолчанию 8080. Нужен
|
|
установленный `ffmpeg`.
|
|
|
|
### Кого пускают
|
|
|
|
Кто пришёл, сервис узнаёт из заголовка `Remote-User`, который ставит обратный
|
|
прокси, сходив к Authelia; своего входа у сервиса нет. Кому верить, задаёт
|
|
перечень доверенных адресов в секции `[auth]`. Подробности —
|
|
[docs/security.md](docs/security.md), «Что разграничивает доступ»; известные
|
|
прорехи образца конфига — [docs/conventions/config.md](docs/conventions/config.md).
|
|
|
|
Локально прокси нет, а браузер заголовков не ставит — на место контура встаёт
|
|
подставной прокси из оснастки:
|
|
|
|
```bash
|
|
go run ./cmd/devtools proxy
|
|
```
|
|
|
|
Приложение после этого открывают **по адресу прокси** — `http://localhost:9000`.
|
|
В перечне доверенных адресов при этом должен стоять петлевой; строки под это
|
|
стоят в `config.example.toml`.
|
|
|
|
## Деплой
|
|
|
|
Деплой запускается из `pet-project-server`:
|
|
|
|
```bash
|
|
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/me` — кто пришёл, `GET /app/config` — пределы,
|
|
которые сервис объявляет приложению. Отдельными адресами стоят `GET /metrics` —
|
|
метрики Prometheus с префиксом `transcriber_` — и `GET /health` — проверка
|
|
живости. Своего входа у сервиса нет: кто пришёл, называет заголовок обратного
|
|
прокси ([access](openspec/specs/access/spec.md)). Сверх этого тем же портом
|
|
отдаётся собственная поверхность встроенного хранилища и панель `/_/` —
|
|
[docs/security.md](docs/security.md), «Из чего строятся пути и ключи».
|
|
|
|
Контракт приёма и опроса нормативен и живёт в
|
|
[openspec/specs/intake/spec.md](openspec/specs/intake/spec.md): поля запроса и
|
|
ответа, коды и условия. Менять его — необратимое действие
|
|
([CLAUDE.md](CLAUDE.md), «Работа»), и второго описания у него быть не должно.
|
|
|
|
## Состояния задач
|
|
|
|
Перечень состояний, переходы между ними и число воркеров —
|
|
[docs/database.md](docs/database.md), разделы «Коллекции» и «Представление
|
|
данных»; как сложен конвейер целиком — [docs/architecture.md](docs/architecture.md).
|
|
|
|
## Структура проекта
|
|
|
|
```
|
|
transcriber/
|
|
├── cmd/
|
|
│ ├── transcriber/ # Точка входа сервиса: конфиг, миграции, сборка зависимостей, запуск
|
|
│ └── devtools/ # Оснастка разработчика: подставной прокси для локального входа
|
|
├── internal/
|
|
│ ├── entity/ # Модели: задача, файл, результат распознавания
|
|
│ ├── contract/ # Интерфейсы адаптеров и репозиториев, типы ошибок
|
|
│ ├── config/ # Разбор config.toml
|
|
│ ├── metrics/ # Метрики Prometheus
|
|
│ ├── service/ # Конвейер расшифровки
|
|
│ ├── controller/
|
|
│ │ ├── http/ # HTTP-обработчики
|
|
│ │ └── worker/ # Фоновые воркеры
|
|
│ └── adapter/
|
|
│ ├── converter/ffmpeg/ # Конвертация аудио
|
|
│ ├── metaviewer/ffmpeg/ # Длительность аудио
|
|
│ ├── recognizer/yandex/ # SpeechKit + Object Storage
|
|
│ └── repo/pocketbase/ # Репозитории, схема коллекций, правила панели
|
|
└── data/ # Каталог данных: база и файлы записей вместе
|
|
├── data.db # База хранилища (создаётся автоматически)
|
|
└── storage/ # Файлы записей в раскладке хранилища
|
|
```
|
|
|
|
## Хранилище
|
|
|
|
Коллекции хранилища — аудиозапись и её приложения. Поля, ключи, правило времени и
|
|
идентификаторов, а также механика захвата задачи воркером —
|
|
[docs/database.md](docs/database.md). Панель владельца — по адресу `/_/` того же
|
|
порта; пароль от неё задаёт сам владелец по приглашению, которое сервис печатает
|
|
в журнал при первом запуске.
|
|
|
|
## Разработка
|
|
|
|
Схему двигают шаги миграций PocketBase на Go —
|
|
`internal/adapter/repo/pocketbase/migrations`, файл на шаг. Непринятые шаги
|
|
накатываются при подъёме хранилища, прежде чем стартуют воркеры и сервер.
|
|
Применённый шаг не переписывается: изменение — только новым файлом шага.
|
|
|
|
Проверки перед коммитом — одной командой:
|
|
|
|
```bash
|
|
task gate
|
|
```
|
|
|
|
Что она гоняет, чем краснеет и какой отказ считается объявленным долгом —
|
|
[CLAUDE.md](CLAUDE.md), раздел «Гейт».
|