Money-Code

Coding For Online Success

Using FFMpeg to create YouTube clone script

| 28 Comments

So this entry, I’m going to get a bit complicated. I was working on a project where administrators needed to upload Windows Media formatted videos (WMV), and wanted them converted to Flash video (FLV). This would duplicate what YouTube or GoogleVideo is currently doing. The browser would then use a Flash player to play the streamed videos. Also, I would need to capture a frame for the preview. I thought this tutorial might be a good resource for others that might be looking for this functionality for their affiliate sites, etc.

Now, I must discuss my environment a bit. This tutorial will cover Linux (specifically Gentoo Linux), using PHP and a Apache web server. Also, you will need some vital packages (ffmpeg-php, ffmpeg and flvtool2). I’m guessing that a few web hosts our there won’t have any of these packages available. This where the argument of getting a dedicated server or virtual server shines. If you had your own server you could install and configure it whatever way you want. I personally prefer dedicated servers. You can pickup dedicated hosting for approximately $100-$300/month depending on what server specifications you’re looking for. All of my servers are around the $150/month rate and work great for me.

ffmpeg-php is a fantastic PHP extension, that ties into ffmpeg and can return fantastic and incredibly useful information of a raw video file (such as frame rate, bitrate and can also grab a GD image handle of a frame in the video).

ffmpeg is a audio/video converter (make sure it’s compiled with amr, encode, ogg, oss, sdl, truetype, vorbis, zlib).

flvtool2 is a manipulation tool for Flash Video files, but we need to use it to embed META data extracted from our WMV file.

You’ll also need to be sure that PHP is compiled with GD support.

I’m going to skip the upload piece to the server. If you need more information on how to get the source WMV file to the server, let me know.

Here is the main chunk of code to worry about. I’ll explain this after the code snippet.

<?php
function makeMultipleTwo ($value){
        $sType = gettype($value/2);
        if($sType == "integer"){
                return $value
        } else {
                return ($value-1);
        }
}
$flvtool2                       = "/usr/bin/flvtool2";
$ffmpeg                         = "/usr/bin/ffmpeg";
$FileName                       = escapeshellcmd($FileName);
$justName                       = explode(".",$FileName);
$wmvName                        = "/path/to/videos/".$FileName
$flvPath                        = "/path/to/videos/".$flvName;
$ffmpegObj                      = new ffmpeg_movie($wmvName);
$srcWidth                       = makeMultipleTwo($ffmpegObj->getFrameWidth());
$srcHeight                      = makeMultipleTwo($ffmpegObj->getFrameHeight());
$srcFPS                         = $ffmpegObj->getFrameRate();
$srcAB                          = intval($ffmpegObj->getAudioBitRate()/1000);
$srcAR                          = $ffmpegObj->getAudioSampleRate();
$frameSnap                      = $ffmpegObj->getFrame(3);
$snapWidth                      = $frameSnap->getWidth();
$snapHeight                     = $frameSnap->getHeight();
$imageSnap                      = $frameSnap->toGDImage();
$thumbname                      = $justName[0].".jpg"; // just get the first part of the name
$imagePath                      = "/path/to/videos/".$thumbname;
imagejpeg($imageSnap, $imagePath, 100);
$cmd                            = $ffmpeg . " -i " . $wmvName . " -ar " . $srcAR . " -ab " . $srcAB . " -acodec mp3 -f flv -deinterlace -nr 500 -s 320×240 -aspect 4:3 -r ".$srcFPS." -b 270k -me_range ".$srcFPS." -i_qfactor 0.71 -g 500 " . $flvPath . " | " . $flvtool2 . " -U stdin " . $flvPath;
exec($cmd, $errArr);
unset($justName);
imagedestroy($imageSnap);
unset($frameSnap);
unset($ffmpegObj);
?>
 

$ffmpegObj is a object we’re creating from ffmpeg-php. Here we pass the path to where our original source WMV file is. ffmpeg-php then analyzes the file and we have various methods to extract information. The makeMultipleTwo function is there, since the width and height has to be a multiple of two (this was discussed at a great resource here). Along with the width and height information, we wan thte frame rate, audio sample rate and audio bit rate. Those are found by using the following methods (getFrameRate(), getAudioBitRate() and getAudioSampleRate()).

Next use the getFrame() method, which will grab a frame snap from the video. In this example, we’re grabbing the 3rd frame. This also returns a new object which we’re calling $frameSnap. We can access various methods within this new object (getWidth() which is the width of the image, getHeight() which is the height of the image, and toGDImage() which will return us a GD handle for the image). Once we have the GD handle for the image, we can simply write the image to the file system with imagejpeg() which is a method in the GD library.

At this point we have information about the WMV file and a frame snap for the preview image. We need to to convert the file to FLV now. Our next step is to create a command string which we’ll need to execute.

