[Из песочницы] Создание сторис для Instagram из PHP

Вступление


В последнее время люди более охотно смотрят в социальных сетяx видео, нежели просматривают фотографии. Сторис в инстаграм набирает в 3–4 раза больше просмотров, чем просто выложенная фотография.

Ну и конечно же, не перестаём забывать, что социальные сети это не только себя показать, других посмотреть, но и продвижение своих товаров, услуг и т.д. Мы уже давно научились постить во вконтакте свежеопубликованную новость с сайта. А что если пойти дальше? Что если подавать эту информацию как видео? Или выкладывать интересные видео-сторис в инстаграм для привлечения большего внимания аудитории?

Так мне в голову пришла идея о создании библиотеки, которая позволяла бы создавать короткие видео-ролики из фотографий, текста и анимации этих объектов. Да, кто-то может сказать, что сервисы, которые позволяют это делать, уже есть и зачем придумывать велосипед? Во-первых — хочу, во-вторых — могу, в третьих — это будет бесплатно.

Эта статья о том, как работать с библиотекой, как создавать свои собственные сторис из PHP.

Ограничения


Сразу стоит сказать, что библиотека использует FFmpeg для генерации финального видео-файла. FFmpeg обязательно должен быть установлен на сервере. Возможно в будущем, будет вариант генерации сторис как gif-файл, но для себя я выбрал именно видео-файл, как результат работы.

Подготовка


Библиотека устанавливается через композер

composer require borodin-vasiliy/php-stories


Создание сторис


Настало время создать свою собственную сторис. Например, мы хотим видеть фоном фотографию котёнка, которая немного приближается на протяжении всего сторис и отобразить 2 текста на ней с анимацией появления. Легко!

Инициализация сторис
// Мы хотим создать 5 секундное сторис размерами 720x1280
$stories = new Stories([
        "width" => 720,
        "height" => 1280,
        "duration" => 5
    ]);



Как можете видеть, все параметры переданы как массив. На данный момент можно изменять:

  • «width» — Ширина сторис в пикселях
  • «height» — Высота в пикселях
  • «duration» — Продолжительность в секундах
  • «fps» — Количество кадров в секунду, по стандарту — 30


Далее нам нужно добавить 3 объекта (картинку и 2 текста) на наше будущее сторис. На данный момент библиотека позволяет добавлять 4 типа разных объектов — картинка, текст, элепс, прямоугольник. Для каждого объекта предусмотрен свой метод, аргумент метода — массив из параметров добавляемого объекта.

Объекты имеют как общие параметры:

  • «top» — позиция объекта от верхнего края сторис
  • «left» — позиция элемента от левого края сторис
  • «opacity» — прозрачность, как в css [0… 1]
  • «rotate» — угол поворота объекта [0… 359]
  • «z-index» — слой, как z-index в css — чем больше, тем выше слоем на кадре будет располагаться элемент
  • «start» — секунда, когда элемент должен быть добавлен на сторис
  • «end» — секунда, когда элемент должен быть убран со сторис


Так и уникальные для каждого типа объекта, например, для картинки:

  • «path» — Путь до картинки, которую хотим добавить
  • «scale» — Множитель размера изображения (приближение)


Добавление картинки на сторис
// Путь до файла с котиком
$main_image = $dir."/images/1.jpg";
// Получим размеры картинки)
list($image_width, $image_height) = getimagesize($main_image);
// Посчитаем, каким должно быть приближение для картинки, что бы она покрыла весь сторис
$image_start_scale = round(1280 / $image_height, 1);

// Добавление картинки
$stories->addImage([
        "path" => $main_image,
        "top" => round(-1 * ($image_height * $image_start_scale - $stories_height) / 2), // Вычислим параметр отступа сверху при текущем приближении
        "left" => round(-1 * ($image_width * $image_start_scale - $stories_width) / 2), // Вычислим параметр отступа слева при текущем приближении
        "scale" => $image_start_scale
    ]);



Готово! Если прямо сейчас сгенерировать сторис, то 5 секунд мы будем любоваться котиком. Но я обещал, что будет анимация, давайте добавим её.

Анимация для объекта добавляется с помощью отдельного метода, аргументом которого являются массив параметров, к которым должен прийти объект. Анимаций для одного объекта может быть сколько угодно. Стоит сказать, что синтаксис библиотеки подразумевает использование Fluent Interface.

