2026-04-24 17:20:09 +03:00
2026-04-23 15:07:24 +03:00
2026-04-22 13:02:49 +03:00
2026-04-20 11:56:11 +03:00
2026-04-23 20:53:54 +03:00
2026-04-23 20:53:54 +03:00
2026-04-23 15:27:29 +03:00
2026-04-21 13:02:35 +03:00
2026-04-24 14:58:35 +03:00
2026-04-20 11:56:11 +03:00
2026-04-20 14:15:27 +03:00
2026-04-20 11:56:11 +03:00
2026-04-23 18:34:37 +03:00
2026-04-24 17:20:09 +03:00
2026-04-20 11:56:11 +03:00

VMIX Football Broadcast System

Python FastAPI PostgreSQL WebSocket vMix Status

Система управления футбольными трансляциями с интеграцией в vMix, админ-панелью, live-обновлением матчей, генерацией данных для графики и WebSocket-взаимодействием с операторскими клиентами.


📌 Что это за проект

Проект предназначен для подготовки и сопровождения футбольных трансляций. Он объединяет в одном приложении:

  • администрирование матчей, команд, игроков, тренеров, судей и стадионов;
  • работу с составами и формациями на матч;
  • генерацию данных для эфирной графики в vMix;
  • создание и выгрузку .vmix-проекта;
  • приём и отправку команд в vMix-клиенты через WebSocket;
  • фоновое отслеживание матчей и обновление live-данных;
  • синхронизацию расписания, игроков, команд и турнирной таблицы.

По текущей структуре проект ориентирован на внутреннюю production/операторскую эксплуатацию, а не на публичный API-сервис.


Основные возможности

Админка и матч-центр

  • авторизация администратора;
  • список матчей и выбор матча для сессии;
  • рабочее пространство матча;
  • редактирование составов;
  • редактирование формаций;
  • управление судьями;
  • управление событиями матча.

База футбольных сущностей

  • игроки;
  • команды;
  • тренеры;
  • судьи;
  • стадионы;
  • турнирная таблица;
  • составы на матч;
  • матчевые сессии для операторов.

Интеграция с vMix

  • генерация .vmix-проекта;
  • формирование имени файла проекта;
  • генерация JSON-данных для графики;
  • публикация команд в подключённые vMix-клиенты;
  • получение динамических значений из vMix API.

Live-логика

  • планировщик, который отслеживает матчи дня;
  • запуск watcher-потоков перед матчем;
  • опрос live-данных каждые 60 секунд;
  • обновление статуса матча и счёта;
  • обновление турнирной таблицы.

Парсинг и синхронизация

  • парсинг матчей;
  • парсинг игроков;
  • парсинг расписания;
  • парсинг таблицы;
  • синхронизация сущностей в БД через сервисный слой.

🏗 Архитектура

Проект построен вокруг классической схемы:

Parsers -> Services -> Repositories -> PostgreSQL
                        |
                        +-> vMix JSON / .vmix generation
                        +-> FastAPI admin UI
                        +-> WebSocket command bus
                        +-> Scheduler / live workers

Слои проекта

parsers/

Получают данные из внешних источников. Используются для матчей, игроков, расписания, команд и таблиц.

services/

Содержат прикладную бизнес-логику: синхронизацию данных, авторизацию, подготовку JSON для vMix.

repositories/

Отвечают за доступ к PostgreSQL. Здесь собраны CRUD-операции и специализированные запросы.

templates/ + static/

HTML-шаблоны Jinja2, CSS, JS и статические файлы интерфейса.

vmix/

Логика генерации vMix-проекта и служебные функции, связанные с эфирной интеграцией.

scheduler.py

Фоновый мониторинг матчей и обновление live-состояния.

agent.py

Отдельный клиент для связи между vMix и сервером через WebSocket.


📁 Структура проекта