<?php
$cmd                            = $ffmpeg . " -i " . $wmvName . " -ar " . $srcAR . " -ab " . $srcAB . " -acodec mp3 -f flv -deinterlace -nr 500 -s 320×240 -aspect 4:3 -r ".$srcFPS." -b 270k -me_range ".$srcFPS." -i_qfactor 0.71 -g 500 " . $flvPath . " | " . $flvtool2 . " -U stdin " . $flvPath;
exec($cmd, $errArr);
?>
 

This converts the file to FLV, but also ‘pipes’ the output to FLVtool2 with the ‘|’. ffmpeg converts the file, but then we use flvtool2 to overwrite the file, but add important META information for FLV.

If your PHP environment is in safe_mode you will run into a problem with the ‘|’ in the command string. Since safe_mode runs all commands through escapeshellcmd() which will try to escape that character. To get around this is semi-tough if you do not have shell access to the server. I run safe_mode on my servers, so what I did was create a bash script with the command string in it, and passed values via exec() to my bash script. The ‘|’ pipe command is in the bash script, so it was not being escaped by PHP. Any time you’re dealing with exec() and shell scripts, it’s incredibly important to check and sanitize user input!!!!!

This is a tricky project, but can be quite cool when you get it working. The next piece is to get a flash player to play your FLV file. I personnally like this one:

http://www.jeroenwijering.com/?item=JW_FLV_Player

<div align="center">
        <script type="text/javascript" src="lib/swfobject.js"></script>
        <p id="player1" style="padding:4px 4px 4px 4px; border:#999999 1px solid; width:323px;"><br><strong>ERROR</strong><br>Looks like you do not have the Flash plugin installed, or you are using a older version (7 is the minimum required)<br><a href="http://www.macromedia.com/go/getflashplayer"><u>Get the Flash Player</u></a> to see this player/movie.<br><br></p>
        <script type="text/javascript">
                var s0 = new SWFObject("lib/flvplayer.swf","single","323","263","7");
                s0.addParam("allowfullscreen","true");
                s0.addVariable("showdownload","true");
                s0.addVariable("link","<?=$webroot?>/videos/<?=$FLVName?>"); // wmv might be an option
                s0.addVariable("file","<?=$webroot?>/videos/<?=$FLVName?>");
                s0.addVariable("image","<?=$webroot?>/videos/<?=$ThumbName?>");
                s0.addVariable("smoothing","false");
                s0.addVariable("backcolor","0xFFFFFF");
                s0.addVariable("largecontrols","false");
                s0.addVariable(‘width’,’323′)// reset width/height for IE issues and cache/refresh
                s0.addVariable(‘height’,’263′);
                s0.write("player1");
        </script>
</div>
 

UPDATE – 1/2/2009

I found this hosting company that offers and promotes FLV hosting. Could be a very good solution for some of you! Hope this helps!

Incoming search terms:

  • ffmpeg youtube
  • youtube ffmpeg
  • ffmpeg php youtube clone
  • ffmpeg upload script
  • using ffmpeg with php