Добавление картинки и анимации
// Путь до файла с котиком
$main_image = $dir."/images/1.jpg";
// Получим размеры картинки)
list($image_width, $image_height) = getimagesize($main_image);
// Посчитаем, каким должно быть приближение для картинки, что бы она покрыла весь сторис
$image_start_scale = round(1280 / $image_height, 1);
// 
$image_end_scale = $image_start_scale + 0.5;

// Добавление картинки с анимацией
$stories->addImage([
        "path" => $main_image,
        "top" => round(-1 * ($image_height * $image_start_scale - $stories_height) / 2), // Вычислим параметр отступа сверху при текущем приближении
        "left" => round(-1 * ($image_width * $image_start_scale - $stories_width) / 2), // Вычислим параметр отступа слева при текущем приближении
        "scale" => $image_start_scale
    ])->addAnimation([
        "top" => round(-1 * ($image_height * $image_end_scale - $stories_height) / 2), // Вычислим финальное местоположение картинки с учетом финального приближения
        "left" => round(-1 * ($image_width * $image_end_scale - $stories_width) / 2),// Вычислим финальное местоположение картинки с учетом финального приближения
        "scale" => $image_end_scale,
    ]);



Как вы могли заметить, для добавления анимации используется метод addAnimation. Обязательные параметры для анимации:

  • «start» — Секунда, когда должна начаться анимация. Если не задана, анимация начнётся в момент добавления объекта
  • «duration» — Продолжительность анимации в секундах


Массив параметров, на которые он может воздействовать анимация:

  • «top»
  • «left»
  • «opacity»
  • «rotate»
  • «scale»
  • «width»
  • «height»


Добавление текста
// Добавление заголовка
$stories->addText([
        "text" => "Hello world!",
        "path" => $dir."/fonts/helvetica.ttf",
        "size" => 130,
        "color" => "#ffffff",
        "width" => 620,
        "top" => 200,
        "left" => 50,
        "opacity" => 0,
        "shadow" => [
            "color" => "#000000",
            "top" => 4,
            "left" => 4
        ]
    ])->addAnimation([
        "duration" => 1,
        "opacity" => 1
    ])->addAnimation([
        "start" => 4.5,
        "duration" => 0.5,
        "opacity" => 0
    ]);

// Добавление текста
$stories->addText([
        "text" => "This is a test of function adding text",
        "path" => $dir."/fonts/helvetica.ttf",
        "size" => 100,
        "color" => "#ffffff",
        "width" => 620,
        "top" => 750,
        "left" => 50,
        "start" => 0.5,
        "opacity" => 0,
        "shadow" => [
            "color" => "#000000",
            "top" => 4,
            "left" => 4
        ]
    ])->addAnimation([
        "duration" => 1,
        "opacity" => 1
    ])->addAnimation([
        "start" => 4.5,
        "duration" => 0.5,
        "opacity" => 0
    ]);



Текст имеет свои уникальные параметры:

  • «text» — текст, который вы хотите вывести — обязательно
  • «path» — путь до шрифта (.ttf) — обязательно
  • «size» — размер шрифта
  • «color» — цвет, например »#ffffff»
  • «width» — ширина блока текста, если задана, то текст автоматически будет разбит на строки
  • «align» — выравнивание текста [left, center, right]
  • «shadow» — тень


Тень это так же массив параметров:

  • «color» — цвет тени
  • «top» — отступ сверху
  • «left» — отступ слева


Генерация сторис
$file_hash = $stories->generate("/tmp");



В результате мы получаем имя файла, который находится во временной папке, переданной как аргумент.

Результат работы


khyg2cy_9yemzeksskxu9jsd1ro.gif

Стоит сказать, что скорость создания сторис не велика, на хорошем компьютере 5и секундный ролик генерируется порядка минуты, на простеньком сервере более 3х минут.

Планы по развитию


  • Добавлении стандартных сценариев анимации, для сокращения кода
  • Текстовые анимации (появление построчно и т.д.)
  • Фон для текста


Надеюсь, кому-то подобная библиотека будет полезна. Буду рад услышать критику и пожелания в функционале.

Git-репозиторий

© Habrahabr.ru