AE Anons - Автономный генератор спортивных анонсов в After Effects
AE Anons — полностью автономная (standalone) система для создания спортивных анонсов с использованием шаблонов After Effects через Nexrender. Все данные берутся из электронных таблиц Synology Office, рендеринг выполняется локально, управление заданиями происходит через встроенный веб-интерфейс с мгновенными обновлениями. Система не требует доступа в интернет — все ресурсы (иконки, стили, шрифты) встроены в бинарный файл.
Новое в версии v0.3.0
- WebSocket — мгновенные обновления списка заданий (без устаревшего polling каждые 60 секунд)
- SQLite — хранение истории заданий и статуса апрува
- Просмотр видео прямо в веб-интерфейсе (по ссылке на готовый файл)
- Апрув заданий с копированием видео на SMB-шару (без монтирования, с поддержкой Active Directory)
- Уведомления в реальном времени о старте/завершении генерации, ошибках
- Улучшенный веб-интерфейс с кнопками апрува и иконками превью
- Оптимизация памяти — строки таблицы обрабатываются потоково, неиспользуемые логотипы и ассеты удаляются после генерации. Пиковое потребление памяти достигается только в момент загрузки и парсинга Excel, после чего память освобождается. Это позволяет работать с таблицами большого объёма (десятки тысяч строк) и обеспечивает стабильную работу в режиме долгоживущего сервиса.
- Полная автономность — все статические ресурсы (HTML, CSS, Font Awesome, логотип, favicon) встроены в бинарный файл.
Обзор
AE Anons — это CLI-утилита и веб-сервер на Rust, которая выступает как интеллектуальный генератор заданий для Nexrender — опенсорсного оркестратора рендеринга After Effects.
Режимы работы
-
Однократная обработка (
--onceили без флагов):- Подключение к NAS Synology
- Парсинг Excel данных
- Генерация и отправка заданий Nexrender
- Мониторинг завершения и выход
-
Веб-сервер (
--web):- Запуск веб-интерфейса на порту
:3000(настраивается) - Управление заданиями через браузер с WebSocket-обновлениями
- Просмотр видео и апрув готовых роликов
- Запуск веб-интерфейса на порту
Особенности
- Полная автономность — не требует выхода в интернет, все ресурсы встроены в бинарник
- Интеграция с Synology — аутентификация и загрузка файлов с NAS Synology (локальные и AD-учётные записи)
- Экспорт офисных таблиц — автоматическое преобразование
.osheetв Excel - Гибкий парсинг данных — динамический парсинг листов с обнаружением заголовков
- Множественная генерация вариантов — "Сегодня", "Завтра" и датированные версии
- Умное управление логотипами — автоматическое разрешение и масштабирование
- Веб-интерфейс с WebSocket — мгновенные обновления, просмотр видео, апрув
- REST API — программное управление заданиями
- SQLite — хранение истории и статуса апрува
- Поддержка SMB — копирование утверждённых видео на сетевую шару (с AD-аутентификацией)
- Профессиональное логирование — структурированный журнал с настройкой уровня
- Эффективная работа с памятью — потоковая обработка строк, своевременное удаление неиспользуемых данных (логотипы, ассеты) позволяет обрабатывать таблицы с десятками тысяч строк без утечек памяти
Предварительные требования
- Rust 1.70 или выше
- Доступ к NAS Synology с пакетами File Station и Office (локальный или доменный пользователь)
- Экземпляр server и worker (не менее одного) Nexrender
- Шаблоны After Effects (формат .aep или .aepx, совместимые с версией AE на worker)
- (Для апрува) Доступ к SMB-шаре с правами на запись
Установка
git clone https://git.example.com/team/ae_anons.git
cd ae_anons
cargo build --release
cp .env.example .env
# отредактируйте .env согласно вашей инфраструктуре
Конфигурация
Все настройки задаются через переменные окружения в файле .env.
Основные переменные
| Переменная | Обязательна | Описание |
|---|---|---|
NAS_FQDN |
Да | URL Synology NAS (*) |
NAS_USER |
Да | Имя пользователя (локального или доменного, например DOMAIN\username) |
NAS_PASS |
Да | Пароль |
NAS_FILE |
Да | Путь к .osheet файлу на NAS (например, /Team Folder/schedule.osheet) |
NEXRENDER_API_URL |
Да | API Nexrender (например, http://nexrender:3050/api/v1/jobs) |
OUTPUT_FOLDER |
Да | Папка, куда Nexrender сохраняет готовые видео (локальный путь) |
TEMPLATE_DOUBLE_SRC |
Да | Путь к AEP-шаблону для двух команд (например, file:///templates/double.aepx) |
TEMPLATE_SINGLE_SRC |
Да | Путь к AEP-шаблону для одной команды |
TEMPLATE_COMPOSITION |
Да | Имя композиции в проекте AE |
TEMPLATE_OUTPUT_MODULE |
Да | Имя модуля вывода в AE |
TEMPLATE_OUTPUT_EXT |
Да | Расширение выходного файла (например, mp4) |
WEB_PORT |
Нет | Порт веб-сервера (по умолчанию 3000) |
RUST_LOG |
Нет | Уровень логирования (info, debug, trace) |
SMB_UPLOAD_URL |
Да(**) | SMB-URL для апрува (например, smb://storage/approved) |
SMB_USERNAME |
Да(**) | Имя пользователя для SMB (локальный или DOMAIN\user) |
SMB_PASSWORD |
Да(**) | Пароль для SMB |
DATABASE_URL |
Нет | Путь к SQLite БД (по умолчанию sqlite:ae_anons.db) |
(*) — для
NAS_FQDNможно указывать протоколhttp://илиhttps://. Безопаснееhttps, хотя для локальной сети допустим иhttp. Если NAS доступен по стандартному HTTPS-порту 443, протокол можно опустить (например,nas.company.local). Иначе указывайте полный URL с портом:https://nas.company.local:5001илиhttp://nas.local:5000.(**) — обязательно, если используется функция апрува (веб-режим). В режиме
--onceапрув не требуется.
Пример файла .env
# Synology NAS
NAS_FQDN="https://nas.company.local:5001"
NAS_USER="DOMAIN\\service_account"
NAS_PASS="strongpassword"
NAS_FILE="/Team Folder/Anonsy/sport.osheet"
# Nexrender
NEXRENDER_API_URL="http://render-01:3050/api/v1/jobs"
OUTPUT_FOLDER="/mnt/nexrender/output"
# After Effects Templates
TEMPLATE_DOUBLE_SRC="file:///mnt/templates/double_team.aepx"
TEMPLATE_SINGLE_SRC="file:///mnt/templates/single_team.aepx"
TEMPLATE_COMPOSITION="main"
TEMPLATE_OUTPUT_MODULE="h264"
TEMPLATE_OUTPUT_EXT="mp4"
# Web server
WEB_PORT="3000"
RUST_LOG="info"
# SMB для апрува (AD-совместимо)
SMB_UPLOAD_URL="smb://storage.company.local/approved_videos"
SMB_USERNAME="DOMAIN\\service_account"
SMB_PASSWORD="strongpassword"
# Database
DATABASE_URL="sqlite:/var/lib/ae_anons/ae_anons.db"
Примечание об аутентификации:
Synology API и SMB-библиотекаsmbподдерживают как локальных пользователей NAS, так и доменных (Active Directory). Для доменных пользователей используйте форматDOMAIN\username(обратный слеш необходимо экранировать в.envкак\\). Проверено на Synology DSM 7.x и Samba AD.
Использование
Однократная обработка (cron или ручной запуск)
./target/release/ae_anons --once
Веб-сервер (интерактивный режим)
./target/release/ae_anons --web
После запуска откройте браузер: http://localhost:3000
Веб-интерфейс
- Главная страница — таблица всех заданий с полями: UID, имя файла, статус, превью (иконка видео), кнопка апрува, дата создания.
- Обновления в реальном времени через WebSocket — статусы заданий меняются мгновенно без перезагрузки страницы.
- Кнопка «Generate» — запускает парсинг таблицы Synology и создание новых заданий. Во время генерации кнопка блокируется, при завершении приходит уведомление.
- Кнопка «Cleanup» — удаляет из Nexrender задания со статусом finished/error.
- Кнопка «Stop all» — останавливает все активные (queued/started/processing) задания.
- Просмотр видео — клик по иконке видео открывает готовый файл в новой вкладке (поддерживается любой браузерный просмотр MP4).
- Апрув — клик по ✅ копирует видео на SMB-шару (путь из
SMB_UPLOAD_URL) и помечает задание как approved. Повторный апрув невозможен.
API эндпоинты
GET /api/jobs— список всех заданий (из SQLite)POST /api/generate— запуск генерацииPOST /api/cleanup— очистка завершённыхPOST /api/jobs/stop-all— остановка активныхGET /api/status— статус сервераGET /api/video/:uid— просмотр видеофайлаPOST /api/approve/:uid— апрув (копирование на SMB)WS /ws— WebSocket для получения событий (JobUpdated,GenerationStarted,GenerationFinished,Error)
Уровни логирования
RUST_LOG=debug ./ae_anons --web
- error — только критические ошибки
- warn — предупреждения
- info — стандартная информация (по умолчанию)
- debug — детали API-вызовов, парсинга, SMB-операций
- trace — максимальная детализация
Структура электронной таблицы
Файл 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
При апруве файл копируется в SMB-шару с тем же именем.
Рабочий процесс (веб-режим)
- Пользователь заполняет таблицу Synology Office.
- Нажимает «Generate» в веб-интерфейсе.
- Сервер аутентифицируется на NAS, скачивает и парсит Excel.
- Генерирует задания Nexrender, сохраняет их в SQLite и отправляет в Nexrender.
- WebSocket уведомляет клиент о новых заданиях.
- Nexrender рендерит видео, статус задания обновляется (периодический опрос или webhook).
- Когда видео готово, пользователь видит иконку превью, может посмотреть видео и нажать апрув.
- При апруве видео копируется на SMB-шару, задание помечается как approved.
Требования к шаблонам After Effects
Не изменились — все слои DATA, TIME_H, TIME_M, LEAGUE, SPORT, TEAMS, TEAM_A_LOGO, TEAM_B_LOGO, CHANELL, TOP должны присутствовать согласно типу шаблона (DOUBLE/SINGLE). Поддержка масштабирования логотипов через выражения After Effects — осталась.
Устранение неисправностей
WebSocket не работает
- Проверьте, что браузер поддерживает WebSocket (все современные поддерживают).
- При использовании прокси (nginx) необходимо настроить Upgrade заголовки.
Ошибка аутентификации на NAS для доменного пользователя
- Убедитесь, что в
.envуказаноDOMAIN\\username(двойной обратный слеш). - Проверьте, что NAS настроен на приём доменных учётных записей (DSM → Домен/LDAP).
Ошибка SMB подключения
- Проверьте доступность шары:
smbclient -U DOMAIN/username -L //storage/ - Убедитесь, что в URL используется
smb://протокол, путь без лишних слешей. - Время на сервере и клиенте должно быть синхронизировано (SMB требует этого).
БД SQLite блокирована
- При конкурентных запросах SQLite может выдавать
database is locked. Для веб-сервера с одним процессом это маловероятно. Если возникает — используйтеsqlite://:memory:для тестов или настройте WAL-режим.
Высокое потребление памяти
- Система спроектирована так, чтобы минимизировать удержание данных. Если вы наблюдаете рост памяти, убедитесь, что вы используете последнюю версию. При работе с очень большими таблицами (сотни тысяч строк) может потребоваться увеличить лимит строк в
processor.rs(константа 10000).
Разработка
Все статические ресурсы (HTML, CSS, шрифты Font Awesome, логотип, favicon) встроены в бинарник с помощью include_str! и include_bytes!. Для разработки можно редактировать файлы в src/static/, но при сборке они компилируются внутрь исполняемого файла.
Сборка для production
cargo build --release
strip target/release/ae_anons # уменьшает размер
Итоговый бинарник можно переносить на любой Linux-сервер без дополнительных зависимостей (кроме libc и openssl, если не используется статическая сборка).
Лицензия
AE Anons — MIT
Nexrender — MIT
Font Awesome Free — CC BY 4.0 (иконки) и SIL OFL 1.1 (шрифты)
Made with 🦀 Rust and ☕ coffee
