34 KiB
AE Anons - Автоматизированный генератор спортивных анонсов в After Effects
Автоматизированная система для создания спортивных анонсов с использованием шаблонов After Effects через Nexrender, с данными из электронных таблиц Synology Office.
Новое в версии 0.2.2
- Веб-интерфейс: Удобное управление заданиями через браузер
- Мониторинг в реальном времени: Отслеживание статуса всех заданий
- Управление очередью: Остановка, очистка и генерация заданий из веб-интерфейса
- Тёмная/светлая тема: Автоматическое определение системной темы
- Сортировка и фильтрация: Удобная работа с большим количеством заданий
Обзор
AE Anons — это CLI-утилита и веб-сервер на Rust, которая выступает как интеллектуальный генератор заданий для Nexrender — опенсорсного оркестратора рендеринга After Effects (лицензия MIT).
Режимы работы
-
Однократная обработка (
--onceили без флагов):- Подключение к NAS Synology
- Парсинг Excel данных
- Генерация и отправка заданий Nexrender
- Мониторинг завершения и выход
-
Веб-сервер (
--web):- Запуск веб-интерфейса на порту
:3000 - Управление заданиями через браузер
- Автообновление статуса каждую минуту
- Запуск веб-интерфейса на порту
Особенности
- Интеграция с Synology: Аутентификация и загрузка файлов с NAS Synology
- Экспорт офисных таблиц: Автоматическое преобразование файлов .osheet в формат Excel
- Гибкий парсинг данных: Динамический парсинг листов с обнаружением заголовков
- Множественная генерация вариантов: Создание "Сегодня", "Завтра" и датированных версий
- Умное управление логотипами: Автоматическое разрешение и масштабирование логотипов
- Веб-интерфейс: Удобное управление и мониторинг заданий
- REST API: Программный доступ к управлению заданиями
- Профессиональное логирование: Структурированный журнал с настройкой уровня
Предварительные требования
- Rust 1.70 или выше
- Доступ к NAS Synology с пакетами File Station и Office
- Экземпляр server и worker(не менее одного) Nexrender
- Шаблоны After Effects (формат Adobe After Effects 2024 .aepx)
Установка
1. Клонирование репозитория
git clone https://git.tvstart.ru/lexx/AE_Anons.git
cd ae_anons
2. Сборка проекта
cargo build --release
3. Настройка окружения
Скопируйте пример конфигурации и заполните своими данными:
cp .env.example .env
Затем отредактируйте файл .env:
См. раздел Конфигурация для подробной информации.
Использование
Однократная обработка
# Запуск с настройками по умолчанию
./target/release/ae_anons
# Явно указать однократный режим
./target/release/ae_anons --once
# С отладочным логированием
RUST_LOG=debug ./target/release/ae_anons
Веб-сервер
# Запуск веб-интерфейса на порту по умолчанию (3000)
./target/release/ae_anons --web
# Или с указанием другого порта через .env файл
# WEB_PORT=8080 ./target/release/ae_anons --web
Веб-интерфейс
После запуска веб-сервера откройте браузер:
-
Главная страница: http://localhost:3000
-
API эндпоинты:
GET /api/jobs- список всех заданийPOST /api/generate- запуск генерацииPOST /api/cleanup- очистка завершённыхPOST /api/jobs/stop-all- остановка активныхGET /api/status- статус сервера
Уровни логирования
Управляйте детализацией вывода через переменную окружения RUST_LOG:
- error - Только критические ошибки
- warn - Предупреждения и ошибки
- info - Общие операционные сообщения (по умолчанию)
- debug - Детальная информация о процессе обработки
- trace - Полное отладочное логирование с деталями API вызовов
RUST_LOG=debug cargo run
Конфигурация
Переменные окружения
| Переменная | Обязательна | Описание |
|---|---|---|
NAS_FQDN |
Да | URL NAS Synology с протоколом и портом |
NAS_USER |
Да | Имя пользователя учетной записи Synology |
NAS_PASS |
Да | Пароль учетной записи Synology |
NAS_FILE |
Да | Полный путь к файлу .osheet на NAS |
NEXRENDER_API_URL |
Да | Конечная точка API сервера Nexrender |
OUTPUT_FOLDER |
Да | Сетевой путь для рендеренных видео |
TEMPLATE_DOUBLE_SRC |
Да | Путь к AEP-шаблону для двух команд |
TEMPLATE_SINGLE_SRC |
Да | Путь к AEP-шаблону для одной команды |
TEMPLATE_COMPOSITION |
Да | Имя композиции в проекте AE (например, main) |
TEMPLATE_OUTPUT_MODULE |
Да | Имя модуля вывода в AE (например, h264) |
TEMPLATE_OUTPUT_EXT |
Да | Расширение выходного файла (например, mp4) |
WEB_PORT |
Нет | Порт для веб-сервера (по умолчанию: 3000) |
RUST_LOG |
Нет | Уровень детализации логирования (по умолчанию: info) |
Пример файла .env
# Synology NAS
NAS_FQDN="https://your-nas.example.com"
NAS_USER="your_username"
NAS_PASS="your_password"
NAS_FILE="/Team Folder/path/to/file.osheet"
# Logging
RUST_LOG="info"
# Web Server
WEB_PORT="3000"
# Nexrender
NEXRENDER_API_URL="http://nexrender-server:3050/api/v1/jobs"
OUTPUT_FOLDER="/path/to/output"
# After Effects Templates
TEMPLATE_DOUBLE_SRC="file:///path/to/double_team_template.aepx"
TEMPLATE_SINGLE_SRC="file:///path/to/single_team_template.aepx"
TEMPLATE_COMPOSITION="main"
TEMPLATE_OUTPUT_MODULE="h264"
TEMPLATE_OUTPUT_EXT="mp4"
Структура электронной таблицы
Файл Excel должен содержать следующие листы со специфичными структурами:
Лист "SPORT"
Связывает названия видов спорта с соответствующими видео пакетами.
| SPORT | LINK |
|---|---|
| Без оформления | \server\share\path\to\null.mov |
| Футбол | \server\share\path\to\football_pack.mov |
| Волейбол | \server\share\path\to\volleyball_pack.mov |
Лист "TEAMS"
Сопоставляет имена команд с их видами спорта и логотипами. Колонка SPORT заполняется из выпадающего списка (заполнена из листа SPORT).
Если несколько команд в одном виде спорта имеют одинаковые названия, но разные логотипы, используется разделитель хеш # для уникальной идентификации.
| TEAM | SPORT | LINK |
|---|---|---|
| Галатасарай#Turki | Футбол | \server\share\path\to\galatasaray_football.png |
| Галатасарай | Волейбол | \server\share\path\to\galatasaray_volleyball.png |
| Галатасарай#UCL | Волейбол | \server\share\path\to\galatasaray_ucl.png |
| Сомбатей##400 | Футбол | \server\share\path\to\szombathely.png |
Лист "CHANELL"
Сопоставляет названия каналов с их логотипами. Поля заполняются вручную без выпадающих списков.
| CHANELL | LINK |
|---|---|
| КАНАЛ | \server\share\path\to\channel_logo.png |
| TRIUMPH | \server\share\path\to\triumph_logo.png |
Лист "Start"
Основной источник данных для генерации анонсов. Большинство полей заполняются из выпадающих списков, основанных на других листах.
Обязательные колонки: DATA, TIME, CHANELL, SPORT, LEAGUE, TEAM A, TEAM B
Примечания:
- Колонка LEAGUE обязательна для заполнения, но не имеет выпадающего списка. Проверка орфографии и опечаток отсутствует!
- Колонка DATA должна содержать дату в формате
ДД.ММ.ГГГГ(например,28.2.2026).
| STATE | TRIPPLE | DATA | TIME | SPORT | LEAGUE | CHANELL | TEAM A | TEAM B |
|---|---|---|---|---|---|---|---|---|
| TRUE | TRUE | 27.2.2026 | 23:40 | Футбол | Чемпионат Португалии | START | Спортинг#ll#550 | Эшторил#ll#550 |
| FALSE | TRUE | 28.2.2026 | 12:55 | Волейбол | Чемпионат Турции. Женщины | TRIUMPH | Бешикташ | Галатасарай#Turki |
Формат имен команд
Имена команд поддерживают два типа разделителей хэш #:
- Первый хеш: Уникальный идентификатор для команд с одинаковыми названиями в одном виде спорта, или одинаковым названием в разных видах спорта. Примеры:
Динамо#Футбол,Динамо#Волейбол- Одно название разный вид спортаСпартак#ЖенскийФ,Спартак#МужскойФОдно название разный вид спорта
- Второй хеш: Целевой размер в пикселях для масштабирования логотипа
Формат: DisplayName#UniqueID#TargetSize
Примеры:
Галатасарай#Turki- только уникальный идентификаторСомбатей##400- только целевой размер (обратите внимание на двойной хеш)Спортинг#ll#550- оба идентификатор и целевой размер
Важно: Обрабатывается только второй хеш для масштабирования логотипа. Если уникальный идентификатор не требуется, используйте двойной хеш ## перед целевым размером.
Выходные файлы
Рендеренные видео
Рендерные видео сохраняются в OUTPUT_FOLDER по следующему шаблону именования:
YYYYMMDD_Sport_League_TeamA_TeamB_Channel[_Variant].mp4
Имена файлов транслитерируются в латиницу. Примеры:
20260228_Volleyball_Championship-Turkey-Women_Beşiktaş_Galatasaray_TRIUMPH.mp420260228_Volleyball_Championship-Turkey-Women_Beşiktaş_Galatasaray_TRIUMPH_Today.mp420260228_Volleyball_Championship-Turkey-Women_Beşiktaş_Galatasaray_TRIUMPH_Tomorrow.mp4
Рабочий процесс
- Аутентификация: Подключение к NAS Synology с использованием предоставленных учетных данных
- Получение файла: Поиск и экспорт указанного файла .osheet в Excel
- Парсинг данных: Чтение всех листов и структурирование данных
- Разрешение ресурсов: Сопоставление видов спорта, команд и каналов с визуальными элементами
- Генерация заданий: Создание заданий Nexrender для каждой активной строки с вариантами
- Очистка: Удаление завершенных/неудачных заданий из предыдущих запусков
- Отправка: Отправка заданий на API Nexrender
- Мониторинг: Слежение за прогрессом выполнения до завершения
- Завершение сеанса: Закрытие сессии Synology
Требования к шаблонам After Effects
Шаблоны должны быть предварительно настроены на узлах рендеринга со следующими именами слоёв.
Файлы шаблонов
Настраиваются через переменные окружения:
| Переменная | Назначение | Пример значения |
|---|---|---|
TEMPLATE_DOUBLE_SRC |
Шаблон для матчей с двумя командами | file:///path/to/double.aepx |
TEMPLATE_SINGLE_SRC |
Шаблон для анонсов с одной командой | file:///path/to/single.aepx |
TEMPLATE_COMPOSITION |
Имя главной композиции | main |
TEMPLATE_OUTPUT_MODULE |
Имя модуля вывода | h264 |
TEMPLATE_OUTPUT_EXT |
Расширение выходного файла | mp4 |
Обязательные слои в шаблонах
Текстовые слои
| Имя слоя | Шаблон DOUBLE | Шаблон SINGLE | Описание |
|---|---|---|---|
DATA |
✅ | ✅ | Отображение даты (автоматически подстраивается) |
TIME_H |
✅ | ❌ | Часы (отдельный слой) |
TIME_M |
✅ | ❌ | Минуты (отдельный слой) |
TIME |
❌ | ✅ | Полное время (единый слой) |
LEAGUE |
✅ | ✅ | Название лиги/турнира |
SPORT |
✅ | ✅ | Категория спорта |
TEAMS |
✅ | ✅ | Скомбинированные имена команд |
Слои с изображениями
| Имя слоя | Шаблон DOUBLE | Шаблон SINGLE | Описание |
|---|---|---|---|
TEAM_A_LOGO |
✅ | ✅ | Логотип команды A |
TEAM_B_LOGO |
✅ | ❌ | Логотип команды B |
CHANELL |
✅ | ✅ | Логотип канала (две буквы L) |
Видео слои
| Имя слоя | Шаблон DOUBLE | Шаблон SINGLE | Описание |
|---|---|---|---|
TOP |
✅ | ✅ | Наложение видео оформления |
Особенности шаблонов
Шаблон DOUBLE (две команды)
Используется когда в строке Excel заполнены оба поля TEAM A и TEAM B.
Обязательные слои:
- Все текстовые слои с
TIME_HиTIME_MвместоTIME - Оба логотипа команд:
TEAM_A_LOGOиTEAM_B_LOGO
Шаблон SINGLE (одна команда)
Используется когда заполнено только одно поле команды.
Обязательные слои:
- Текстовый слой
TIMEвместоTIME_HиTIME_M - Только логотип
TEAM_A_LOGO
Автоматические корректировки
AE Anons автоматически применяет следующие настройки к слоям:
Слой DATA
В зависимости от отображаемого текста и типа шаблона:
| Текст | Шаблон | Font Size | Anchor Point |
|---|---|---|---|
| "сегодня" | DOUBLE | 105 | [0, 5] |
| "завтра" | DOUBLE | 115 | [0, 25] |
| дата (<6) | DOUBLE | 120 | [0, 20] |
Слои TIME_H, TIME_M, TIME
Корректировка Anchor Point в зависимости от длины текста:
| Условие | Anchor Point |
|---|---|
| 1 символ | [60, 0] |
| 2 символа, <20 | [20, 0] |
Слой LEAGUE
Если длина текста превышает 16 символов, размер шрифта уменьшается до 73.
Слой TEAMS
Если суммарная длина имён команд ≥ 32 символов, размер шрифта уменьшается до 55.
Логотипы (TEAM_A_LOGO, TEAM_B_LOGO)
Если в имени команды указан целевой размер через # (например, Спортинг##550), применяется выражение масштабирования:
if (width > height) {
max_size = width;
} else {
max_size = height;
}
var real_size = 550 / max_size * 100;
[real_size, real_size]
Пример структуры слоёв в After Effects
Ниже представлен рекомендуемый порядок слоёв в композиции. Порядок важен для правильного наложения элементов.
📁 main (композиция)
├── 🎬 TOP (видео слой) # Видео-оверлей (обязательный)
├── 📝 TEAMS (текстовый слой) # Имена команд (обязательный)
├── 📝 LEAGUE (текстовый слой) # Название лиги (обязательный)
├── 📝 SPORT (текстовый слой) # Вид спорта (обязательный)
├── 📝 DATA (текстовый слой) # Дата (обязательный)
├── 📝 TIME (текстовый слой) # Время (только SINGLE)
├── 📝 TIME_H (текстовый слой) # Часы (только DOUBLE)
├── 📝 TIME_M (текстовый слой) # Минуты (только DOUBLE)
├── 🖼️ CHANELL (слой изображения) # Логотип канала (обязательный)
├── 🖼️ TEAM_A_LOGO (слой изображения) # Логотип команды A (обязательный)
├── 🖼️ TEAM_B_LOGO (слой изображения) # Логотип команды B (только DOUBLE)
└── 🖼️ BOTTOM (слой изображения) # Фоновый слой (опционально)
Формат проекта и совместимость с After Effects
Поддерживаемые форматы проектов:
.aep— стандартный бинарный формат After Effects (рекомендуется).aepx— XML-формат проекта (поддерживается с AE CC 2015)
Совместимость версий After Effects:
| Версия After Effects | Поддерживаемые форматы | Особенности |
|---|---|---|
| CS 5.5 | .aep |
Базовая поддержка |
| CC / CC 2014 | .aep |
Полная поддержка |
| CC 2015 - CC 2019 | .aep, .aepx |
Добавлена поддержка XML формата .aepx |
| CC 2020 - CC 2022 | .aep, .aepx |
Рекомендуется использовать .aep |
| CC 2023 и новее | .aep, .aepx |
Требуется настройка Output Module (см. ниже) |
⚠️ Важно для After Effects 2023+:
В версиях After Effects 2023 и новее критически важно настроить Output Module в шаблоне проекта. Бинарный файл рендеринга (
aerender) не будет обрабатывать композицию без явно указанного модуля вывода, даже если в проекте используется модуль по умолчанию.AE Anons автоматически решает эту проблему, используя параметры
TEMPLATE_OUTPUT_MODULEиTEMPLATE_OUTPUT_EXTиз.envфайла. Убедитесь, что эти значения соответствуют настройкам вашего шаблона.
Настройки композиции
| Параметр | Переменная окружения | Пример значения | Описание |
|---|---|---|---|
| Имя композиции | TEMPLATE_COMPOSITION |
main |
Имя главной композиции в проекте AE |
| Выходной модуль | TEMPLATE_OUTPUT_MODULE |
h264 |
Имя модуля вывода в AE |
| Расширение выходного файла | TEMPLATE_OUTPUT_EXT |
mp4 |
Расширение выходного файла |
Рекомендации по выбору формата:
- Используйте
.aepдля максимальной совместимости со всеми версиями AE - Версия After Effects на worker-машине должна быть не ниже версии, в которой создан проект
- Для AE 2023+ убедитесь, что в шаблоне настроен Output Module с именем, указанным в
TEMPLATE_OUTPUT_MODULE
Источники:
Устранение неисправностей
Частые проблемы
Ошибка подключения к NAS
- Проверьте, что
NAS_FQDNвключает протокол и порт (например,https://nas.example.com:5001) - Проверьте сетевую связность с NAS
- Убедитесь, что сервисы File Station и Office включены
Файл не найден
- Убедитесь, что путь в
NAS_FILEточно соответствует пути в Synology Drive - Путь должен начинаться с
/Team Folder/для рабочих папок - Проверьте права доступа к файлу для учетной записи сервиса
Ошибка отправки задания Nexrender
- Подтвердите доступность сервера Nexrender
- Убедитесь, что
NEXRENDER_API_URLправильный - Проверьте существование файлов шаблонов на узлах рендеринга
Режим отладки
Включите подробное логирование для детального анализа:
RUST_LOG=debug ./target/release/ae_anons
Это выведет:
- Детали API запросов/ответов
- Информацию о парсинге листов
- Детали создания заданий
- Процесс разрешения ресурсов
Возможные ограничения по производительности
- Большие таблицы: Ограничение обработки до 10,000 строк на лист
- Задержка сети: Загрузка файлов с NAS может занимать время для больших файлов
- Параллельные задания: Nexrender управляет очередью заданий внутренне
Примечания по безопасности
- Храните учетные данные только в файле
.env(исключен из git) - Используйте специальные аккаунты с минимально необходимыми правами
- Сессии Synology завершаются после выполнения
- HTTPS рекомендуется для подключений NAS в продакшене
Разработка
Структура кода
ae_anons/
├── .gitignore
├── .env.example
├── Cargo.toml
├── LICENSE
├── README.md
├── assets/
│ └── logo.png
└── src/
├── main.rs # Точка входа, CLI
├── config.rs # Конфигурация из .env
├── nexrender.rs # Модели заданий Nexrender
├── synology.rs # Клиент Synology API
├── processor.rs # Логика обработки
├── web.rs # Веб-сервер и API
└── static/
├── index.html # Веб-интерфейс
└── style.css # Стили
Зависимости
Основные зависимости
| Crate | Версия | Назначение |
|---|---|---|
| reqwest | 0.12 | HTTP клиент для коммуникации с API |
| serde / serde_json | 1.0 | Сериализация и десериализация JSON |
| calamine | 0.26 | Парсинг файлов Excel (.xlsx, .xls) |
| chrono | 0.4 | Обработка дат и времени |
| tokio | 1.0 | Асинхронная среда выполнения |
| dotenv | 0.15 | Загрузка конфигурации из .env файла |
| log / env_logger | 0.4/0.11 | Система логирования с уровнями |
| thiserror | 2.0 | Эргономичные определения типов ошибок |
| anyhow | 1.0 | Упрощённая обработка ошибок |
| regex | 1.11 | Регулярные выражения |
| urlencoding | 2.1 | Кодирование URL для API запросов |
| bytes | 1.9 | Работа с байтовыми данными |
| futures | 0.3 | Асинхронные примитивы |
Веб-сервер и CLI
| Crate | Версия | Назначение |
|---|---|---|
| axum | 0.8 | Веб-фреймворк для REST API |
| tower | 0.5 | Промежуточное ПО для веб-сервера |
| tower-http | 0.6 | HTTP утилиты (CORS, статика, трассировка) |
| askama | 0.15 | Шаблонизация (опционально) |
| clap | 4.5 | Парсинг аргументов командной строки |
Платформозависимые зависимости
| Crate | Версия | Платформа | Назначение |
|---|---|---|---|
| openssl | 0.10 | Linux | Криптография для HTTPS (vendored) |
🙏 Благодарности
Особая благодарность проекту Nexrender (@inlife и контрибьюторам) за создание надёжной платформы для автоматизации After Effects.
Лицензия
AE Anons — License
Nexrender — MIT License
Обе лицензии MIT обеспечивают полную свободу использования и модификации кода.
Разрешается:
- ✅ Использовать в коммерческих целях
- ✅ Изменять исходный код
- ✅ Распространять копии
- ✅ Использовать приватно
Требуется:
- Сохранять копирайт и текст лицензии
Поддержка
Для вопросов и запросов функций обращайтесь:
История изменений
v0.2.2 (текущая)
-
Исправлено отображение имён выходных файлов в веб-интерфейсе
-
Улучшена цветовая схема
-
Добавлена сортировка по всем колонкам
-
Вынесены стили в отдельный CSS файл
v0.2.0
-
Добавлен веб-интерфейс для управления заданиями
-
Реализован REST API
-
Добавлена поддержка тёмной/светлой темы
-
Автообновление статуса заданий
-
Возможность остановки всех активных заданий
v0.1.1
-
Оптимизирована работа с памятью
-
Убрана функция создания .json
v0.1.0
-
Первый выпуск
-
Интеграция с Synology Office
-
Базовая генерация заданий Nexrender
-
Парсинг Excel с динамическим обнаружением листов
Made with 🦀 Rust and ☕ coffee
