Привет, Хабр! Меня зовут Андрей Денисов и я видеодизайнер Fix Price. Сегодня я расскажу о нашем новом программном комплексе, который позволяет создавать ролики с рекламой наших товаров вдвое быстрее, чем раньше.
Наши магазины работают уже в 10 странах мира, а в России, Беларуси, Казахстане, мы регулярно размещаем разнообразные рекламные материалы в различных форматах. Подгонять ролики вручную под требования законодательства разных стран, особенности дизайна и форматы вещания очень затратно по времени. Также нужно учесть, что отдел рекламы должен готовить еженедельно не менее 80 роликов (это без учёта дополнительных акций, появления новых товаров и других событий).
Поэтому возникла необходимость найти решение, которое помогло бы не расширяя штат сотрудников, оптимизировать время производства шаблонных роликов. Базового программного решения на рынке не оказалось, в связи с этим мы командой глубже изучили возможности программного пакета adobe, что позволило мне попытаться разработать ПО самому и в последствии внедрить его в работу всей команде.
Fix Studio и её компоненты
Мы назвали программное обеспечение «Fix Studio». Оно состоит из нескольких компонентов и интегрировано в общий программный комплекс Adobe. Давайте познакомимся подробнее с этими компонентами.
Fix Tool
Представляет собой расширение для Adobe After Effects. Fix Tool позволяет автоматически обрабатывать данные из файлов Excel (названия, цены, фотографии и т. д.), работает в связке HTML, JavaScript, ExtendedScript в сочетании с ExtendScript. Фактически всё, что должен сделать монтажёр, — дать команду Fix Tool на обработку файла Excel, и программа автоматически разместит все элементы ролика, прописанные в файле, на нужных местах. Это позволяет сэкономить не менее часа на создании каждого видео.
Версия предыдущего года выглядела так:

Новая версия ещё в работе (на скрине демо-версия), но дизайн немного изменился:

Вот кусочки кода:
Когда FixTool начинает обработку, он проверяет наличие материалов с помощью следующих параметров:
const configList = [
{
label: "Фото OLV",
field: "ЛК (lk)",
basePath: "Z:\\\\!ДИЗАЙН-ВИДЕО ДМ\\\\КОЛЛЕКТ ФАЙЛЫ\\\\ФОТО ТОВАРОВ",
subfolder: "OLV",
extension: ".jpg"
},
В случае, если какие либо фото отсутствуют, то Fix Tool сообщит об этом с помощью функции:
checkMissingFiles(jsonData, configList, function (missing) {
const labels = Object.keys(missing);
if (labels.length > 0) {
let message = "";
labels.forEach(label => {
message += `Отсутствуют ${label} в соответствующих папках:\n`;
message += missing[label].join("\n") + "\n\n";
});
message += "Отправьте этот текст менеджеру по видео-контенту. Попробуйте выполнить операцию снова, когда файлы будут добавлены.";
showModal(message);
} else {
processExcelData(jsonData);
}
Далее FT начинает парсить excel таблицу:
const lk = nextRow["ЛК (lk)"] || "Нет данных";
const tradeName = nextRow["Торговое название 1"] || "Нет данных";
const tradeName2 = nextRow["Торговое название 2"] || "Нет данных";
const tagName = nextRow["Тэг"] || "Нет данных";
const price = nextRow["Цена"] || "Нет данных";
const phtvkl = nextRow["Фотовключение"] || "Нет данных";
batch.push(`${lk}|${tradeName}|${tradeName2}|${tagName}|${price}|${phtvkl}`);
Передача полученной информации в After Effects:
const combinedArgs = `10|${country}|${temptype}|${sogltype}|${nabivka}|${category}|${sound}|${batch.join("|")}`;
Внутри After Effects происходит обработка:
var parts = args.split('|');
var duration = parts[0]; // "10" или "5"
var country = parts[1];
var temptype = parts[2];
var sogltype = parts[3];
var nabivka = parts[4];
var category = parts[5];
var sound = parts[6];
И идёт определение композиций, которые будут использоваться для обработки:
// Определяем список основных композиций и вспомогательных композиций
if (duration === "10") {if (temptype.indexOf("LED") !== -1) {originalCompNames = ["240X720_10S_" + sogltype + "_" + temptype, "384X704_10S_" + sogltype + "_" + temptype]} else {
originalCompNames = ["16X9_10S_" + sogltype + "_" + temptype, "9X16_10S_" + sogltype + "_" + temptype]};
compsToDuplicate = ["PRICE1", "PRICE2", "PRICE3", "PRODUCT1", "PRODUCT2", "PRODUCT3", "PHTVKL1", "PHTVKL2", "PHTVKL3", "shutterstock", "Sound"];
}
Fix Encoder
Это приложение мы интегрировали в Adobe Media Encoder с помощью утилиты Fix Link. Оно создано на Python и активно использует библиотеку FFmpeg для пакетной обработки видеофайлов в разных форматах. Fix Encoder автоматизирует работу с метаданными и параметрами кадрирования. Но, в отличие от Media Encoder, где нам приходится отдельно применять пресеты и шаблоны к каждому ролику, в Fix Encoder достаточно указать папку с видеороликами, папку выгрузки и необходимый пресет.
Облегчает он работу и с не шаблонным, уникальным видео контентом. Раньше у дизайнеров много времени отнимало добавление логотипа и ценников в каждый ролик, причём нужно было учитывать форматы (для каждой страны — свой, где-то нужно сделать ролик без ценника и т.д.). Fix Encoder решил эту проблему благодаря пакетной обработки видео с учётом предустановленных настроек. В результате дизайнеры экономят более 90% времени, которое раньше уходило на последовательную обработку каждого видео. Теперь наглядно скринами:
Сам Fix Encoder выглядит просто, минималистично и «user-friendly»: имеет всего 3 кнопки и окно со списком элементов.

Когда пользователь нажимает кнопку «+», перед ним открывается окно с добавлением элемента в очередь.
В виде кода это выглядит следующим образом:
# Создание окна для выбора параметров
add_window = ctk.CTkToplevel(self)
add_window.title("Добавить в очередь")
# Устанавливаем владение мышью и клавиатурой для нового окна
add_window.grab_set()
Для разных пресетов есть разные условия, если пользователь забудет выбрать какой-либо из элементов, то ему придет оповещение:
# Проверка на наличие файла брифа только для пресетов "Новинки" и "ООН"
if current_preset in ["Новинки", "ООН"] and brief_file_label.cget("text") in ["Файл брифа не выбран", ""]:
tk.messagebox.showerror("Ошибка", "Пожалуйста, выберите файл брифа для выбранного пресета.")
return
# Проверка на наличие папки с видео
if video_folder_label.cget("text") in ["Папка с видео не выбрана", ""]:
tk.messagebox.showerror("Ошибка", "Пожалуйста, выберите папку с видео.")
return
# Проверка на наличие папки с видео
if output_folder_label.cget("text") in ["Папка выгрузки не выбрана", ""]:
tk.messagebox.showerror("Ошибка", "Пожалуйста, выберите папку выгрузки.")
return
После добавления элемента в очередь, пользователь видит его в списке элементов.
Также пользователь может открыть контекстное меню, кликнув конкретный элемент и нажав ПКМ:

Далее, когда пользователь нажимает на кнопку обработки, то Fix Encoder начинает проверять элементы на статус, если элемент в очереди имеет статус «В очереди», то он начинает его обработку, а после меняет статус элемента на «Выполнено», для большинства пресетов обычно используется библиотека FFmpeg, которая позволяет быстро обработать видеоролики:
if status == "В очереди" and preset == "LED 384x704":
# Выполняется рендер
video_folder_path = item[0]
output_folder_path = item[1]
path = os.path.join(f'{output_folder_path}\\LED')
os.makedirs(path, exist_ok=True)
for filename in os.listdir(video_folder_path):
if filename.endswith('.mp4'):
filename_without_ext, ext = os.path.splitext(filename)
subprocess.run(['ffmpeg', '-y', '-i', os.path.join(video_folder_path, filename), '-vf', 'scale=384x704', '-an', os.path.join(f'{output_folder_path}\\LED\\{filename_without_ext}.mp4')],creationflags=subprocess.CREATE_NO_WINDOW)
self.tree.item(i, values=item[:-1] + ["Выполнено"])
Если в обработку берется телевизионный формат, то Fix Encoder обращается к Fix Link следующим образом:
os.system('taskkill /im "Adobe Media Encoder.exe" /F')
# Выполняется рендер
video_folder_path = item[0]
output_folder_path = item[1]
# Путь к исполняемому файлу ExtendScript (Adobe Media Encoder)
extendscript_path = r'"%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\Adobe Media Encoder 2025.lnk"'
# Путь к вашему скрипту JSX
jsx_script_path = r'C:\FixStudio\bin\Utilites\FixLink.jsx'
# Путь к файлу, в который будут записаны данные
data_file_path = r'C:\FixStudio\bin\Utilites\data.txt'
# Значение переменной, которое нужно передать в скрипт JSX
# Записываем данные в файл
with open(data_file_path, 'w') as f:
f.writelines([video_folder_path + '\n',output_folder_path + '\n',"KZ"])
# Команда для запуска Adobe Media Encoder с передачей пути к файлу данных
Так как Adobe Media Encoder выполняет сценарии только один раз после запуска, то Fix Encoder закрывает его перед началом работы. И затем заново открывает, но уже с аргументом для запуска Fix Link.
В случае обработки новинок или ООН, Fix Encoder обращается к брифу, брифы заполняются менеджерами.
Fix Link
Эта утилита — связующее звено Fix Encoder с Media Encoder. Она позволяет автоматизировать процесс кодирования группы роликов и использовать все возможности Media Encoder внутри автоматизированных сценариев. Фактически Fix Link указывает Media Encoder на действия для выполнения: например, применить к видеороликам, расположенным в определенном месте, конкретный пресет, настройки и выгрузить их в определенную папку.
После запуска Adobe Media Encoder запускает Fix Link (который был указан ранее в качестве аргумента для запуска Adobe Media Encoder внутри Fix Encoder), который сообщает ему данные для обработки:
if (country === "RU") {
if (exporter) {
// Add each video file to the batch and apply the specified preset
for (var i = 0; i < videoFiles.length; i++) {
var wapfolder1 = new Folder(outfolder + "\\wap\\16x9");
var wapfolder2 = new Folder(outfolder + "\\wap\\FHD");
wapfolder1.create();
wapfolder2.create();
var videoFile = videoFiles[i];
var source = videoFile.fsName;
var destination1 = (outfolder + "\\wap\\16x9");
var destination2 = (outfolder + "\\wap\\FHD");
var preset1 = "C:\\FixStudio\\bin\\Utilites\\EPR\\RU\\SD_16-9_1.epr";
var preset2 = "C:\\FixStudio\\bin\\Utilites\\EPR\\RU\\FullHD.epr";
var matchSourceSettings = false; // optional
var writeFramesToDisk = false; // optional
var itemsToEncode = (videoFiles.length * 2);
var encoderWrapper = exporter.exportItem(
source,
destination1,
preset1,
matchSourceSettings,
writeFramesToDisk
);
После того, как Adobe Media Encoder заканчивает обработку, он закрывается:
if (encoderWrapper && encoderWrapper1) {
encoderWrapper.addEventListener(
"onEncodeFinished",
function (eventObj) {
itemsEncoded++; // Increment itemsEncoded when a file has finished encoding.
if (itemsEncoded === itemsToEncode) {
app.quit();
}
},
false
);
Пользователь не видит сам Fix Link, так как он всего лишь сообщает Media Encoder видео в обработку и ее параметры.
Пример ролика
Итак, Fix Studio обращается к брифу, собирает все необходимые данные из разных папок и файлов и размещает их в нужных местах видео согласно запрограммированному шаблону. Вот как это выглядит:



Это для понимания, сколько видеороликов требуется сделать. Раньше у дизайнера могло уйти несколько рабочих дней на выполнение данной задачи, а сейчас примерно 4-6 часов.
Преимущества Fix Studio
Главные достоинства разработки для сотрудников студии:
Быстрый запуск благодаря Fix Tool и импорту данных из Excel;
Автоматизация кодирования сотен файлов одновременно;
Полноценная интеграция с ТВ-форматами путём связывания Fix Encoder с Media Encoder через Fix Link.
В результате мы:
Получили колоссальную экономию времени;
Уменьшили влияние человеческого фактора при создании видеоконтента;
Обеспечили полноценную интеграцию Fix Studio с продуктами Adobe.