Video Editing Tutorial With PHP and FFMPEG
Php 18-Mar-2017

Video Editing Tutorial With PHP and FFMPEG

In this short article, I will share about how to use PHP for video editing. We will create video converter by leveraging a free tool called FFMPEG. This tool is powerful for video editing and becoming the base of many video editor software out there. This script can do the following jobs:
– Convert video file to GIF image.
– Cut the length of given video.
– Convert given video to mp4 format.

If user do not specify anything other than the uploaded video, then it will automatically cut the video duration to 10 seconds from the start of the video and output it in the same format.

Testing Environments:
Here is a little information about the testing environments I used for writing this script:
OS: Windows 10 64bit
Local server: XAMPP version 7.0.13
Browser: Firefox Developer Edition version 52.0a2
FFMPEG Version: 20170123-e371f03 64bit for Windows

In order to handle larger file upload, I increased “post_max_size” and “upload_max_filesize” in php.ini file and then restart apache. So, maybe you also need to check yours to ensure that it will not block the upload process.

Before you start writing your FFMPEG-PHP script, make sure that you have downloaded FFMPEG binary file suitable for your OS here https://ffmpeg.org/download.html. Don’t forget to check the “More downloading options” to see more download choices and select the static build. You will only need the binary file containing ffmpeg on its name for this purpose. It is located inside the bin folder in your downloaded zip file.

Let’s now create some folders to organize our script.

First, create the main folder with a name “videoedit”, you can use any name you like. Next, let us put 3 other folders inside the folder we just created.
1. “binaries” – Put the downloaded FFMPEG binary files inside this directory.
2. “input” – This is the temporary folder to hold user’s upload before it is being processed with ffmpeg.
3. “output” – The result of video editing will be served and presented to the user from here.

Now, let’s move on to writing our PHP script.

1. Create an index.php file and put this html codes inside it.

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="utf-8">
 <title>Edit Video</title>
 <meta name="keyword" content="video to gif, video shortener">
 <meta name="description" content="Convert video to gif or cut it out to shorter length">
 <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>

<div id="main-area">
    <div id="header">
        <h1>Please upload your video to edit it!</h1>
        <p>Make sure that your uploaded file name is not containing any special characters and or white spaces! You can convert your video to gif or mp4 format with this tool. You can also cut the duration of your video.</p>
    </div>

        <form method="post" action="" enctype="multipart/form-data">
            <div id="form-contents">

                <label for="video_file">Video to Edit:</label> </br>
                <input id="video_file" type="file" name="user_video" value=""/></br>
                
                <label for="extension">Convert to:</label></br>
                <select name="extension" id="extension">
                    <option value="none">Default</option>
                    <option value="gif">gif</option>
                    <option value="mp4">mp4</option>
                    <!-- You can add other format here -->
                </select></br>
                <label for="start_from">Start From:</label></br>
                <input type="text" name="start_from" id="start_from" value="" placeholder="example: 00:02:21"/>
                </br>
                <label for="length">Length:</label></br>
                <input type="text" name="length" id="length" value="" placeholder="example: 10"/> seconds
                </br>
                <input type="submit" name="submit" value="Edit">
            </div>                
        </form>
</div>
</body>
</html>

The codes above is the base template for our video editor script. It contains a header and a form to handle user upload. You can add other format names as the additional options for the “select” field. You can refer here https://ffmpeg.org/general.html#File-Formats to see the supported format by ffmpeg.

2. Put the following PHP codes right after the closing form tag “

“.

<?php    
    $input_dir = dirname(__FILE__). "/input/";
    $output_dir = dirname(__FILE__). "/output/";
    
    if(isset($_POST["submit"])) {        
        if(file_exists($_FILES["user_video"]["tmp_name"])){
            $temp_file = $_FILES["user_video"]["tmp_name"];
            
            $fileType = mime_content_type($temp_file);        
            if(!preg_match('/video\/*/', $fileType)) {    
                echo "Please upload a video";
                return;
            }
            
            // file name with extension
            $file = $_FILES["user_video"]["name"];    
            
            // name without extension
            $filename = pathinfo($file, PATHINFO_FILENAME);
            
            // Default extension
            $default = pathinfo($file, PATHINFO_EXTENSION);
            
            // create special string from date to ensure filename is unique
            $date = date("Y-m-d H:i:s");
            $uploadtime = strtotime($date);
            
            // upload path
            $video_file = $input_dir . "/" . $uploadtime ."_". $file;
            
            // check the specified extension
            if(!isset($_POST["extension"]) || $_POST["extension"] == ""){
                echo "Please set the output extension.";
                return;
            }
            $ext = $_POST["extension"]; // output extension    
            if($ext == "none") {
                $ext = $default;
            }            
            
            // put file to input directory to make it easier to be processed with ffmpeg
            $moved = move_uploaded_file($temp_file, $video_file);
            if($moved) {
                // change php working directory to where ffmpeg binary file reside
                chdir("binaries");
                
                $start_from = "00:00:00";                
                // check the specified starting time
                if(isset($_POST["start_from"]) && $_POST["start_from"] != ""){
                    $start_from = $_POST["start_from"];
                }                
                
                $length = 10;
                // check the specified duration
                if(isset($_POST["length"]) && $_POST["length"] != ""){
                    $length = $_POST["length"];
                }
                
                $output = "$output_dir/$uploadtime"."_$filename.$ext";
                $process = exec("ffmpeg -t $length -ss $start_from -i $video_file -b:v 2048k $output 2>&1", $result);                
                
                // delete uploaded file from input folder to reserve disk space
                unlink($video_file);
                
                echo "<span>Edit Finished:</span>";
                
                echo "<a href='http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"."output/$uploadtime"."_$filename.$ext'>Download</a>";
            }
            
        } else {
            echo "<h3>No file was uploaded!</h3>";
        }
    }
