Вступление


В последнее время люди более охотно смотрят в социальных сетя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");


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

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




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

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


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

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

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

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


  1. sazareks
    17.01.2019 19:15

    Это всё круто, но каким способом вы публикуете в сам инстаграм? Не ручками же?


    1. Jangle_ru Автор
      17.01.2019 19:22

      До реальной публикации пока не дошёл, все время тратится на доработку библиотеки и её развитие. А с публикацией есть трудности?


      1. sazareks
        17.01.2019 19:25

        В целом нет, но иногда возникает трудность в подтверждении аккаунта инстаграм. Знаете, когда авторизируешься с другого IP инстаграм иногда может запрос смс делать или на почту, вот эти самые запросы хочется иногда иметь программно вызывать. Некоторые сервисы вроде так делают.


        1. Jangle_ru Автор
          17.01.2019 19:31

          Да, понимаю о чём вы, но в данной библиотеке я решал всё же другую проблему. Но об этой тоже можно задуматься


      1. mitgard
        17.01.2019 21:51

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


        1. zzzmmtt
          18.01.2019 10:00

          Апи то у них есть, но постинга сторис при беглом просмотре я там не увидел.


        1. CAJAX
          18.01.2019 19:53

          Оригинальная версия API закрыта с ноября. Есть новая, через Фейсбук. Там есть постинг фото для "Бизнес Партнёров Инстаграма", но постинга сторис там нет. Статус партнёра просто так не заполучить.


          При этом у инстаграма есть graphql для своего софта, который, в принципе реверсится.


  1. akdes
    17.01.2019 19:18

    Спасибо за работу и вклад в сообщество PHP разработки.
    Однако, при чём тут инста? По факту статья о создании видео файла с наложением текста и анмиции. По названию ожидал увидеть что-то иное, хотябы интеграцию инсты в скрипт, для дальнейшего авто постинга, как минимум.


    1. Jangle_ru Автор
      17.01.2019 19:20

      На самом деле долго думал над вектором, в котором двигаться. На деле, я для себя не нашёл применения этой библиотеки кроме как в социальных сетях. Но вы правы, на данный момент это просто создание видео из PHP. Инстаграм в заголовке взят как пример.


      1. akdes
        17.01.2019 20:29

        Я думаю название "Генерация/создание видео для статуса/Стори посредством пхп" было бы более приемлемым, благо статус — тема актуальная. ВК, инста, ватсэпп..


        Ну да ладно, рад что вообще ещё вижу PHP на хабре


  1. Taraflex
    17.01.2019 22:35

    Слишком долго кодом анимацию всю описывать.
    Для реального задачи лично я бы взял flash (уфф. предвкушаю волну негодования).
    В текстовых полях разместил бы плейсхолдеры в стиле {{{тут будет ваша реклама… тут пробелов на пару килобайт...}}}
    Распаковал бы полученный swf в несжатый формат.
    Через php заменил бы плейсхолдеры на требуемый текст обычными регулярками (просто открыв swf как обычный юникод текст).
    Отрендерил тем же ffmpeg полученный swf в mp4.


    1. Jangle_ru Автор
      17.01.2019 22:45

      Это если шаблон использования один, может и сработать, но для широкого использования точно не подойдёт


      1. Taraflex
        17.01.2019 23:08

        Почему не подойдет для широкого использования?
        Кодом анимацию прописывать еще дольше.
        Если хочется все «по-красивше» выполнить, без заглушек из пробелов, то можно заморочиться и завести на сервере (у вас все равно нативная зависимость от ffmpeg получается)
        www.redtamarin.com/about/description — виртуалка для flash байткода в стиле nodejs, но без flash рантайма.
        +
        github.com/claus/as3swf — статичный текст будет храниться в отдельных тегах — подменить не особо сложная задача.


  1. triada63
    18.01.2019 10:27

    Идея конечно прикольная, но вот язык выбран как мне кажется не совсем тот. Сам я тоже вебщик на PHP, но для такой либы выбрал бы Java или, в крайнем случае, ноду (NodeJS)


    1. akdes
      18.01.2019 11:21

      обычно катаюсь на мерсе, но тут бы на бмв лучше проехал…
      Кто что имеет, тот на том и катается. Не вижу особой разницы…


  1. nikolau
    18.01.2019 17:09

    Хорошая идея, но из-за времени генерации использовать можно только для своих нужд. Если для какого-нибудь сервиса, то такую генерацию, если это возможно, лучше реализовать в браузере.


    1. Jangle_ru Автор
      18.01.2019 19:55

      Увы, полностью в браузере этого не сделать, генерация видео где-то да будет происходить. Но создание анимации безусловно супер удобно было бы делать в браузере и подобные сервисы есть. Возможно и я дорасту до подобного


  1. 3JIoDeu
    20.01.2019 02:06

    Это наверно хороший академический проект, но я не до конца понимаю, какой профит даёт php обёртка над ffmpeg?


    1. Jangle_ru Автор
      20.01.2019 08:02

      Это не совсем обертка, ffmpeg нужна что бы склеить кадры в видео и все. А php как раз рисует эти кадры