How to convert a webm video to mp4 using FFMpeg in Symfony 3

How to convert a webm video to mp4 using FFMpeg in Symfony 3

WebM is an open, royaltyz-free, media file format designed for the web that defines the file container structure, video and audio formats. WebM files consist of video streams compressed with the VP8 or VP9 video codecs and audio streams compressed with the Vorbis or Opus audio codecs. The WebM file structure is based on the Matroska container. WebM is 100% free, and open-sourced under a BSD-style license. A lot of WebRTC based open source projects that allow you for example, record a video from the browser and upload it to your server, use the webm format as it's one of the most known formats for the web.

Sometimes, your user will need the recorded videos outside of the browser for different reasons and your project may need as well provide support for this kind of users by simply converting the video into its mp4 version so it can be played on multiple platforms as well. In this article, we'll share with you an useful snippet using PHP FFMpeg to convert a webm video to mp4 easily.

1. Install FFMpeg binaries

As first step you will need to install FFMpeg on your development machine. FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. It supports the most obscure ancient formats up to the cutting edge. No matter if they were designed by some standards committee, the community or a corporation. It is also highly portable: FFmpeg compiles, runs, and passes our testing infrastructure FATE across Linux, Mac OS X, Microsoft Windows, the BSDs, Solaris, etc. under a wide variety of build environments, machine architectures, and configurations.

In order to convert your video from webm to mp4, we'll run some commands that allow you to achieve this using a third party library for PHP. You can install FFMpeg on different platforms:

Windows

To use ffmpeg in windows you need to download the binaries from this website. You will need as well to have the ffmpeg command available from the path in case that you are in window, for example, you should be able to print the version of ffmpeg running the ffmpeg -version command in the command prompt:

ffmpeg command prompt in Windows

If you don't want to add the executable as an environment variable in Windows, you can as well set the binaries path later during the creation of a ffmpeg instance with PHP:

$ffmpeg = FFMpeg\FFMpeg::create(array(
    'ffmpeg.binaries'  => '/opt/local/ffmpeg/bin/ffmpeg',
    'ffprobe.binaries' => '/opt/local/ffmpeg/bin/ffprobe',
    'timeout'          => 3600, // The timeout for the underlying process
    'ffmpeg.threads'   => 12,   // The number of threads that FFMpeg should use
), $logger);

Ubuntu

Just run the following command from your terminal:

sudo apt-get install ffmpeg

For more information and steps to install in other operative systems, please visit the official downloads page of the ffmpeg website here.

2. Install PHP FFMpeg

In order to interact with FFMpeg with PHP, you will need either to write your own commands of ffmpeg to execute them using shell_exec or use a library that does this for you. We are talking about PHP-FFMpeg, an Object Oriented library that allows you to convert video/audio files with FFmpeg / AVConv with a friendly developer syntax. The preferred way to install this library in your Symfony project is using composer.

To add this wrapper to your project, execute the following command in your terminal (located in the root directory of your symfony project):

composer require php-ffmpeg/php-ffmpeg

After the installation, you will be able to use the namespaces of the library.

3. Converting video

Now that you have ffmpeg installed on the development machine and the wrapper to write the convert logic in PHP, we can finally proceed to convert it with code. As first step, you need to include the ffmpeg required namespaces, in this case we only need the FFMpeg tool and the x264 class that allows to convert a video to Mp4. You need to create a static instance of the FFMpeg and store it into a variable, you can provide other settings in this method as mentioned in the docs.

As next, you need to obtain the absolute path to the webm video that you want to convert and provide it as first argument  to the open method of our previously created media manipulation object. This method returns a Video object that can be used to save, make modifications etc. In this case we only want to save it with another format, so you will need to create as well an instance of the X264 codec and provide it as first argument on the save method of the video. As second argument you need to provide the destination path of the new mp4 file and that's it !

Note

As every code example in Our Code World, we write it so simple as we can so everyone can understand it. You can create this obviously as a service to keep your controllers thin.

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
 
// Use the FFMpeg tool
use FFMpeg\FFMpeg;
use FFMpeg\Format\Video\X264;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // Create an instance of FFMpeg
        $ffmpeg =  FFMpeg::create();
        
        // In this example we have a path for the videos
        $videosDirectory = $this->get('kernel')->getRootDir() . '/../web/uploads';
        
        // Open the webm video providing the absolute path
        $video = $ffmpeg->open($videosDirectory . '/video.webm');
        
        // Configure the new mp4 formax (x264)
        $mp4Format = new X264();

        // Fix for error "Encoding failed : Can't save to X264"
        // See: https://github.com/PHP-FFMpeg/PHP-FFMpeg/issues/310
        $mp4Format->setAudioCodec("libmp3lame");
        
        // Save the video in the same directory with the new format
        $video->save($mp4Format, $videosDirectory . '/video.mp4');

        return new Response("webm video succesfully converted to mp4");
    }
}

After accessing the index route of the previous controller, there should be now 2 files in the uploads directory, the original webm video and the new version in mp4 format.

Happy coding !

This could interest you

Become a more social person