Skip to content

Repository files navigation

Спецификация сервиса Mapvideo

Если хотите протестировать сервис, обратитесь в Telegram: @Requestin

Обзор продукта

Mapvideo — веб-сервис для редакции телеканала. Позволяет создавать анимированные карты для новостных сюжетов в прямом эфире. Пользователь настраивает карту с точками, маршрутами и анимациями в браузере, затем скачивает готовый MP4/MXF файл.


Пользователи и авторизация

Роли

  • admin — единственный администратор. Доступ к /admin панели.
  • user — обычный пользователь редакции.

Страница логина (/login)

  • Поля: логин, пароль
  • Логотип и название "Mapvideo" на странице
  • После успешного логина → редирект на /
  • Любая страница без авторизации → редирект на /login
  • Сессия запоминается автоматически (httpOnly cookie session, срок 30 дней)
  • Защита от CSRF: double-submit cookie (csrf_token cookie, не httpOnly) + заголовок X-CSRF-Token на мутирующих запросах
  • GET /api/auth/csrf нужен только чтобы гарантировать наличие csrf_token cookie; источник токена — cookie, а не response body
  • Rate limit на POST /api/auth/login: 5 неудачных попыток с одного IP за 10 минут → 429
  • Пароли хранятся в БД в хэшированном виде (bcrypt, 12 раундов)

Страница администратора (/admin)

  • Доступна только пользователю admin
  • Список всех пользователей: имя, дата регистрации
  • Добавить пользователя (форма: логин + пароль)
  • Удалить пользователя (с подтверждением)

Главная страница — редактор карты (/)

Компоновка

┌──────────────────────────────────────────────────┐
│                         [Имя пользователя ▼]     │  ← шапка 48px
├────────────────────────────────────┬─────────────┤
│                                    │             │
│   ПРЕВЬЮ КАРТЫ 16:9 (строго)       │   ПРАВАЯ    │
│   (MapLibre подложка               │   БОКОВАЯ   │
│    + PixiJS анимации поверх)       │   ПАНЕЛЬ    │
│                                    │   320px     │
│   [⌂] кнопка сброса положения      │             │
│       (правый нижний угол превью)  │             │
├────────────────────────────────────┴─────────────┤
│ [+ Точка] [↗ Маршрут*] [⚙ Видео] [💾 Сохранить] │  ← нижняя панель 56px
└──────────────────────────────────────────────────┘
* кнопка "Маршрут" только при 2+ точках на карте

Слева поверх карты — список элементов (200px, полупрозрачный). Правая боковая панель — открывается при двойном клике на элемент.

Превью карты

  • Соотношение сторон строго 16:9
  • Пользователь видит в превью ровно то что будет на видео (строгое условие!)
  • Все анимации живые постоянно (точки пульсируют, иконки движутся)
  • Иконки на маршрутах зацикливаются (доехал до конца — начинает заново)
  • Тема карты меняется сразу при изменении в настройках видео
  • Кнопка "Сбросить положение" возвращает карту к охвату всех точек

Меню пользователя (выпадающее)

Кнопка с именем пользователя в шапке справа:

  1. Тех. поддержка → модал: "Напишите в Telegram: @Requestin"
  2. Моя история → боковая панель с историей видео
  3. Выйти → разлогин + редирект на /login

Элементы карты

Точка

Добавление

  1. Кнопка "Добавить точку"
  2. Модальное окно: текстбокс + геосаджест (Photon через backend proxy на публичный сервис)
  3. Геосаджест помогает, но пользователь редактирует текст сам
  4. "Продолжить" → карта перемещается к точке, появляется точка + подпись
  5. При наличии других точек — карта автомасштабируется под все точки

Взаимодействие

  • Перетаскивание точки и подписи независимо друг от друга
  • Двойной клик → меню настроек в правой панели
  • Клик вне меню → меню закрывается

Настройки точки (правая панель)

Анимация (radio): Мигающая точка | Взрыв | Огонь | Землетрясение

Мигающая точка (процедурная, без готового ассета):

  • Цвет, размер, прозрачность, скорость пульсации
  • Окантовка: вкл/выкл, цвет, размер, прозрачность

Взрыв (PNG иконка + процедурные круги):

  • Размер иконки, прозрачность, скорость кругов
  • Круги расходятся непрерывно весь ролик

Огонь (PNG секвенция 150 кадров, зациклена):

  • Размер, прозрачность, скорость воспроизведения

Землетрясение (PNG иконка, статично):

  • Размер, прозрачность

Кнопки: Сбросить настройки | Сбросить местоположение | Удалить (с подтверждением) При удалении точки — удаляются все связанные маршруты.


