Как мы в Fix Price автоматизировали создание рекламных видео

от автора

Привет, Хабр! Меня зовут Андрей Денисов и я видеодизайнер 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.


ссылка на оригинал статьи https://habr.com/ru/articles/930974/