Transcoding Videos for Web Streaming with FFmpeg using Laravel Queues

I’ve been working on a project where we were using AWS elastic transcoder for media conversion. Elastic transcoder is a highly scalable solution for media transcoding. However, it charges your per minute for media conversion depending on your region. To reduce operational costs, we decided to shift away from AWS transcoder and use FFmpeg with Laravel for media conversion on our own servers. In this tutorial, I’ll show you how we can use FFmpeg for media conversion and defer processing using Laravel Queues.

Let’s get started by setting up a new project. Create a new Video model, its migration, and controller.  We will store uploaded videos information on videos table.

On file upload, we will store video title, original file name, and path of the stored file in the database. After upload, we will dispatch a Job for transcoding it to a web streamable format and update stream_path with the output file path, update converted_for_streaming_at timestamp and set processed to true after FFmpeg is done processing uploaded media file.

In Video model class, add the converted_for_streaming_at column to $dates array so that it should be mutated to dates like created_at or updated_at columns.

Add these routes to web.php file.

GET /uploader route will render a form for uploading videos and POST /upload route will handle the form submission, upload video, create a database record and dispatch an FFmpeg transcoding job. GET / index route will render videos view where all uploaded videos will be displayed in native HTML video player.

In VideoController add these methods.

Create  uploader.blade.php under views directory.

Also, create a StoreVideoRequest form request for validating uploader form input.

We have a  mimetypes validation rule with video/* wildcard to only allow video uploads.

Now create a  ConvertVideoForStreaming job which will be dispatched after video is done uploading and a database record is created in VideoController@store method.

In handle() method of the dispatched job, we will create a low bitrate X264 format. We will open uploaded file from public disk and add a resize filter to it. Then we will tell FFmpeg to start transcoding by calling export() method and output file to public disk in a low bitrate mp4 container format.

Before you go an test it, make sure you have installed Laravel FFmpeg package that we are using in our transcoding job.

Also, make sure you have ffmpeg binaries installed of your machine. If you’re running Linux, you can easily install it by running following apt install command.

You must also add FFmpeg Service Provider and Facade to app.php.

and run following command to publish package configuration files.

If you’re running windows, you must add ffmpeg binaries to the system PATH. If you don’t have access to that, you can define these environment variables in your .env file.

Laravel Queues Configuration

You also need to configure queue connection in your env file. For this tutorial, I’m using database queue connection. Edit .env  file and update QUEUE_CONNECTION variable to database.

Also run  php artisan queue:table to create database queue table migration and php artisan migrate to create table. To deal with failed jobs, run  php artisan queue:failed-table to create failed queue jobs migration table and  php artisan migrate to create table.

Running Queue Worker

Before we go and test, run Laravel’s queue worker

we have added a --timeout flag to queue worker. This indicates that don’t want our queue jobs to run longer than 8600 seconds.

Now if you head over to /uploader route in your application and upload a video file, a database record will be created a transcoding job will be dispatched. You’ll be able to view your dispatched job in the terminal.

Displaying Videos

Create videos.blade.php file under view directory.

We will display an alert for videos that are currently being processed. For processed videos, we will render a video element with transcoded stream_path.

Here’s a demo of what we have done so far.

I have set up a Github repository with example application code. If you run into any issue or have any questions, leave a comment and I will try to help you in any way possible.

Share this post

One thought on “Transcoding Videos for Web Streaming with FFmpeg using Laravel Queues”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.