Подпись точки

Поведение

  • Появляется автоматически при добавлении точки
  • Текст по умолчанию — название из геокодера
  • Перетаскивается независимо от точки

Настройки подписи (правая панель)

  • Шрифт (выпадающий список из файлов assets/fonts/), размер, цвет, прозрачность
  • Окантовка: цвет, размер, прозрачность
  • Галочка "До запятой" — показывает текст до первой запятой
  • Галочка "Только заглавные" — переводит в верхний регистр

Кнопки: Сбросить настройки | Сбросить местоположение | Удалить (с подтверждением)


Маршрут

Добавление

  • Кнопка "Маршрут" появляется при 2+ точках
  • Клик на начальную точку → от неё тянется линия за курсором
  • Escape — отменить построение
  • Клик на другую отмеченную точку → маршрут между точками
  • Клик на произвольное место → маршрут заканчивается стрелкой (без иконки)
  • При перемещении точки — маршрут перестраивается автоматически
  • Несколько маршрутов могут пересекаться (поздний рисуется поверх)

Настройки маршрута (правая панель)

Вид: Прямая (пульсирующая) | Пунктирная (движение пунктира А→Б циклично) Параметры линии: цвет, толщина, прозрачность, окантовка (цвет/размер/прозрачность) Стрелка (если конец в произвольной точке): масштабируется с толщиной линии

Иконка (только для маршрутов между отмеченными точками): Нет | Автомобиль | Самолёт | Вертолёт | Корабль

  • Иконка движется А→Б один раз за длительность видео
  • Иконка поворачивается по направлению движения
  • Иконка располагается чуть выше линии маршрута
  • На каждом маршруте своя иконка

Автомобиль: галочка "Маршрут по дороге" → строит через OSRM Самолёт/Вертолёт/Корабль: переключатель Прямая | Дуга (горизонтальная кривая)

Кнопки: Сбросить настройки | Удалить (с подтверждением)


Настройки видео

Параметр Варианты По умолчанию
Разрешение 1920×1080 / 3840×2160 1920×1080
Кадры/с 25p / 30p / 50i / 60p 25p
Формат MP4 / MXF MP4
Длительность 3–60 секунд 10
Тема карты Светлая / Тёмная Тёмная
Дыхание камеры Ползунок 0–100 0

Дыхание камеры: циклическая анимация приближения/отдаления. Активна только пока открыто меню настроек видео — превью показывает эффект. В остальное время карта статична.

Кнопки: Сохранить | Сбросить настройки

Примечание по профилям:

  • MP4: 25/30/50/60 трактуются как progressive;
  • MXF: 50 трактуется как 50i, а 25/30/60 — progressive MXF.

Рендер видео

  • Кнопка "Сохранить видео" запускает рендер
  • Интерфейс блокируется, показывается прогресс-бар
  • Рендер продолжается на сервере даже если пользователь закрыл браузер
  • При возврате на сайт во время рендера — снова показывается прогресс-бар
  • После завершения, если страница открыта у пользователя — файл автоматически скачивается (если страница закрыта, то автоматически переходит в "Моя история")
  • Одновременно один рендер на пользователя
  • На сервере одновременно выполняется один рендер (single worker); остальные — в очереди (до 5 одновременно в очереди, дальше 429)

История видео ("Моя история")

  • Боковая панель, открывается из меню пользователя
  • Хранится 10 дней, затем автоматически удаляется
  • Каждая запись: миниатюра (первый кадр 320×180), название (авто по дате), дата
  • Кнопка "Скачать" для повторного скачивания

Хранение данных

База данных (PostgreSQL)

Имена таблиц и колонок — только английский (чтобы работать с ORM, миграциями и SQL без кавычек). Комментарии в коде и тексты ошибок — русский.

  • users — (id, username, password_hash, role, created_at)
  • sessions — (id, user_id, token_hash, expires_at, created_at)
  • render_jobs — единый источник истины по рендерам и истории видео: (id, user_id, status, progress, state_json, output_path, thumbnail_path, error_message, created_at, updated_at). Статусы: queued | running | done | error | cancelled. "Моя история" = выборка status = 'done', отсортированная по updated_at DESC. Отдельной таблицы videos нет.
  • render_tokens — одноразовые токены внутреннего доступа к GET /api/render/state/:jobId: (id, job_id, token_hash, expires_at, used_at, created_at)
  • gis — отдельная БД для PostGIS/Martin (геокодер Photon используется как внешний публичный сервис через бэкенд-прокси)

Файловая система

  • Готовые видео и миниатюры: /data/videos/{user_id}/
  • Временные PNG-кадры не сохраняются: захват идёт через image2pipe (Puppeteer -> stdin FFmpeg)
  • Cron: удаление файлов старше 10 дней

