Creating story for Instagram from PHP
Introduction
Recently, people are more willing to watch social networking videos than browse through photos. Storis on Instagram gains 3-4 times more views than just posted a photo.
And of course, we do not cease to forget that social networks not only show themselves, look at others, but also promote their products, services, etc. We have long learned to post in vkontakte svezhepubilirovannuyu news from the site. And what if you go on? What if you submit this information as a video? Or lay out interesting video story instagram to attract more attention of the audience?
So I came up with the idea of ββcreating a library that would allow creating short videos from photos, text and animation of these objects. Yes, someone can say that the services that allow you to do this already exist and why invent a bicycle? First, I want to; secondly, I can; thirdly, it will be free of charge.
This article is about how to work with the library, how to create your own story from PHP.
Restrictions
Immediately it should be said that the library uses FFmpeg to generate the final video file. FFmpeg must be installed on the server. Perhaps in the future, there will be an option to generate a story as a gif-file, but for myself I chose the video file as the result of the work.
Training
The library is installed through the composer
composer require borodin-vasiliy/php-storiesCreate story
It is time to create your own story. For example, we want to see a background photo of a kitten, which is a little closer throughout the whole story and display 2 text on it with an animation of appearance. Easy!
// ΠΡ Ρ
ΠΎΡΠΈΠΌ ΡΠΎΠ·Π΄Π°ΡΡ 5 ΡΠ΅ΠΊΡΠ½Π΄Π½ΠΎΠ΅ ΡΡΠΎΡΠΈΡ ΡΠ°Π·ΠΌΠ΅ΡΠ°ΠΌΠΈ 720x1280
$stories = new Stories([
"width" => 720,
"height" => 1280,
"duration" => 5
]);
As you can see, all parameters are passed as an array. At the moment, you can change:
- "Width" - The width of the color in pixels
- "Height" - height in pixels
- "Duration" - Duration in seconds
- "Fps" - The number of frames per second, according to the standard - 30
Next, we need to add 3 objects (picture and 2 texts) on our future story. At the moment, the library allows you to add 4 types of different objects - a picture, text, elex, a rectangle. Each object has its own method, the method argument is an array of the parameters of the object being added.
Objects have as general parameters:
- "Top" - the position of the object from the top edge of the color
- "Left" - the position of the element from the left edge of the color
- "Opacity" - transparency, as in css [0 ... 1]
- "Rotate" - the angle of rotation of the object [0 ... 359]
- "Z-index" - a layer, like z-index in css - the more, the higher the layer on the frame will be the element
- "Start" is the second when the item should be added to the story
- "End" - the second when the item should be removed from the story
So are unique for each type of object, for example, for a picture:
- "Path" - The path to the image that we want to add
- βScaleβ - Image size multiplier (approximation)
// ΠΡΡΡ Π΄ΠΎ ΡΠ°ΠΉΠ»Π° Ρ ΠΊΠΎΡΠΈΠΊΠΎΠΌ
$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
]);
Done! If you now generate a story, then 5 seconds we will admire the cat. But I promised that there will be an animation, let's add it.
An animation for an object is added using a separate method whose argument is an array of parameters to which the object should come. Animations for one object can be any number. It is worth saying that the syntax of the library implies the use of the 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,
]);
As you can see, the addAnimation method is used to add animation. Required parameters for animation:
- βStartβ - the second when the animation should start. If not specified, the animation will start when the object is added.
- "Duration" - the duration of the animation in seconds
Array of parameters on which it can affect animation:
- "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
]);
The text has its own unique parameters:
- βTextβ - the text you want to display is required
- "Path" - the path to the font (.ttf) - required
- "Size" - font size
- "Color" - color, for example "#ffffff"
- "Width" - the width of the block of text, if specified, the text will automatically be split into lines
- βAlignβ - text alignment [left, center, right]
- "Shadow" - shadow
Shadow is also an array of parameters:
- "Color" - the color of the shadow
- "Top" - indent from above
- "Left" - left indent
$file_hash = $stories->generate("/tmp");
As a result, we get the name of the file that is in the temporary folder passed as an argument.
Work result

It should be said that the speed of creating a story is not great, on a good computer a 5 second video is generated on the order of a minute, on a simple server more than 3 minutes.
Development plans
- Adding standard animation scripts to shorten code
- Text animations (appearing line by line, etc.)
- Background for text
I hope someone like this library will be useful. I will be glad to hear criticism and suggestions in the functional.
Git repository