# AE Anons - Автоматизированный генератор спортивных анонсов в After Effects

AE Anons Logo

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Rust](https://img.shields.io/badge/Rust-1.70%2B-orange.svg)](https://www.rust-lang.org/) [![Status](https://img.shields.io/badge/status-production-green.svg)](https://git.tvstart.ru/lexx/AE_Anons) Автоматизированная система для создания спортивных анонсов с использованием шаблонов After Effects через Nexrender, с данными из электронных таблиц Synology Office. ## Новое в версии v0.2.4 - Групповая отправка заданий по 3 (оригинал + today + tomorrow) для сохранения порядка в очереди - Улучшена читаемость логов отправки (добавлен UID) ## Обзор AE Anons — это CLI-утилита и веб-сервер на Rust, которая выступает как **интеллектуальный генератор заданий** для [Nexrender](https://github.com/inlife/nexrender) — опенсорсного оркестратора рендеринга After Effects (лицензия MIT). ### Режимы работы 1. **Однократная обработка** (`--once` или без флагов): - Подключение к NAS Synology - Парсинг Excel данных - Генерация и отправка заданий Nexrender - Мониторинг завершения и выход 2. **Веб-сервер** (`--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. Клонирование репозитория ```bash git clone https://git.tvstart.ru/lexx/AE_Anons.git cd ae_anons ``` ### 2. Сборка проекта ```bash cargo build --release ``` ### 3. Настройка окружения Скопируйте пример конфигурации и заполните своими данными: ```bash cp .env.example .env ``` Затем отредактируйте файл .env: См. раздел Конфигурация для подробной информации. ## Использование ### Однократная обработка ```bash # Запуск с настройками по умолчанию ./target/release/ae_anons # Явно указать однократный режим ./target/release/ae_anons --once # С отладочным логированием RUST_LOG=debug ./target/release/ae_anons ``` ### Веб-сервер ```bash # Запуск веб-интерфейса на порту по умолчанию (3000) ./target/release/ae_anons --web # Или с указанием другого порта через .env файл # WEB_PORT=8080 ./target/release/ae_anons --web ``` ## Веб-интерфейс После запуска веб-сервера откройте браузер: - Главная страница: - 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 вызовов ```bash 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` ```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| ### Формат имен команд Имена команд поддерживают два типа разделителей хэш #: 1. **Первый хеш**: Уникальный идентификатор для команд с одинаковыми названиями в одном виде спорта, или одинаковым названием в разных видах спорта. Примеры: - `Динамо#Футбол`, `Динамо#Волейбол` - Одно название разный вид спорта - `Спартак#ЖенскийФ`, `Спартак#МужскойФ` Одно название _разный_ вид спорта 1. **Второй хеш**: Целевой размер в пикселях для масштабирования логотипа Формат: `DisplayName#UniqueID#TargetSize` Примеры: - `Галатасарай#Turki` - только уникальный идентификатор - `Сомбатей##400` - только целевой размер (обратите внимание на двойной хеш) - `Спортинг#ll#550` - оба идентификатор и целевой размер **Важно**: Обрабатывается **только второй хеш** для масштабирования логотипа. Если уникальный идентификатор не требуется, используйте двойной хеш ## перед целевым размером. ## Выходные файлы ### Рендеренные видео Рендерные видео сохраняются в `OUTPUT_FOLDER` по следующему шаблону именования: ```shell YYYYMMDD_Sport_League_TeamA_TeamB_Channel[_Variant].mp4 ``` Имена файлов транслитерируются в латиницу. **Примеры:** - `20260228_Volleyball_Championship-Turkey-Women_Beşiktaş_Galatasaray_TRIUMPH.mp4` - `20260228_Volleyball_Championship-Turkey-Women_Beşiktaş_Galatasaray_TRIUMPH_Today.mp4` - `20260228_Volleyball_Championship-Turkey-Women_Beşiktaş_Galatasaray_TRIUMPH_Tomorrow.mp4` ## Рабочий процесс 1. **Аутентификация**: Подключение к NAS Synology с использованием предоставленных учетных данных 2. **Получение файла**: Поиск и экспорт указанного файла .osheet в Excel 3. **Парсинг данных**: Чтение всех листов и структурирование данных 4. **Разрешение ресурсов**: Сопоставление видов спорта, команд и каналов с визуальными элементами 5. **Генерация заданий**: Создание заданий Nexrender для каждой активной строки с вариантами 6. **Очистка**: Удаление завершенных/неудачных заданий из предыдущих запусков 7. **Отправка**: Отправка заданий на API Nexrender 8. **Мониторинг**: Слежение за прогрессом выполнения до завершения 9. **Завершение сеанса**: Закрытие сессии 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`), применяется выражение масштабирования: ```javascript if (width > height) { max_size = width; } else { max_size = height; } var real_size = 550 / max_size * 100; [real_size, real_size] ``` ### Пример структуры слоёв в After Effects Ниже представлен рекомендуемый порядок слоёв в композиции. Порядок важен для правильного наложения элементов. ```text 📁 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` | Расширение выходного файла | **Рекомендации по выбору формата:** 1. Используйте `.aep` для максимальной совместимости со всеми версиями AE 2. Версия After Effects на worker-машине должна быть не ниже версии, в которой создан проект 3. Для AE 2023+ убедитесь, что в шаблоне настроен Output Module с именем, указанным в `TEMPLATE_OUTPUT_MODULE` **Источники:** - [Nexrender - Tested with After Effects versions](https://github.com/inlife/nexrender#tested-with) - [Adobe Aerender documentation](https://helpx.adobe.com/after-effects/using/automated-rendering-network-rendering.html) ## Устранение неисправностей ### Частые проблемы #### Ошибка подключения к NAS - Проверьте, что `NAS_FQDN` включает протокол и порт (например, `https://nas.example.com:5001`) - Проверьте сетевую связность с NAS - Убедитесь, что сервисы File Station и Office включены #### Файл не найден - Убедитесь, что путь в `NAS_FILE` точно соответствует пути в Synology Drive - Путь должен начинаться с `/Team Folder/` для рабочих папок - Проверьте права доступа к файлу для учетной записи сервиса #### Ошибка отправки задания Nexrender - Подтвердите доступность сервера Nexrender - Убедитесь, что `NEXRENDER_API_URL` правильный - Проверьте существование файлов шаблонов на узлах рендеринга ### Режим отладки Включите подробное логирование для детального анализа: ```bash RUST_LOG=debug ./target/release/ae_anons ``` Это выведет: - Детали API запросов/ответов - Информацию о парсинге листов - Детали создания заданий - Процесс разрешения ресурсов ## Возможные ограничения по производительности - **Большие таблицы**: Ограничение обработки до 10,000 строк на лист - **Задержка сети**: Загрузка файлов с NAS может занимать время для больших файлов - **Параллельные задания**: Nexrender управляет очередью заданий внутренне ## Примечания по безопасности - Храните учетные данные только в файле `.env` (исключен из git) - Используйте специальные аккаунты с минимально необходимыми правами - Сессии Synology завершаются после выполнения - HTTPS рекомендуется для подключений NAS в продакшене ## Разработка ### Структура кода ```shell 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 Особая благодарность проекту **[Nexrender](https://github.com/inlife/nexrender)** ([@inlife](https://github.com/inlife) и контрибьюторам) за создание надёжной платформы для автоматизации After Effects. ### Font Awesome Free 6.4.0 Веб-интерфейс использует иконки и шрифты **Font Awesome Free**: - **Иконки**: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) - **Шрифты**: [SIL OFL 1.1](https://scripts.sil.org/OFL) © 2023 Fonticons, Inc. — ## Лицензия **AE Anons** — [License](LICENSE) **Nexrender** — [MIT License](https://github.com/inlife/nexrender/blob/master/LICENSE) Обе лицензии MIT обеспечивают полную свободу использования и модификации кода. **Разрешается:** - ✅ Использовать в коммерческих целях - ✅ Изменять исходный код - ✅ Распространять копии - ✅ Использовать приватно **Требуется:** - Сохранять копирайт и текст лицензии ## Поддержка Для вопросов и запросов функций обращайтесь: - - [README.md](https://git.tvstart.ru/lexx/AE_Anons) ## История изменений ### v0.2.4 (текущая) - Групповая отправка заданий по 3 (оригинал + today + tomorrow) для сохранения порядка в очереди - Улучшена читаемость логов отправки (добавлен UID) ### v0.2.3 - Веб-интерфейс с настраиваемым портом (WEB_PORT) - Улучшенное debug-логирование - Исправлена обработка UNC/SMB путей - Нормализация множественных пробелов в именах файлов" ### 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