vmix/
├── app.py                         # Основной FastAPI сервер
├── agent.py                       # WebSocket/vMix агент
├── db.py                          # Подключение к PostgreSQL
├── scheduler.py                   # Фоновый live scheduler
├── main.py                        # Demo/seed сценарий
├── deploy.sh                      # Скрипт деплоя
├── requirements.txt               # Python зависимости
├── wfl.sql                        # Основная схема БД
│
├── parsers/
│   ├── parser_game.py             # Парсинг/обновление данных матча
│   ├── parser_players.py          # Парсинг игроков
│   ├── parser_schedule.py         # Парсинг расписания
│   ├── parser_standings.py        # Парсинг таблицы
│   └── parser_teams.py            # Парсинг команд
│
├── repositories/
│   ├── audit_log_repository.py
│   ├── auth_repository.py
│   ├── coach_repository.py
│   ├── match_clock_repository.py
│   ├── match_coach_repository.py
│   ├── match_event_repository.py
│   ├── match_formation_repository.py
│   ├── match_lineup_repository.py
│   ├── match_referee_repository.py
│   ├── match_repository.py
│   ├── match_session_repository.py
│   ├── match_view_repository.py
│   ├── player_repository.py
│   ├── referee_repository.py
│   ├── stadium_repository.py
│   ├── standings_repository.py
│   ├── team_coach_repository.py
│   ├── team_repository.py
│   └── team_squad_repository.py
│
├── services/
│   ├── auth_service.py
│   ├── game_service.py
│   ├── players_service.py
│   ├── schedule_service.py
│   ├── standings_service.py
│   ├── teams_service.py
│   └── vmix_json_service.py
│
├── sql/
│   └── 001_auth.sql               # Таблицы админ-пользователей и сессий
│
├── static/
│   ├── script.js
│   ├── styles.css
│   ├── smith.ico
│   └── images/
│       └── vmix_icon.png
│
├── templates/
│   ├── login.html
│   ├── matches.html
│   ├── match_workspace.html
│   ├── download_vmix.html
│   ├── admin_db_index.html
│   ├── admin_db_players.html
│   ├── admin_db_player_edit.html
│   ├── admin_db_referees.html
│   ├── admin_db_referee_edit.html
│   ├── admin_db_coaches.html
│   ├── admin_db_coach_edit.html
│   ├── admin_db_stadiums.html
│   ├── admin_db_stadium_edit.html
│   ├── admin_db_teams.html
│   └── admin_db_team_edit.html
│
└── vmix/
    ├── __init__.py
    └── vmix_service.py            # Генерация .vmix файла

🧰 Технологии

Категория Технологии
Backend FastAPI
Валидация Pydantic
Шаблоны Jinja2
База данных PostgreSQL + psycopg2
Парсинг requests + BeautifulSoup4
Realtime WebSocket
Интеграция с эфиром vMix API + XML
Конфигурация python-dotenv
Дополнительно numpy

Зависимости из requirements.txt

fastapi>=0.115,<1.0
uvicorn[standard]>=0.30,<1.0
pydantic>=2.0,<3.0
jinja2>=3.1,<4.0
python-multipart>=0.0.9,<1.0
requests>=2.31,<3.0
websockets>=12,<16
beautifulsoup4>=4.12,<5.0
psycopg2-binary>=2.9,<3.0
python-dotenv>=1.0,<2.0
numpy>=1.26,<3.0

Также в файле указан дополнительный приватный индекс и пакет nasio, поэтому для полноценной установки в целевой среде может понадобиться доступ к внутреннему package registry.


🚀 Быстрый старт

1. Клонирование репозитория

git clone <YOUR_REPOSITORY_URL>
cd vmix

2. Установка зависимостей

pip install -r requirements.txt

3. Настройка переменных окружения

Создай файл .env в корне проекта:

DB_HOST=localhost
DB_PORT=5432
DB_NAME=wfl_db
DB_USER=postgres
DB_PASSWORD=your_password

db.py загружает эти параметры через python-dotenv и использует их для подключения к PostgreSQL.

4. Инициализация базы данных

Сначала разверни основную схему:

psql -U postgres -d wfl_db -f wfl.sql

Затем создай таблицы авторизации:

psql -U postgres -d wfl_db -f sql/001_auth.sql

5. Создание администратора

python scripts/create_admin.py

Скрипт запросит:

  • Username
  • Password

После этого создаст запись в таблице admin_users.

6. Запуск приложения

uvicorn app:app --host 0.0.0.0 --port 8000 --reload

После запуска приложение будет доступно по адресу:

http://localhost:8000

🔐 Авторизация

В проекте используется сессионная авторизация для админки.

Что есть в коде

  • таблица admin_users;
  • таблица auth_sessions;
  • проверка пароля в services/auth_service.py;
  • cookie/session-based доступ к админским маршрутам;
  • logout с отзывом сессии.

SQL-таблицы авторизации

Файл sql/001_auth.sql создаёт:

  • admin_users
  • auth_sessions
  • индексы по токену, пользователю и активности