?>

Let’s break down some part of the codes above to see what is it doing.

First, we obtain the path to input and output folder using the following codes:

    $input_dir = dirname(__FILE__). "/input/";
    $output_dir = dirname(__FILE__). "/output/";

After user hit the “edit” button or submitting their query, we check whether they upload any file or not with this code:

if(file_exists($_FILES["user_video"]["tmp_name"])){}

If they are not uploading any file, we tell them that there are no file was uploaded.

 else { echo "<h3>No file was uploaded!</h3>"; }

Because we only want to accept video file, then we check whether the uploaded file is video or not by identifying its mime type. We then tell the user to upload a video and stop the process if the file isn’t containing video mime type.

$temp_file = $_FILES["user_video"]["tmp_name"];
$fileType = mime_content_type($temp_file);        
if(!preg_match('/video\/*/', $fileType)) {    
    echo "Please upload a video";
    return;
}

If the mime check is passed, then we grab some information from the video and then define the necessary identities to handle it.

// file name with extension
$file = $_FILES["user_video"]["name"];    

// name without extension
$filename = pathinfo($file, PATHINFO_FILENAME);

// Default extension
$default = pathinfo($file, PATHINFO_EXTENSION);

// create special string from date to ensure filename is unique
$date = date("Y-m-d H:i:s");
$uploadtime = strtotime($date);

// upload path
$video_file = $input_dir . "/" . $uploadtime ."_". $file;

Next, we check what file extension user want for the output and let’s save it into a variable.

// check the specified extension
if(!isset($_POST["extension"]) || $_POST["extension"] == ""){
    echo "Please set the output extension.";
    return;
}
// output extension    
$ext = $_POST["extension"];
if($ext == "none") {
    $ext = $default;
}

Now, let’s save user’s upload inside the “input” directory we created before.

// put file to input directory to make it easier to be processed with ffmpeg
$moved = move_uploaded_file($temp_file, $video_file);

After the video file has successfully being moved into “input” folder, we will then start to edit it with ffmpeg per user request and then provide them the access to its final result.

// change php working directory to where ffmpeg binary file reside
chdir("binaries");

$start_from = "00:00:00";                
// check the specified starting time
if(isset($_POST["start_from"]) && $_POST["start_from"] != ""){
    $start_from = $_POST["start_from"];
}                

$length = 10;
// check the specified duration
if(isset($_POST["length"]) && $_POST["length"] != ""){
    $length = $_POST["length"];
}

$output = "$output_dir/$uploadtime"."_$filename.$ext";
$process = exec("ffmpeg -t $length -ss $start_from -i $video_file -b:v 2048k $output 2>&1", $result);                

// delete uploaded file from input folder to reserve disk space
unlink($video_file);

echo "<span>Edit Finished:</span>";

echo "<a href='http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"."output/$uploadtime"."_$filename.$ext'>Download</a>";

3. To make the interface a little tidier, let’s add some css rules. Create a css file with a name “style.css” and put the following codes inside:

#main-area {
    width: 80%;
    margin: 0 auto;
    paddig: 20px;
    font-family: Arial;
}

#form-contents {
    font-size: 14px;
}

label, input, select {
    margin-bottom: 10px;
}
label {
    font-weight: bold;
}
input[type="submit"] {
    width: 125px;
}
a, a:hover {
    display: inline-block;
    text-decoration: none;    
}
a, input[type="submit"] {
    background: #3e8746;
    padding: 5px;
    border-radius: 2px;
    box-shadow: 0 2px 0 2px #333333;
    color: #fff;
    cursor: pointer;
}
span {
    display: block;
}