30 KiB
⚽ VMIX Football Broadcast System
Система управления футбольными трансляциями с интеграцией в 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
Скрипт запросит:
UsernamePassword
После этого создаст запись в таблице 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_usersauth_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-логика.
Как это работает в общем
- Оператор открывает матч в админке.
- Создаётся матчевая сессия с
session_token. - Сервер отдаёт JSON и/или
.vmix-файл. - Локальный агент подключается по WebSocket.
- Сервер отправляет команды конкретному клиенту, группе или оператору.
- Агент применяет команды в локальном vMix через HTTP API.
🧾 Генерация JSON для графики
Логика сосредоточена в services/vmix_json_service.py.
По коду видно, что сервис формирует:
- стартовые составы;
- запасных;
- информацию о матче;
- турнирную таблицу;
- расписание тура;
- формации команд;
- scoreboard-информацию;
- события матча;
- данные для показа авторов голов.
Особенности реализации
- строятся полные имена игроков;
- добавляются суффиксы капитана и вратаря;
- формируются пути к фотографиям игроков;
- используются логотипы команд и специальные варианты логотипов для некоторых клубов;
- матчевая информация собирается SQL-запросами по сессии.
📦 Генерация .vmix проекта
Файл vmix/vmix_service.py используется для:
- сборки бинарного содержимого vMix-проекта;
- генерации имени файла;
- выдачи файла пользователю через FastAPI.
В app.py для этого используются:
build_vmix_project_bytesbuild_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.pyaudit_log_repository.py
Матчи
match_repository.pymatch_session_repository.pymatch_view_repository.pymatch_clock_repository.pymatch_event_repository.py
Составы и формации
match_lineup_repository.pymatch_formation_repository.pyteam_squad_repository.py
Официальные лица и стадионы
referee_repository.pymatch_referee_repository.pycoach_repository.pymatch_coach_repository.pyteam_coach_repository.pystadium_repository.py
Команды, игроки, таблица
team_repository.pyplayer_repository.pystandings_repository.py
Это хороший признак разделённой архитектуры: доступ к данным отделён от HTTP-слоя и от прикладной логики.
🔄 Сервисы синхронизации
В services/ есть отдельные сервисы:
teams_service.pyschedule_service.pyplayers_service.pystandings_service.pygame_service.pyauth_service.pyvmix_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
🖼 Скриншоты
Ниже заготовки под реальные скриншоты интерфейса. Когда будут реальные изображения, просто положи их в репозиторий и обнови пути.




⚠️ Ограничения и важные замечания
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/apiwss://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:
- отдельная ветка на каждую фичу;
- PR с описанием изменений;
- проверка SQL-миграций перед merge;
- ручная проверка 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.