mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(docs-i18n): translate all documentation into 20 languages
All 181 docs markdown files translated into 20 languages (apps/docs/<locale>/**). Companion to the i18n code PR; admin-merged because the file count exceeds GitHub's per-PR CI trigger limit. Validated by pnpm i18n:check (all surfaces, 0 stale/missing) and a clean all-locale docs build.
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
---
|
||||
description: "Структура монорепозиторію, архітектура застосунків і пакетів, життєвий цикл запиту та споживання ресурсів SnapOtter."
|
||||
i18n_source_hash: 9e8f80499a37
|
||||
i18n_provenance: human
|
||||
i18n_output_hash: 6a1de194bb8b
|
||||
---
|
||||
|
||||
# Архітектура {#architecture}
|
||||
|
||||
SnapOtter є монорепозиторієм, що керується робочими просторами pnpm та Turborepo. Він розгортається як стек Docker Compose з 3 контейнерів: образ застосунку SnapOtter, PostgreSQL 17 і Redis 8.
|
||||
|
||||
## Структура проєкту {#project-structure}
|
||||
|
||||
```
|
||||
snapotter/
|
||||
├── apps/
|
||||
│ ├── api/ # Fastify backend
|
||||
│ ├── web/ # React + Vite frontend
|
||||
│ └── docs/ # This VitePress site
|
||||
├── packages/
|
||||
│ ├── image-engine/ # Sharp-based image operations
|
||||
│ ├── media-engine/ # FFmpeg spawn + progress parsing
|
||||
│ ├── doc-engine/ # qpdf, LibreOffice, ghostscript wrappers
|
||||
│ ├── ai/ # Python AI model bridge
|
||||
│ └── shared/ # Types, constants, i18n
|
||||
└── docker/ # Dockerfile and Compose config
|
||||
```
|
||||
|
||||
## Пакети {#packages}
|
||||
|
||||
### `@snapotter/image-engine` {#snapotter-image-engine}
|
||||
|
||||
Основна бібліотека обробки зображень, побудована на [Sharp](https://sharp.pixelplumbing.com/). Вона обробляє всі не-AI операції: зміну розміру, обрізку, обертання, віддзеркалення, конвертацію, стиснення, видалення метаданих та коригування кольорів (яскравість, контраст, насиченість, відтінки сірого, сепія, інверсія, канали кольору).
|
||||
|
||||
Цей пакет не має мережевих залежностей і працює повністю в процесі.
|
||||
|
||||
### `@snapotter/ai` {#snapotter-ai}
|
||||
|
||||
Проміжний шар, який викликає скрипти Python для ML-операцій. Під час першого використання цей шар запускає стійкий процес-диспетчер Python, який заздалегідь імпортує важкі бібліотеки (PIL, NumPy, MediaPipe, rembg), тож наступні AI-виклики пропускають накладні витрати на імпорт. Якщо диспетчер ще не готовий, шар повертається до породження свіжого підпроцесу Python на кожен запит.
|
||||
|
||||
**Моделі не завантажуються заздалегідь.** Скрипт кожного інструмента завантажує ваги своєї моделі з диска під час запиту і відкидає їх після завершення запиту. Дивіться [Споживання ресурсів](#resource-footprint) для повного профілю пам'яті.
|
||||
|
||||
Підтримувані операції: видалення фону (rembg/BiRefNet), збільшення роздільності (RealESRGAN), розмиття облич (MediaPipe), покращення облич (GFPGAN/CodeFormer), видалення об'єктів (LaMa ONNX), OCR (PaddleOCR/Tesseract), розфарбовування (DDColor), видалення шуму, видалення ефекту червоних очей, відновлення фото, генерація фото на паспорт, виправлення прозорості (BiRefNet HR-matting) та зміна розміру з урахуванням вмісту (двійковий файл Go caire).
|
||||
|
||||
Скрипти Python розташовані в `packages/ai/python/`. Образ Docker заздалегідь завантажує всі ваги моделей під час збірки, тож контейнер працює повністю офлайн.
|
||||
|
||||
### `@snapotter/shared` {#snapotter-shared}
|
||||
|
||||
Спільні типи TypeScript, константи (як-от `APP_VERSION` та визначення інструментів) і рядки перекладів i18n, які використовуються і фронтендом, і бекендом.
|
||||
|
||||
## Застосунки {#applications}
|
||||
|
||||
### API (`apps/api`) {#api-apps-api}
|
||||
|
||||
Сервер Fastify v5, що надає 241 маршрут інструментів у п'яти модальностях (image, video, audio, PDF, file) і обробляє:
|
||||
- Завантаження файлів, керування тимчасовим робочим простором та постійне зберігання файлів
|
||||
- Бібліотеку файлів користувача з ланцюжками версій (таблиця `user_files`) - кожен оброблений результат посилається назад на свій вихідний файл і фіксує, який інструмент було застосовано, з автоматично згенерованими мініатюрами для сторінки Files
|
||||
- Виконання інструментів (маршрутизує кожен запит інструмента до рушія зображень або мосту AI)
|
||||
- Оркестрацію конвеєрів (послідовне поєднання кількох інструментів)
|
||||
- Пакетну обробку з контролем паралельності через черги завдань BullMQ (пули: image, media, ai, docs, system)
|
||||
- Автентифікацію користувачів, RBAC (ролі admin/user з повним набором дозволів), керування ключами API та обмеження частоти запитів
|
||||
- Керування командами - CRUD лише для адміністраторів; користувачі призначаються до команди через поле `team` у своєму профілі
|
||||
- Налаштування середовища виконання - сховище «ключ-значення» в таблиці `settings`, яке керує `disabledTools`, `enableExperimentalTools`, `loginAttemptLimit` та іншими операційними важелями без повторного розгортання
|
||||
- Власний брендинг та налаштування середовища виконання через параметри, що зберігаються в базі даних
|
||||
- Документацію Scalar/OpenAPI за адресою `/api/docs`
|
||||
- Обслуговування зібраного фронтенду як SPA у продакшні
|
||||
|
||||
Ключові залежності: Fastify, Drizzle ORM (pg-core, node-postgres), Sharp, BullMQ, ioredis, Zod для валідації.
|
||||
|
||||
Сервер обробляє коректне завершення роботи за SIGTERM/SIGINT: він осушує HTTP-з'єднання, зупиняє воркери BullMQ, вимикає диспетчер Python і закриває з'єднання з базою даних.
|
||||
|
||||
### Web (`apps/web`) {#web-apps-web}
|
||||
|
||||
Односторінковий застосунок на React 19, зібраний за допомогою Vite. Використовує Zustand для керування станом, Tailwind CSS v4 для стилізації та Lucide для іконок. Взаємодіє з API через REST та SSE (для відстеження прогресу).
|
||||
|
||||
Сторінки включають робочий простір інструментів, сторінку Files для керування постійними завантаженнями та результатами, конструктор автоматизації/конвеєрів та панель адміністративних налаштувань.
|
||||
|
||||
Зібраний фронтенд обслуговується бекендом Fastify у продакшні, тож окремого вебсервера в контейнері Docker немає.
|
||||
|
||||
### Docs (`apps/docs`) {#docs-apps-docs}
|
||||
|
||||
Цей сайт VitePress. Розгортається на Cloudflare Pages автоматично під час відправлення в `main`.
|
||||
|
||||
## Як проходить запит {#how-a-request-flows}
|
||||
|
||||
1. Користувач обирає інструмент у вебінтерфейсі та завантажує файл.
|
||||
2. Фронтенд надсилає multipart POST на `/api/v1/tools/:section/:toolId` з файлом і налаштуваннями.
|
||||
3. Маршрут API валідує вхідні дані за допомогою Zod, а потім розподіляє обробку.
|
||||
4. Для стандартних інструментів завдання ставиться в чергу до відповідного пулу BullMQ (image, media або docs залежно від модальності). Воркер BullMQ у процесі автоматично орієнтує зображення на основі метаданих EXIF, виконує функцію обробки інструмента й повертає результат.
|
||||
5. Для AI-інструментів міст TypeScript надсилає запит до стійкого диспетчера Python (або породжує свіжий підпроцес як запасний варіант), чекає його завершення та зчитує вихідний файл.
|
||||
6. Прогрес завдання зберігається в таблиці `jobs` у PostgreSQL, тож стан переживає перезапуски контейнера. Оновлення в реальному часі доставляються через SSE за адресою `/api/v1/jobs/:jobId/progress`.
|
||||
7. API повертає `jobId` та `downloadUrl`. Користувач завантажує оброблений файл з `/api/v1/download/:jobId/:filename`.
|
||||
|
||||
Для конвеєрів API подає вихід кожного кроку як вхід для наступного, виконуючи їх послідовно.
|
||||
|
||||
Для пакетної обробки API використовує потоки BullMQ з дочірніми завданнями для кожного кроку й повертає ZIP-файл з усіма обробленими файлами.
|
||||
|
||||
## Споживання ресурсів {#resource-footprint}
|
||||
|
||||
SnapOtter розроблений для низького споживання пам'яті в стані спокою. Нічого не завантажується заздалегідь і не тримається «розігрітим» під час запуску.
|
||||
|
||||
### У стані спокою {#at-idle}
|
||||
|
||||
Процес Node.js/Fastify, PostgreSQL і Redis працюють. Типове споживання RAM у стані спокою становить **~200-300 МБ** для всіх трьох контейнерів (процес Node.js, Postgres і Redis). Жодного процесу Python, жодних ваг моделей у пам'яті.
|
||||
|
||||
### Що запускається і коли {#what-starts-and-when}
|
||||
|
||||
| Компонент | Запускається коли | Пам'ять під час роботи |
|
||||
|-----------|-------------|---------------------|
|
||||
| Сервер Fastify + Postgres + Redis | Запуск контейнера | ~200-300 МБ загалом |
|
||||
| Воркери BullMQ | Запуск контейнера (у процесі) | Один воркер на пул (image, media, ai, docs, system) |
|
||||
| Диспетчер Python | Перший запит AI-інструмента | Інтерпретатор Python + заздалегідь імпортовані бібліотеки (PIL, NumPy, MediaPipe, rembg) - без ваг моделей |
|
||||
| Ваги моделей AI | Під час запиту конкретного інструмента | Завантажуються з диска, звільняються після завершення запиту |
|
||||
|
||||
### Завантаження моделей {#model-loading}
|
||||
|
||||
Усі файли ваг моделей (загалом кілька ГБ) весь час лежать на диску в `/opt/models/`. Скрипт кожного AI-інструмента завантажує в пам'ять лише свою модель (моделі) на час запиту, а потім звільняє їх. Деякі скрипти явно викликають `del model` і `torch.cuda.empty_cache()` після виведення, щоб пам'ять повернулася негайно.
|
||||
|
||||
Кешу моделей між запитами немає. Виконання того самого AI-інструмента підряд щоразу перезавантажує модель. Це утримує споживання пам'яті в стані спокою близьким до нуля ціною затримки на завантаження моделі під час кожного AI-запиту.
|
||||
|
||||
### Холодний старт першого AI-запиту {#first-ai-request-cold-start}
|
||||
|
||||
Диспетчер Python не працює під час запуску контейнера. Перший AI-запит запускає паралельно дві речі: диспетчер починає розігріватися у фоні, а сам запит повертається до одноразового породження підпроцесу Python. Щойно диспетчер сигналізує про готовність, усі наступні AI-запити використовують його безпосередньо й пропускають витрати на породження підпроцесу.
|
||||
Reference in New Issue
Block a user