Синхронизация с server/: нормализация видео, овал-подсказка, хосты с путём, DNR-стенд

- app.py: probe_video(), HDR→bt709, fps=30, -t 20, логирование progress/face_ok,
  split_host_path() для хостов с путём (domain.com/v1/giga), FPG_WS_PORT
- templates/index.html: овал-подсказка, canvas 1080×1080, запас 10%
- templates/result.html: стилевые правки (цвета)
- gigadoc_ws.py: поддержка пути в --sdk-host
- test_fpg.py: переведён на DNR-стенд (bearer subprotocol, Origin)
- README: хосты с путём, FPG_WS_PORT, нормализация
- .gitignore: server/, wordpress/, wordpress-plugin/ (отдельные репозитории)
This commit is contained in:
apuc committed 2026-09-17 15:35:10 +03:00
1 parent 421183b7e3
commit 7375618b1d
9 files changed
+423 -108

No files matched your search

+62 -22
View File
@@ -1,4 +1,4 @@
# Диагностика по видео (ФПГ GigaDoc)
# Med Diagnostics — API-сервер (ФПГ GigaDoc)
Веб-приложение: пользователь загружает или записывает видео с лицом → система извлекает кадры → отправляет в SDK ФПГ (GigaDoc) → показывает понятный диагноз с сохранением в SQLite, share-ссылками, экспортом PDF/DOCX и скачиванием записанного видео.
@@ -15,16 +15,34 @@
| reportlab | 5.0.1 (PDF-экспорт, кириллица через DejaVu) |
| python-docx | 1.2.0 (DOCX-экспорт) |
Установка зависимостей (на сервере venv могут быть сломаны — ставится через `pip install --user`):
## Быстрый запуск (локально)
```bash
pip install --user flask waitress websockets requests reportlab python-docx
# 1. Клонировать
git clone https://git.itguild.info/apuc/sber-med-server.git med-server
cd med-server
# 2. Зависимости (рекомендуется venv)
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# 3. Шрифты DejaVu для кириллицы в PDF (обычно уже есть в системе)
sudo apt install -y fonts-dejavu
# 4. Секреты SDK ФПГ (обязательно!)
export FPG_CLIENT_ID=client_fpg_front_dnr
export FPG_CLIENT_SECRET=ВАШ_СЕКРЕТ
# 5. Запуск (dev-режим, порт 5000)
python3 app.py
# или через waitress (как на проде):
python3 -c "from waitress import serve; from app import app; serve(app, host='127.0.0.1', port=18018, threads=8)"
```
Шрифты DejaVu для кириллицы в PDF (обычно уже есть в системе):
```bash
apt list --installed 2>/dev/null | grep fonts-dejavu || sudo apt install -y fonts-dejavu
```
Приложение само создаёт при старте:
- `videos/` — сохранённые записи сканирования (рядом с app.py)
- `results.db` — SQLite с результатами (share_id начиная с 10005)
## Переменные окружения (секреты!)
@@ -32,24 +50,28 @@ apt list --installed 2>/dev/null | grep fonts-dejavu || sudo apt install -y font
| Переменная | Описание |
|---|---|
| `FPG_CLIENT_ID` | client_id для OAuth SDK ФПГ (по умолчанию `client_fpg_front`) |
| `FPG_CLIENT_ID` | client_id для OAuth SDK ФПГ (по умолчанию `client_fpg_front_dnr` — персональный стенд) |
| `FPG_CLIENT_SECRET` | client_secret для OAuth SDK ФПГ (**обязательна**, без неё авторизация не работает) |
| `CORS_ORIGINS` | (необязательно) список разрешённых Origin для CORS через запятую, например `https://site1.ru,https://site2.ru`. По умолчанию `*` |
| `FPG_OAUTH_URL` | (необязательно) URL OAuth-токена (по умолчанию `https://oauth.sbermed.ai/token`) |
| `FPG_REST_HOST` | (необязательно) REST-хост SDK (по умолчанию `gigadoc-dnr-sdk.sbermed.ai` — персональный стенд) |
| `FPG_WS_HOST` | (необязательно) WebSocket-хост SDK (по умолчанию `gigadoc-dnr-sdk.sbermed.ai`) |
| `FPG_WS_PORT` | (необязательно) WebSocket-порт SDK (по умолчанию `8443`) |
| `FPG_WS_ORIGIN` | (необязательно) Origin для WebSocket (по умолчанию `https://gigadoc-dnr-sdk.sbermed.ai`) |
## Развёртывание
**Хосты с путём.** `FPG_REST_HOST` и `FPG_WS_HOST` могут содержать не только домен, но и путь — например `domain.com/v1/giga` (или полностью `https://domain.com/v1/giga`). Путь автоматически подставляется в REST-базу и в WebSocket-URI (`wss://domain.com:8443/v1/giga/api/v2/ws/predict/...`).
## Развёртывание на сервере
### 1. Клонирование и структура
```bash
sudo mkdir -p /opt/med && sudo chown $USER:$USER /opt/med
git clone https://git.itguild.info/apuc/sber_med.git /opt/med
git clone https://git.itguild.info/apuc/sber-med-server.git /opt/med
cd /opt/med
mkdir -p templates static videos
```
Приложение само создаёт при старте:
- `videos/` — сохранённые записи сканирования (рядом с app.py)
- `results.db` — SQLite с результатами (share_id начиная с 10005)
### 2. Systemd-сервис
`/etc/systemd/system/med.service`:
@@ -64,9 +86,9 @@ Type=simple
User=apuc
WorkingDirectory=/opt/med
Environment=PYTHONUNBUFFERED=1
Environment=FPG_CLIENT_ID=client_fpg_front
Environment=FPG_CLIENT_ID=client_fpg_front_dnr
Environment=FPG_CLIENT_SECRET=ВАШ_СЕКРЕТ
ExecStart=/usr/bin/python3 -c "from waitress import serve; from app import app; serve(app, host='127.0.0.1', port=8063, threads=8)"
ExecStart=/usr/bin/python3 -c "from waitress import serve; from app import app; serve(app, host='127.0.0.1', port=18018, threads=8)"
Restart=always
RestartSec=5
@@ -91,7 +113,7 @@ server {
client_max_body_size 100M; # видео до 100 МБ
location / {
proxy_pass http://127.0.0.1:8063;
proxy_pass http://127.0.0.1:18018;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -133,14 +155,32 @@ sudo systemctl restart med.service
## Как работает анализ
1. Видео сохраняется в `videos/` (копия записи — доступна для скачивания)
2. `ffmpeg` извлекает 300 кадров 1280×720 (bt709 + yuv420p — важно для iPhone MOV с P3/HDR)
3. OAuth-токен → создание сессии → кадры по WebSocket (`wss://gigadoc-sdk.sbermed.ai:8443`, subprotocol `bearer.<token>`, Origin `https://gigadoc.sbermed.ai`)
2. `ffmpeg` извлекает до 300 кадров 1280×720 (первые 20 секунд, fps=30) с нормализацией: HDR→bt709 (iPhone P3/HDR), поворот по метаданным, yuv420p
3. OAuth-токен → создание сессии → кадры по WebSocket (`wss://gigadoc-dnr-sdk.sbermed.ai:8443`, subprotocol `bearer.<token>`, Origin `https://gigadoc-dnr-sdk.sbermed.ai`)
4. Интерпретация JSON SDK → summary/metrics/warnings/advice → сохранение в SQLite
## Важные нюансы
- **SDK ФПГ не находит лицо на кадрах 640×480** — нужны кадры 1280×720.
- **Камерное сканирование** (мобильные): canvas 720×720 (квадрат, без обрезки головы), MediaRecorder с битрейтом 1.5 Мбит/с (~1–2 МБ за 310 кадров), автоповтор fetch до 3 попыток при обрыве сети.
- **Камерное сканирование** (мобильные): canvas 1080×1080 (квадрат), овал-подсказка для позиционирования лица, запас 10% при захвате (голова не обрезается), MediaRecorder с битрейтом 1.5 Мбит/с (~1–2 МБ за 310 кадров), автоповтор fetch до 3 попыток при обрыве сети.
- **Логирование прогресса SDK**: в логах сервера пишется `progress` и `face_ok` при каждом изменении; если финальный результат не пришёл — предупреждение в лог.
- **iOS MediaRecorder** пишет mp4 (webm может не поддерживаться) — расширение выбирается из `blob.type`.
- **Порт 5000** на сервере занят другим сервисом — приложение слушает 8063.
- Дисклеймер «не медицинский диагноз» — во всех отчётах и на страницах.
- **Порт 5000** на сервере занят другим сервисом — приложение слушает 18018.
- Дисклеймер «не медицинский диагноз» — во всех отчётах и на страницах.
## Структура
```
server/
├── app.py — Flask-приложение (маршруты, CORS, анализ)
├── storage.py — SQLite (share_id, результаты)
├── export.py — PDF/DOCX-экспорт
├── interpret.py — интерпретация JSON SDK → понятный результат
├── fpg_stream.py — утилита: потоковая отправка кадров в SDK
├── fpg_connect.py — утилита: проверка подключения к SDK
├── gigadoc_ws.py — утилита: низкоуровневый WebSocket-клиент SDK (нужен aiohttp)
├── test_fpg.py — тестовая отправка кадров
├── templates/ — index.html, result.html
├── static/ — og-image.png
└── requirements.txt
```