Manipulating Videos in PHP

Posted on September 08, 2017

Handling video is something that I have been avoiding for several years. And now in order to save some server space, I am forced to learn how this thing works.

So if you want you can come along for the ride.

To start we need FFmpeg which is "A complete, cross-platform solution to record, convert and stream audio and video".

I'm on a Mac so I will use Homebrew.

brew install ffmpeg

Now let's use Lambo to create a test Laravel project to mess around with.

lambo ffmpeg-test

Now we could use some fancy shell interaction to handle resizing and transcoding some videos but instead, we will use PHP-FFMpeg a library written specifically for interacting with FFmpeg through PHP.

composer require php-ffmpeg/php-ffmpeg

Now let's go into our web.php route file and create a new instance.

Route::get('/', function () {

    $ffmpeg = FFMpeg\FFMpeg::create([
        // We need to pass in the path to our ffmpeg binary
        // You can find this by running `which ffmpeg`
        'ffmpeg.binaries'  => '/usr/local/bin/ffmpeg',

        // We also need to pass in the path to our ffprobe binary
        // You can find this by running `which ffprobe`
        'ffprobe.binaries' => '/usr/local/bin/ffprobe',

        // Set the number of threads ffmpeg can use
        'ffmpeg.threads'  => 12,
    ]);

});

Next, let's have some fun with some videos!

Converting a Video #

So one of the most important things one would want to do with videos is transcoding or converting to a different format.

This is how we can do that with FFmpeg:

// inside the "/" route closure

// Use the Storage Facade to get the path to an .mov file
$video = $ffmpeg->open(Storage::disk('local')->path('test.mov'));

// Create a Format to convert to. This is an mp4 format with an mp3 audio codec
$format = (new FFMpeg\Format\Video\X264())->setAudioCodec("libmp3lame");

// Save the video using the created format
$video->save($format, Storage::disk('local')->path('small.mp4'));

And that's all there is to it. You can find all the different video formats here.

Resizing #

We can also resize videos like this:

// get the $video and create the $format

$video->filters()
    ->resize(new FFMpeg\Coordinate\Dimension(1280, 720));

// Save the video using the created format
$video->save($format, Storage::disk('local')->path('small.mp4'));

This will resize the video without retaining the aspect ratio. If your video might not already be a 16:9 aspect ratio you would want to use the pad() method:

$video->filters()
    ->pad(new FFMpeg\Coordinate\Dimension(1280, 720));

Which will just add either vertical or horizontal padding based on what the video needs to fit the size you passed.

How about thumbnails? #

So if we were building something like Vimeo or Youtube we need video thumbnails. FFmpeg can get a frame of a video and return it as an image.

We can do this in PHP-FFmpeg using the frame() method on the Video class. Let's give it a try:

$video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(1))
    ->save(Storage::disk('local')->path('frame.jpg'));

It's that easy!

Now there are a lot of other things you can do with FFmpeg and the PHP-FFmpeg library like:

  • Add a watermark to your videos
  • Export your video as a GIF
  • Trim your videos
  • Export every 10 frames as images

And a whole lot of others that I will not be covering in this post.

In Closing #

Editing video using php may seem hard, at least it did to me. But there are libraries out there (like PHP-FFmpeg) made by amazing people that make it super easy.