Вступление
В последнее время люди более охотно смотрят в социальных сетя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");
В результате мы получаем имя файла, который находится во временной папке, переданной как аргумент.
Результат работы
![](https://habrastorage.org/webt/kh/yg/2c/khyg2cy_9yemzeksskxu9jsd1ro.gif)
Стоит сказать, что скорость создания сторис не велика, на хорошем компьютере 5и секундный ролик генерируется порядка минуты, на простеньком сервере более 3х минут.
Планы по развитию
- Добавлении стандартных сценариев анимации, для сокращения кода
- Текстовые анимации (появление построчно и т.д.)
- Фон для текста
Надеюсь, кому-то подобная библиотека будет полезна. Буду рад услышать критику и пожелания в функционале.
Git-репозиторий
Комментарии (19)
akdes
17.01.2019 19:18Спасибо за работу и вклад в сообщество PHP разработки.
Однако, при чём тут инста? По факту статья о создании видео файла с наложением текста и анмиции. По названию ожидал увидеть что-то иное, хотябы интеграцию инсты в скрипт, для дальнейшего авто постинга, как минимум.Jangle_ru Автор
17.01.2019 19:20На самом деле долго думал над вектором, в котором двигаться. На деле, я для себя не нашёл применения этой библиотеки кроме как в социальных сетях. Но вы правы, на данный момент это просто создание видео из PHP. Инстаграм в заголовке взят как пример.
akdes
17.01.2019 20:29Я думаю название "Генерация/создание видео для статуса/Стори посредством пхп" было бы более приемлемым, благо статус — тема актуальная. ВК, инста, ватсэпп..
Ну да ладно, рад что вообще ещё вижу PHP на хабре
Taraflex
17.01.2019 22:35Слишком долго кодом анимацию всю описывать.
Для реального задачи лично я бы взял flash (уфф. предвкушаю волну негодования).
В текстовых полях разместил бы плейсхолдеры в стиле {{{тут будет ваша реклама… тут пробелов на пару килобайт...}}}
Распаковал бы полученный swf в несжатый формат.
Через php заменил бы плейсхолдеры на требуемый текст обычными регулярками (просто открыв swf как обычный юникод текст).
Отрендерил тем же ffmpeg полученный swf в mp4.Jangle_ru Автор
17.01.2019 22:45Это если шаблон использования один, может и сработать, но для широкого использования точно не подойдёт
Taraflex
17.01.2019 23:08Почему не подойдет для широкого использования?
Кодом анимацию прописывать еще дольше.
Если хочется все «по-красивше» выполнить, без заглушек из пробелов, то можно заморочиться и завести на сервере (у вас все равно нативная зависимость от ffmpeg получается)
www.redtamarin.com/about/description — виртуалка для flash байткода в стиле nodejs, но без flash рантайма.
+
github.com/claus/as3swf — статичный текст будет храниться в отдельных тегах — подменить не особо сложная задача.
triada63
18.01.2019 10:27Идея конечно прикольная, но вот язык выбран как мне кажется не совсем тот. Сам я тоже вебщик на PHP, но для такой либы выбрал бы Java или, в крайнем случае, ноду (NodeJS)
akdes
18.01.2019 11:21обычно катаюсь на мерсе, но тут бы на бмв лучше проехал…
Кто что имеет, тот на том и катается. Не вижу особой разницы…
nikolau
18.01.2019 17:09Хорошая идея, но из-за времени генерации использовать можно только для своих нужд. Если для какого-нибудь сервиса, то такую генерацию, если это возможно, лучше реализовать в браузере.
Jangle_ru Автор
18.01.2019 19:55Увы, полностью в браузере этого не сделать, генерация видео где-то да будет происходить. Но создание анимации безусловно супер удобно было бы делать в браузере и подобные сервисы есть. Возможно и я дорасту до подобного
sazareks
Это всё круто, но каким способом вы публикуете в сам инстаграм? Не ручками же?
Jangle_ru Автор
До реальной публикации пока не дошёл, все время тратится на доработку библиотеки и её развитие. А с публикацией есть трудности?
sazareks
В целом нет, но иногда возникает трудность в подтверждении аккаунта инстаграм. Знаете, когда авторизируешься с другого IP инстаграм иногда может запрос смс делать или на почту, вот эти самые запросы хочется иногда иметь программно вызывать. Некоторые сервисы вроде так делают.
Jangle_ru Автор
Да, понимаю о чём вы, но в данной библиотеке я решал всё же другую проблему. Но об этой тоже можно задуматься
mitgard
На сколько мне известно, трудности есть. У инсты нет оффициального апи. Все либы, что есть являются реверс-инженерингом андроид приложения. Правда могу ошибаться.
zzzmmtt
Апи то у них есть, но постинга сторис при беглом просмотре я там не увидел.
CAJAX
Оригинальная версия API закрыта с ноября. Есть новая, через Фейсбук. Там есть постинг фото для "Бизнес Партнёров Инстаграма", но постинга сторис там нет. Статус партнёра просто так не заполучить.
При этом у инстаграма есть graphql для своего софта, который, в принципе реверсится.