Скрипт создания пользователя

python scripts/create_admin.py


🖥 Интерфейс и рабочие зоны

Основные страницы

  • /login — вход администратора;
  • / — редирект/входная точка;
  • /admin/matches — список матчей для администратора;
  • /admin/session/{session_token} — рабочее пространство матча;
  • /admin/session/{session_token}/download-vmix-page — страница выгрузки проекта;
  • /admin/db — индекс админского раздела БД.

Разделы админ-БД

  • игроки;
  • судьи;
  • тренеры;
  • стадионы;
  • команды.

Для каждой сущности есть минимум список и форма редактирования.


📡 HTTP и WebSocket API

Ниже — маршруты, которые реально определены в app.py.

Аутентификация

Метод Маршрут Назначение
GET /login страница входа
POST /login авторизация
POST /logout выход

Матчи и сессии

Метод Маршрут Назначение
GET /admin/matches список матчей
GET /admin/matches/{match_id}/select выбор матча и создание/открытие сессии
GET /admin/session/{session_token} рабочее пространство матча
POST /admin/session/{session_token}/load-match-data загрузка/обновление данных матча
POST /admin/session/{session_token}/close закрытие сессии
GET /admin/session/{session_token}/download-vmix-page HTML-страница выгрузки vMix
GET /admin/session/{session_token}/download-vmix скачивание .vmix

Формации и составы

Метод Маршрут Назначение
POST /admin/session/{session_token}/formations/apply применить preset формации к игрокам
POST /admin/session/{session_token}/formations/save сохранить формации
GET /admin/session/{session_token}/squad-editor-data получить данные редактора состава
POST /admin/session/{session_token}/squad-editor-save сохранить состав
POST /admin/session/{session_token}/referees/save сохранить судей на матч

События матча

Метод Маршрут Назначение
GET /admin/session/{session_token}/events список событий
POST /admin/session/{session_token}/event создать событие
PUT /admin/session/{session_token}/event/{event_id} обновить событие
DELETE /admin/session/{session_token}/event/{event_id} удалить событие
DELETE /admin/session/{session_token}/events очистить все события

Справочники БД

Метод Маршрут Назначение
GET /admin/db главная админ-БД
GET/POST /admin/db/players / /admin/db/players/{player_id}/edit список/редактирование игроков
GET/POST /admin/db/referees / /admin/db/referees/{referee_id}/edit список/редактирование судей
GET/POST /admin/db/coaches / /admin/db/coaches/{coach_id}/edit список/редактирование тренеров
GET/POST /admin/db/stadiums / /admin/db/stadiums/{stadium_id}/edit список/редактирование стадионов
GET/POST /admin/db/teams / /admin/db/teams/{team_id}/edit список/редактирование команд

vMix JSON endpoints

Метод Маршрут Назначение
GET /vmix/session/{session_token}/home-lineup стартовый состав хозяев
GET /vmix/session/{session_token}/away-lineup стартовый состав гостей
GET /vmix/session/{session_token}/home-bench запасные хозяев
GET /vmix/session/{session_token}/away-bench запасные гостей
GET /vmix/session/{session_token}/info информация о матче
GET /vmix/session/{session_token}/standings турнирная таблица
GET /vmix/session/{session_token}/schedule расписание/тур
GET /vmix/session/{session_token}/home-formations формация хозяев
GET /vmix/session/{session_token}/away-formations формация гостей
GET /vmix/session/{session_token}/scoreboard данные для счётчика
GET /vmix/session/{session_token}/match-events данные по событиям матча

Команды для vMix-клиентов

Метод Маршрут Назначение
POST /api/vmix/publish-command отправить команду в vMix-клиент(ы)
GET /api/vmix/clients список подключённых клиентов
WS /ws/vmix-client WebSocket-канал клиентов

🎬 Интеграция с vMix

Что делает сервер

Сервер:

  • создаёт матчевые сессии;
  • готовит JSON для графики;
  • собирает и отдаёт .vmix-проект;
  • отправляет команды в подключённые клиентские агенты.

Что делает агент agent.py

Агент — это отдельное приложение, которое запускается рядом с vMix и выполняет роль моста между сервером и локальным vMix API.

В коде агента есть:

  • VMIX_API = "http://127.0.0.1:8088/api"
  • WS_BASE = "wss://wfl.tvstart.ru/ws/vmix-client"
  • чтение XML-ответа vMix;
  • извлечение dynamic/value1, dynamic/value2 и других значений;
  • регистрация клиента в WebSocket;
  • reconnect-логика.