28 Comments

  1. how can I install the needed vital packages in the server of godaddy or how can I connect it to the server of godaddy?

  2. Good article! It`s really help me to understand how to integrate video on my sites ;) Thanks!

  3. it was a nice one
    it helped me a lot and i am glad to see this post
    which took awaya my tension
    thanks

  4. Hi,

    I’m looking now for a decent dedicated Gentoo hosting.
    I want to install on it some YouTube clone script for my client.
    Could you suggest a good hosting company that you are personally using and have a good experience with?
    You can e-mail me to: lkolchin [at] gmail.com

    Thanks in advance,
    Leon

  5. WHY you no show 1 example?

    Thanks

  6. Hello

    All due respect. I’ve provided working code.. which I use myself.. but I don’t want to show off the site I built this for. Also, to me, me providing an example is not needed. Go to YouTube. It simply takes a WMV/AVI/etc and converts it to FLV.. just like YouTube.. or many other sites that allow for video uploads and Flash players.

    hanji

  7. Hi! Great post, really simple. I just have one doubt: the convertion of a large video file will make the proccess to take a while right? So in most cases the default execution time of the php will be overpassed. Youtube just let you add the video and then if its not yet converted they said “come back” in a while.

    Is there a way to achieve that?

    Thanks in advance!

  8. Hello

    Thanks for posting! I think you could do this with some server side magic. I would check the file size after the upload. If the file size is more than than what you want to do convert in real time, you could push the file to a tmp directory. Dump the data related to that entry in a ‘pending’ table. At this time you would present that message to the user.

    Then use a cron job, to look for pending jobs. Have it look every 5 minutes. If a job is found, then process the video and push the pending data into your main table when it’s completed.

    You still will need to worry about execution time, and memory consumption with your server. So you may need to adjust settings within your php.ini. Remember to watch for weirdness in the logs.

    Good luck.. and let me know how it goes.
    Thanks!
    hanji

  9. I want to know that how can i get the source WMV or AVI file to the server

  10. Hello

    You need to have PHP script that handles uploads to the server. I would be concerned about security if this is open to the public. Make sure you validate the MIME type with a ‘approver’ script of some sort on the server. Do NOT look at the extension or by looking at the $_FILES global since these can be manipulated by the attacker. I would look file_info or using `file` to verify the MIME after it’s upload before moving it to a directory that is accessible.

    hanji

  11. Hello All

    For those of you having trouble with the server configurations, you may want to look at a FLV hosting alternative. I found FLV Hosting, which offers and promotes FLV hosting and could be a excellent solution to provide streaming media.

    http://www.money-code.com/target/flvhosting.php

    hanji

  12. hi..this tutorial is very useful..actually i’m using zend framework for my project..i’ve create a video controller class and in this class i’ve got an upload function..where should i put this encode script so that all of the formatted video that has been uploaded will be convert to flv automatically before it will be displayed..tq

  13. I haven’t messed with the Zend framework before, but I would create a new method that handles this within the class and call it after the file has been uploaded via your upload method. Verify that file is there and is the right MIME type, then manipulate the file.

    HTH
    hanji

  14. You can’t. That’s the problem with a cheap solution like GoDaddy hosting, unless you’ve signed up with a dedicated hosting solution. If you don’t have a dedicated solution, then a shared hosting environment that specializes in Flash video is the way to go…

    I found this hosting company that offers and promotes FLV hosting. Could be a very good solution for some of you! Hope this helps!

  15. No problem. Glad you liked the article!

  16. Glad it helped!

  17. Hello

    Good question. There are quite a few out there. I would just google Gentoo hosting and start looking at features. The other option is to see if other big names can install it for you, or at least give you the ability to send them a live CD for the install. In the past I did this with Rackspace. Currently, they’re WAY too expensive, and I would not recommend them now because of this. I would find a good Gentoo friendly hosting facility, and look for other’s opinions on their reputation.

    I would also recommend posting a question on the Gentoo forum. That place is awesome, you should get a great response to that question there.

  18. Hello,

    My server support saying they have installed the ffmpeg but only the criteria here is I used your code and add this code to check whethere the ffmpeg is loaded or not and it shows can not load ffmpeg

    so can you tell me how to locate ffmpeg on server currently my server support saying they installed it here ‘/usr/local/bin/ffmpeg’

  19. Hello Mils

    I would try doing a exec() or file_exists() on that path. Depending on the server configuration, it may be permission issue or an issue with accessing the binary from your location (ie: chroot, etc).

    hanji

    [WORDPRESS HASHCASH] The poster sent us ’0 which is not a hashcash value.

  20. Thanks for the quick reply

    I am using the path but with this function in php

    $ffmpeg = “/usr/local/bin/ffmpeg”;

    extension_loaded($ffmpeg) or die(‘Error in loading ffmpeg’);

    it shows me the error so what path I can use. this path has been provided by support team of my server.

  21. Hello Mils

    I’m guess they just have media-video/ffmpeg installed on the server.. not the extension for PHP (dev-php5/ffmpeg-php). In my example I’m using a combination of the two. Where you see:

    $cmd = $ffmpeg . ” -i ” . $wmvName . ” -ar ” . $srcAR . ” -ab ” . $srcAB . ” -acodec mp3 -f flv -deinterlace -nr 500 -s 320×240 -aspect 4:3 -r “.$srcFPS.” -b 270k -me_range “.$srcFPS.” -i_qfactor 0.71 -g 500 ” . $flvPath . ” | ” . $flvtool2 . ” -U stdin ” . $flvPath;

    I’m using exec to manually use ffmpeg (not the extension).

    Where you’re seeing the object:
    $ffmpegObj->getFrameRate

    This is the extension. I use the extension to get additional information about the video. You might be able to figure out how to use the binary alone with exec() to get file information and skip the extension. I would still ask the host if they can install it.

  22. Very nice article! It was a BIG help for us this morning.

  23. I will gladly pay anyone, who can develop a php upload script using the ffmpeg that is already installed on my server, so I can simply upload videos (in other formats) to be converted to FLV – like what YouTube does.

    I am not building a Video Sharing site, I am trying to add some videos to some products in addition to the images which we can already upload.

    I need to find somebody as soon as possible.
    Michael
    webmaster@koihosting.com
    Thanks

  24. Which is better – FFMPEG OR RED5?

  25. Pingback: Using FFMpeg to create YouTube clone script – Money-Code | Shu Family Blog

  26. @Shandra – I’ve never used RED5. I’ll have to look into it.

  27. Hi the tutprial is great I have used it but when I check my Videos folder the converted file has 0 kb. I have ffmpeg on my hosting plan but no flvtool which i guess is not important as it only provides meta data . can any one help/

Leave a Reply

Required fields are marked *.


CommentLuv badge