apuc 5331730433 Поддержка хостов с путём (domain.com/v1/giga) в конфигурации
- split_host_path(): разделяет host/path на (scheme, hostname, base_path),
  поддерживает варианты без схемы и с ней
- REST_BASE собирается с учётом пути
- WS: hostname и base_path разделяются, WS_PATH_TEMPLATE включает base_path
- FPG_WS_PORT теперь настраивается через env (было захардкожено 8443)
- fpg_connect.py: варианты URI переписаны на WS_HOSTNAME/WS_BASE_PATH
2026-09-17 15:22:06 +03:00

Med Diagnostics — API-сервер (ФПГ GigaDoc)

Веб-приложение: пользователь загружает или записывает видео с лицом → система извлекает кадры → отправляет в SDK ФПГ (GigaDoc) → показывает понятный диагноз с сохранением в SQLite, share-ссылками, экспортом PDF/DOCX и скачиванием записанного видео.

Требования (проверено на сервере)

Компонент Версия
Python 3.10.10
ffmpeg 4.2.7 (нужен для извлечения кадров)
Flask 3.1.1
waitress 3.0.2
websockets 10.4 (важно: API extra_headers/origin появился в 10.x)
requests 2.28.2
reportlab 5.0.1 (PDF-экспорт, кириллица через DejaVu)
python-docx 1.2.0 (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)"

Приложение само создаёт при старте:

  • videos/ — сохранённые записи сканирования (рядом с app.py)
  • results.db — SQLite с результатами (share_id начиная с 10005)

Переменные окружения (секреты!)

Секреты не хранятся в репозитории — задаются через окружение:

Переменная Описание
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_ORIGIN (необязательно) Origin для WebSocket (по умолчанию https://gigadoc-dnr-sdk.sbermed.ai)

Развёртывание на сервере

1. Клонирование и структура

sudo mkdir -p /opt/med && sudo chown $USER:$USER /opt/med
git clone https://git.itguild.info/apuc/sber-med-server.git /opt/med
cd /opt/med
mkdir -p templates static videos

2. Systemd-сервис

/etc/systemd/system/med.service:

[Unit]
Description=Med Diagnostics (FPG GigaDoc)
After=network.target

[Service]
Type=simple
User=apuc
WorkingDirectory=/opt/med
Environment=PYTHONUNBUFFERED=1
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=18018, threads=8)"
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now med.service
sudo systemctl status med.service

3. Nginx (HTTPS)

/etc/nginx/sites-enabled/med.my-dpr.ru:

server {
    server_name med.my-dpr.ru;

    client_max_body_size 100M;   # видео до 100 МБ

    location / {
        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;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 60s;
        client_body_timeout 300s;   # важно: мобильная сеть может загружать медленно
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/med.my-dpr.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/med.my-dpr.ru/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

Сертификат: sudo certbot --nginx -d med.my-dpr.ru

4. Обновление кода

cd /opt/med && git pull
sudo systemctl restart med.service

Маршруты

Маршрут Описание
/ Главная: загрузка файла или сканирование с камеры
/analyze (POST) Принимает video (mp4/avi/mov/mkv/webm/m4v), возвращает диагноз + share_id/share_url/video_url
/r/<share_id> Публичная страница результата (с OG-тегами)
/download/<share_id>/pdf Экспорт в PDF
/download/<share_id>/docx Экспорт в DOCX
/download/<video_id>/video Скачивание записанного видео (есть даже при ошибке анализа)

Как работает анализ

  1. Видео сохраняется в videos/ (копия записи — доступна для скачивания)
  2. ffmpeg извлекает 300 кадров 1280×720 (bt709 + yuv420p — важно для iPhone MOV с P3/HDR)
  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 попыток при обрыве сети.
  • iOS MediaRecorder пишет mp4 (webm может не поддерживаться) — расширение выбирается из blob.type.
  • Порт 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
S
Description
API-сервер диагностики по видео (ФПГ GigaDoc): Flask + WebSocket SDK, экспорт PDF/DOCX, CORS
Readme
378 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 71.7%
HTML 28.3%