Как это работает в общем

  1. Оператор открывает матч в админке.
  2. Создаётся матчевая сессия с session_token.
  3. Сервер отдаёт JSON и/или .vmix-файл.
  4. Локальный агент подключается по WebSocket.
  5. Сервер отправляет команды конкретному клиенту, группе или оператору.
  6. Агент применяет команды в локальном vMix через HTTP API.

🧾 Генерация JSON для графики

Логика сосредоточена в services/vmix_json_service.py.

По коду видно, что сервис формирует:

  • стартовые составы;
  • запасных;
  • информацию о матче;
  • турнирную таблицу;
  • расписание тура;
  • формации команд;
  • scoreboard-информацию;
  • события матча;
  • данные для показа авторов голов.

Особенности реализации

  • строятся полные имена игроков;
  • добавляются суффиксы капитана и вратаря;
  • формируются пути к фотографиям игроков;
  • используются логотипы команд и специальные варианты логотипов для некоторых клубов;
  • матчевая информация собирается SQL-запросами по сессии.

📦 Генерация .vmix проекта

Файл vmix/vmix_service.py используется для:

  • сборки бинарного содержимого vMix-проекта;
  • генерации имени файла;
  • выдачи файла пользователю через FastAPI.

В app.py для этого используются:

  • build_vmix_project_bytes
  • build_vmix_filename

Это означает, что оператор может открыть страницу сессии и скачать готовый .vmix-проект под конкретный матч.


⏱ Scheduler и live-мониторинг

scheduler.py — это фоновый процесс, который поднимается на старте приложения:

@app.on_event("startup")
def start_scheduler():
    import threading
    thread = threading.Thread(target=run_scheduler, daemon=True)
    thread.start()

Ключевые интервалы

MATCH_START_LEAD_MINUTES = 1
LIVE_MATCH_POLL_SECONDS = 60
MATCHES_LOOP_SECONDS = 60
STANDINGS_LOOP_SECONDS = 60
WORKER_ERROR_RETRY_SECONDS = 30
WORKER_MAX_ERRORS_IN_ROW = 20

Что делает scheduler

  • получает матчи на сегодня из БД;
  • определяет, какие матчи уже пора мониторить;
  • запускает отдельные worker-потоки;
  • обновляет status/home_score/away_score в таблице матчей;
  • вызывает обновление турнирной таблицы;
  • ведёт реестр активных worker'ов.

Источник live-данных

По текущему коду live-страница матча запрашивается с:

https://wfl.rfs.ru/match/{match_id}

HTML разбирается через BeautifulSoup.

Важное замечание

В fetch_match_live_data() есть незавершённая часть: функция частично реализована и в конце всё ещё содержит NotImplementedError. То есть scheduler уже встроен, но live-парсинг требует аккуратной доработки, чтобы считать его полностью production-ready.


🗄 Репозитории и доменные сущности

По составу repositories/ проект работает со следующими сущностями:

Пользователи и аудит

  • auth_repository.py
  • audit_log_repository.py

Матчи

  • match_repository.py
  • match_session_repository.py
  • match_view_repository.py
  • match_clock_repository.py
  • match_event_repository.py

Составы и формации

  • match_lineup_repository.py
  • match_formation_repository.py
  • team_squad_repository.py

Официальные лица и стадионы

  • referee_repository.py
  • match_referee_repository.py
  • coach_repository.py
  • match_coach_repository.py
  • team_coach_repository.py
  • stadium_repository.py

Команды, игроки, таблица

  • team_repository.py
  • player_repository.py
  • standings_repository.py

Это хороший признак разделённой архитектуры: доступ к данным отделён от HTTP-слоя и от прикладной логики.


🔄 Сервисы синхронизации

В services/ есть отдельные сервисы:

  • teams_service.py
  • schedule_service.py
  • players_service.py
  • standings_service.py
  • game_service.py
  • auth_service.py
  • vmix_json_service.py

Demo-режим

main.py показывает, как можно программно наполнить систему тестовыми данными:

  • создаются 2 команды;
  • создаётся матч;
  • добавляются игроки;
  • заполняется турнирная таблица.

Запуск:

python main.py

Это удобно для первичной проверки БД и шаблонного сценария разработки.


🧪 Полезные команды

Проверка подключения к БД

python db.py

Создание администратора

python scripts/create_admin.py