UI — Цветовая палитра

--color-bg-page:         #0d0d0d;
--color-bg-panel:        #1a1a1a;
--color-bg-panel-2:      #222222;
--color-bg-input:        #2a2a2a;
--color-bg-hover:        #333333;
--color-text-primary:    #f0f0f0;
--color-text-secondary:  #888888;
--color-accent:          #3d8bff;
--color-accent-hover:    #5a9fff;
--color-danger:          #ff4444;
--color-success:         #44bb44;
--color-border:          #333333;
--color-border-light:    #444444;

Минимальная ширина экрана: 1280px. Мобильная версия не нужна.


API — Общие правила

Базовый URL: https://mapvideo.gyhyry.ru/api Публичные эндпоинты без сессии: /auth/login, /auth/csrf, /health. Остальные эндпоинты используют cookie-based сессию (httpOnly session cookie). Исключение: GET /render/state/:jobId допускает либо owner-сессию, либо валидный одноразовый render_token (внутренний доступ рендер-воркера). Все ошибки возвращают: { "error": "Описание на русском" }

Код Описание
400 Неверный формат запроса
401 Не авторизован
403 Нет прав доступа
404 Ресурс не найден
409 Конфликт
429 Слишком много запросов / активный рендер уже есть / переполнена очередь
500 Внутренняя ошибка

Ассеты

Все ассеты уже находятся на сервере в папке assets/.

Иконки (assets/icons/)

Ассет Файл Тип Примечание
Огонь assets/icons/fire_loop/ PNG секвенция Готовая секвенция, зациклена на всё видео
Взрыв assets/icons/explosion.png PNG иконка Статично, анимация кругов процедурная
Землетрясение assets/icons/earthquake.png PNG иконка Статично, без анимации
Автомобиль assets/icons/car.png PNG иконка Нос смотрит вправо
Самолёт assets/icons/airplane.png PNG иконка Нос смотрит вправо
Вертолёт assets/icons/helicopter.png PNG иконка Нос смотрит вправо
Корабль assets/icons/ship.png PNG иконка Нос смотрит вправо

Мигающая точка — процедурно через PixiJS, PNG ассет не нужен.

Шрифты (assets/fonts/)

Шрифты используются для подписей точек на карте. Список доступных шрифтов формируется из файлов в этой папке. Фронтенд получает список через GET /api/fonts, подключает их через @font-face и дожидается document.fonts.ready перед рендером.


Что НЕ входит в v1

  • Отмена действий (Ctrl+Z)
  • Редактирование сохранённых проектов
  • Загрузка пользовательских иконок
  • Кастомизация стилей карты (реализуется отдельно через Maputnik после завершения разработки)

Формат работы

Разработка ведётся строго последовательно по фазам:

  • Начинаем с task1.md и не переходим к следующему пока текущий task не завершён полностью
  • После завершения фазы — обновить её статус ниже с "Не начато" / "В работе" на "✅ Сделано"
  • При возобновлении сессии после обновления лимита токенов:
    1. Найти фазу со статусом "🔄 В работе" — продолжать её
    2. Открыть соответствующий task*.md и найти "## Заметка для следующей сессии"
    3. Продолжить с того места где остановились

Прогресс разработки

# Фаза Файл Статус
1 Инфраструктура и окружение task1.md ✅ Сделано
2 Авторизация (бэкенд) task2.md ✅ Сделано
3 Скелет фронтенда task3.md ✅ Сделано
4 Карта и базовый редактор task4.md ✅ Сделано
5 Точки и подписи task5.md ✅ Сделано
6 Маршруты task6.md ✅ Сделано
7 Настройки видео task7.md ✅ Сделано
8 Рендер видео task8.md ✅ Сделано
9 Полировка и деплой task9.md 🔄 В работе (код готов, деплой не выполнен)
10 Полировка визуала (UX-багфиксы 1) task10.md ✅ Сделано
11 Фикс слайдеров (UX-багфиксы 2) task11.md ✅ Сделано
12 Выпадающие/overlay-панели (UX-багфиксы 3) task12.md ✅ Сделано
13 Геокод, админка, начертания (UX-багфиксы 4) task13.md ✅ Сделано
14 Палитра цветов (UX-багфиксы 5) task14.md ✅ Сделано
15 Критические баги рендер-пайплайна task15.md ✅ Сделано
16 Исправления UX и обработки ошибок task16.md ✅ Сделано
17 Безопасность, валидация, мелкие баги task17.md ✅ Сделано
18 Синхронизация документации task18.md ✅ Сделано

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages