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

Комментарии (2)


  1. NikiPo
    25.07.2025 07:13

    Почему выбор остановили на Adobe After Effects?
    Были идеи как реализовать такое через FFMpeg или другой опенсорс проект?


    1. AndrFP Автор
      25.07.2025 07:13

      Дело в том, что шаблоны, которые мы использовали для создания рекламы, в основном были именно в After Effects и на сегодняшний день это самое удобное приложение для создания шейповой анимации. Нам оставалось только сделать автоматизацию импорта файлов и обратки композиций. FFmpeg активно используется для пакетной обработки видеофайлов внутри Fix Encoder.

      Если же интересно, почему мы не обрабатываем внутри FFmpeg телевизионные форматы, то ответ такой: в течение долгого времени мы тестировали форматы через FFmpeg и возникало много ошибок (FFmpeg может обработать не все параметры для ТВ), поэтому был создан Fix Link. Поскольку шаблоны для Media Encoder уже были готовы, оставалось автоматизовать обработку видеороликов внутри Media Encoder , решение - Fix Link.