Demo-наполнение

python main.py

Запуск сервера

uvicorn app:app --reload

🖼 Скриншоты

Ниже заготовки под реальные скриншоты интерфейса. Когда будут реальные изображения, просто положи их в репозиторий и обнови пути.

![Login](docs/screens/login.png)
![Matches](docs/screens/matches.png)
![Workspace](docs/screens/workspace.png)
![Database](docs/screens/database.png)

⚠️ Ограничения и важные замечания

1. Документация OpenAPI отключена

В app.py явно выключены:

  • /docs
  • /redoc
  • /openapi.json

Это нормально для внутреннего production-режима, но неудобно для внешних интеграций.

2. Live scheduler требует доработки

fetch_match_live_data() ещё не завершена до конца и сейчас выглядит как заготовка с частичной логикой.

3. Есть Windows-специфичные элементы

В JSON-сервисе и агенте встречаются Windows-пути и логика работы с иконкой консоли. Это значит, что часть инфраструктуры ориентирована на Windows-машину оператора.

4. Есть внешняя зависимость от приватного Python registry

В requirements.txt указан --extra-index-url, поэтому разворачивание в другой среде может потребовать доступов.

5. Есть жёстко заданные интеграционные значения

Например:

  • http://127.0.0.1:8088/api
  • wss://wfl.tvstart.ru/ws/vmix-client

Для production лучше вынести их в .env.


🔮 Что можно улучшить

Инфраструктура

  • добавить Dockerfile и docker-compose.yml;
  • вынести конфигурацию целиком в .env;
  • добавить healthcheck и monitoring;
  • настроить CI/CD.

Backend

  • включить структурированное логирование;
  • покрыть ключевые места тестами;
  • заменить часть threading-логики на более управляемый background orchestration;
  • валидацию live-парсеров сделать устойчивее.

Безопасность

  • ограничить rate limit для логина;
  • добавить CSRF-защиту, если нужна;
  • вынести секреты и URL в окружение;
  • расширить аудит действий администратора.

API и DX

  • вернуть внутреннюю OpenAPI-документацию под флагом окружения;
  • добавить Postman/Insomnia collection;
  • оформить контракт JSON-ответов для графики.

UI/UX

  • добавить больше навигации в админке;
  • улучшить визуальный статус live-сессий;
  • добавить быстрые действия в матч-центре.

🛠 Пример локального сценария запуска

# 1. установить зависимости
pip install -r requirements.txt

# 2. создать .env
cp .env.example .env   # если появится шаблон

# 3. поднять БД и применить SQL
psql -U postgres -d wfl_db -f wfl.sql
psql -U postgres -d wfl_db -f sql/001_auth.sql

# 4. создать администратора
python scripts/create_admin.py

# 5. при необходимости заполнить демо-данными
python main.py

# 6. запустить сервер
uvicorn app:app --host 0.0.0.0 --port 8000 --reload

🤝 Вклад в проект

Если проект будет развиваться дальше, рекомендуется принять минимальные правила contribution:

  1. отдельная ветка на каждую фичу;
  2. PR с описанием изменений;
  3. проверка SQL-миграций перед merge;
  4. ручная проверка vMix-сценария и матчевого workflow.

📄 Лицензия

В текущем архиве лицензия отдельно не обнаружена.

Если проект внутренний — можно оставить private/internal use only. Если репозиторий будет публичным — добавь подходящую лицензию, например MIT, Apache-2.0 или другую нужную команде.


👨‍💻 Итог

Этот проект — это не просто CRUD-приложение, а полноценный операторский инструмент для футбольной трансляции:

  • FastAPI-сервер с HTML-интерфейсом;
  • PostgreSQL как основной источник данных;
  • сессионная админ-авторизация;
  • матчевые рабочие сессии;
  • составы, формации, события и судьи;
  • JSON и .vmix для эфирной графики;
  • WebSocket-мост для операторских клиентов;
  • scheduler для live-матчей и обновления данных.

Если нужно, следующим сообщением я могу так же сделать ещё и:

  • README_EN.md на английском;
  • docs/API.md с описанием всех маршрутов;
  • docker-compose.yml для локального запуска;
  • .env.example;
  • более «маркетинговую» GitHub-версию с centered hero, anchors и navigation block.
Description
No description provided
Readme 22 MiB
Languages
Python 42%
HTML 36.1%
JavaScript 15.8%
CSS 5.5%
Shell 0.6%