Hi guys,

Hacked together a quick FFMPEG php library, as that compiling one is a pain. Its in a very rudimentary form at the moment and any suggestions or feedback or indeed contributions would be appreciated!

file: class.ffmpeg.php
PHP Code:
<?php
/**
 * This wont work on windows. Sorry
 */

require_once("class.ffmpeg.config.php");

class 
ffmpegPHP extends ffmpegPHPConfig {
    
    protected 
$_inputVideos = array();
    protected 
$_outputVideos = array();
    
    private 
$_pathToFFMPEG "";
    private 
$_pathToFFMPEG2THEORA "";
    private 
$_pathToFFPROBE "";
    
    private 
$_infoCache = array();
    
    public function 
__construct() {
        
//check if all the requirements are met
        
        
if (is_null(ffmpegPHPConfig::pathToFFMPEG)) {
            
$pathToFFMPEG trim(exec('which ffmpeg'));
            if (
$pathToFFMPEG == "") {
                throw new 
Exception("FFMPEG not located");
            }
            
$this->_pathToFFMPEG $pathToFFMPEG;
        } else {
            
$this->_pathToFFMPEG ffmpegPHPConfig::pathToFFMPEG;
        }
        
        if (
is_null(ffmpegPHPConfig::pathToFFMPEG2THEORA)) {
            
$pathToFFMPEG2THEORA trim(exec('which ffmpeg2theora'));
            if (
$pathToFFMPEG2THEORA == "") {
                throw new 
Exception("FFMPEG2Theora not located");
            }
            
$this->_pathToFFMPEG2THEORA $pathToFFMPEG2THEORA;
        } else {
            
$this->_pathToFFMPEG2THEORA ffmpegPHPConfig::pathToFFMPEG2THEORA;
        }
        if (
is_null(ffmpegPHPConfig::pathToFFPROBE)) {
            
$pathToFFPROBE trim(exec('which ffprobe'));
            if (
$pathToFFPROBE == "") {
                throw new 
Exception("ffprobe not located");
            }
            
$this->_pathToFFPROBE $pathToFFPROBE;
        } else {
            
$this->_pathToFFPROBE ffmpegPHPConfig::pathToFFPROBE;
        }
        
        
    }
    
    
/**
     * Execute a shell command
     *
     *@param string $cmd 'The shell command to execute'
     *@param string $dataPipe 'The pipe to return content from. 0 = stdin, 1 = stdout, 2 = stderr'
     *@return string 'Returned data from process'
     */
    
private function _openProcess($cmd$dataPipe 2) {
        
//create descriptor
        
$descriptorspec = array(
            
=> array("pipe""r"),  // stdin
            
=> array("pipe""w"),  // stdout
            
=> array("pipe""w"),  // stderr
        
);
        
//open the process
        
$process proc_open($cmd$descriptorspec$pipesdirname(__FILE__), null);
        
$rawInfo stream_get_contents($pipes[$dataPipe]); //get content from the pipe
        
proc_close($process); //close the process
        
return $rawInfo;
    }
    
    
/**
     * Add an input video to the current processing chain
     *
     *@param string $path 'Path to the video input file'
     * @return boolean 'Returns false if the video could not be located, or true if added'
     */
    
    
public function addInputFile($path) {
        if ((
file_exists($path)) &&
            (!
is_dir($path))) {
            
//get the basename of the file and use that as the key
            
$this->_inputVideos[basename($path)]['path'] = $path;
            
$this->_getFileInfo($path);
            return 
true;
        }
        return 
false;
    }
    
    
/**
     * Add an output video to the current processing chain
     *
     *@param string $path 'Path to the video output file'
     * @return boolean 'Returns true'
     */
    
    
public function addOutputFile($path) {
        
$this->_outputVideos[basename($path)]['path'] = $path;
        return 
true;
    }
    
    private function 
_getFileInfo($path) {
        if (!isset(
$this->_infoCache[$path]["rawinfo"])) {
            
$this->_infoCache[$path]["rawinfo"] = $this->_openProcess($this->_pathToFFPROBE " " $path);
        }
        
        
/**
         * Add the video info from this video to the data array
         */
        
$methods get_class_methods($this);
        foreach (
$methods as $methodName) {
            if (
stripos($methodName,'parseGet') !== false) {
                
//run this function
                
$this->_infoCache[$path]['data'][str_replace("parseGet","",$methodName)] = $this->$methodName($this->_infoCache[$path]["rawinfo"]);
            }
        }
    }
    
    
/**
     * Add a flag to an input video!
     * EG addFlagToInput("input.mpg", "-ss 00:00:01.000");
    *
    * @param string $inputKey 'The key of the input video'
    * @param string $flag 'The flag to add'
    *
    * @return boolean 'True on success, false on earthquake (or failure)'
    */
    
public function addFlagToInput($inputKey$flag null){
        if (
$flag) {
            
//check if the key exists
            
if (isset($this->_inputVideos[$inputKey])) {
                
$this->_inputVideos[$inputKey]["flags"][] = trim($flag);
                return 
true;
            }
        }
        return 
false;
    }
    
    
/**
     * Add a flag to an output video!
     * EG addFlagToOutput("output.mp4", "-t 15");
    *
    * @param string $inputKey 'The key of the output video'
    * @param string $flag 'The flag to add'
    *
    * @return boolean 'True on success, false on earthquake (or failure)'
    */
    
public function addFlagToOutput($inputKey$flag null){
        if (
$flag) {
            
//check if the key exists
            
if (isset($this->_outputVideos[$inputKey])) {
                
$this->_outputVideos[$inputKey]["flags"][] = trim($flag);
                return 
true;
            }
        }
        return 
false;
    }
    
    
/**
     * Build and execute a command
     */
    
    
public function execute() {
        
$command $this->_buildCommand();
        echo(
"\n\n\n");
        die(
$command);
    }
    
    
/**
     * Build the command
     */
    
    
private function _buildCommand() {
        if (empty(
$this->_inputVideos)) {
            throw new 
Exception("No input videos specified");
        }
        if (empty(
$this->_outputVideos)) {
            throw new 
Exception("No output videos specified");
        }
        
        
$baseCmd $this->_pathToFFMPEG;
        
        foreach (
$this->_inputVideos as $inputVideo) {
            if (isset(
$inputVideo["flags"])) {
                if (!empty(
$inputVideo["flags"])) {
                    foreach (
$inputVideo["flags"] as $flag) {
                        
$baseCmd .= " {$flag}";
                    }
                }
            }
            
$baseCmd .= " -i {$inputVideo['path']}";
        }
        
        foreach (
$this->_outputVideos as $outputVideo) {
            if (isset(
$outputVideo["flags"])) {
                if (!empty(
$outputVideo["flags"])) {
                    foreach (
$outputVideo["flags"] as $flag) {
                        
$baseCmd .= " {$flag}";
                    }
                }
            }
            
$baseCmd .= " {$outputVideo['path']}";
        }
        
        return 
$baseCmd;
        
    }
    
/**
     * DATA PARSING FUNCTIONS
     */
    
    /**
     * Returns the duration of a video file based on a ffmpeg info dump
     *
     * @param string $data 'FFPROBE dump'
     * @return array 
     */
    
    
public function parseGetDuration($data) {
        
preg_match(ffmpegPHPConfig::REGEX_DURATION,$data$matches);
        return array(
"ms"=>(int)$matches[5],"sec"=>(int)$matches[3],"min"=>(int)$matches[2], "hours"=>(int)$matches[1]);
    }
    
    public function 
parseGetError($data) {
        
preg_match(ffmpegPHPConfig::REGEX_ERRORS$data$matches);
        if (empty(
$array)) {
            return 
false;
        }
        return 
true;
    }
    
    public function 
parseGetVideoCodec($data) {
        
preg_match(ffmpegPHPConfig::REGEX_VIDEO_CODEC$data$matches);
        return 
$matches;
    }
    
    public function 
parseGetAudioCodec($data) {
        
preg_match(ffmpegPHPConfig::REGEX_AUDIO_CODEC$data$matches);
        return 
$matches;
    }
    
    public function 
parseGetFrameRate($data) {
        
preg_match(ffmpegPHPConfig::REGEX_FRAME_RATE$data$matches);
        return 
$matches;
    }
    public function 
parseGetPixelFormat($data) {
        
preg_match(ffmpegPHPConfig::REGEX_PIXEL_FORMAT$data$matches);
        return 
$matches;
    }
    
    public function 
parseGetDimensions($data) {
        
preg_match(ffmpegPHPConfig::REGEX_FRAME_WH$data$matches);
        return array(
"w"=>$matches[1], "h"=>$matches[2]);
    }
    
    public function 
parseGetBitrate($data) {
        
preg_match(ffmpegPHPConfig::REGEX_BITRATE$data$matches);
        return 
$matches;
    }
    
    public function 
parseGetAudioBitrate($data) {
        
preg_match(ffmpegPHPConfig::REGEX_AUDIO_BITRATE$data$matches);
        return 
$matches;
    }
    
    public function 
parseGetHasAudio($data) {
        
preg_match(ffmpegPHPConfig::REGEX_HAS_AUDIO$data$matches);
        return 
$matches;
    }
    
    public function 
parseGetHasVideo($data) {
        
preg_match(ffmpegPHPConfig::REGEX_HAS_VIDEO$data$matches);
        return 
$matches;
    }

}
?>
file: class.ffmpeg.config.php
PHP Code:
<?php

/**
 * This class contains a whole bunch of settings you can change to suit your needs
 */

class ffmpegPHPConfig {
    
    const 
workingDirectory "/tmp"//path to directory to use for any temporary videos
    
    
const pathToFFMPEG null//set the path to ffmpeg, this means we wont autodetect. useful for windows.
    
const pathToFFMPEG2THEORA null//set the path to ffmpeg2theora, this means we wont autodetect. useful for windows.
    
const pathToFFPROBE null//set the path to ffprobe, this means we wont autodetect. useful for windows.

    /**
     * Some regular expressions to parse data provided by FFMPEG
     */
    
    
const REGEX_DURATION          '/Duration: ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]+))?/';
    const 
REGEX_FRAME_RATE        '/([0-9\.]+\sfps,\s)?([0-9\.]+)\stbr/';    
    const 
REGEX_COMMENT           '/comment\s*(:|=)\s*(.+)/i';
    const 
REGEX_TITLE             '/title\s*(:|=)\s*(.+)/i';
    const 
REGEX_ARTIST            '/(artist|author)\s*(:|=)\s*(.+)/i';
    const 
REGEX_COPYRIGHT         '/copyright\s*(:|=)\s*(.+)/i';
    const 
REGEX_GENRE             '/genre\s*(:|=)\s*(.+)/i';
    const 
REGEX_TRACK_NUMBER      '/track\s*(:|=)\s*(.+)/i';
    const 
REGEX_YEAR              '/year\s*(:|=)\s*(.+)/i';
    const 
REGEX_FRAME_WH          '/Video:.+?([1-9][0-9]*)x([1-9][0-9]*)/';
    const 
REGEX_PIXEL_FORMAT      '/Video: [^,]+, ([^,]+)/';
    const 
REGEX_BITRATE           '/bitrate: ([0-9]+) kb\/s/';    
    const 
REGEX_VIDEO_BITRATE     '/Video:.+?([0-9]+) kb\/s/';
    const 
REGEX_AUDIO_BITRATE     '/Audio:.+?([0-9]+) kb\/s/';
    const 
REGEX_AUDIO_SAMPLE_RATE '/Audio:.+?([0-9]+) Hz/';
    const 
REGEX_VIDEO_CODEC       '/Video:\s([^,]+),/';
    const 
REGEX_AUDIO_CODEC       '/Audio:\s([^,]+),/';
    const 
REGEX_AUDIO_CHANNELS    '/Audio:\s[^,]+,[^,]+,([^,]+)/';
    const 
REGEX_HAS_AUDIO         '/Stream.+Audio/';
    const 
REGEX_HAS_VIDEO         '/Stream.+Video/';
    const 
REGEX_ERRORS            '/.*(Error|Permission denied|could not seek to position|Invalid pixel format|Unknown encoder|could not find codec|does not contain any stream).*/i';

}
file: index.php (small usage example)

PHP Code:

<?php
require("class.ffmpeg.php");
$test = new ffmpegPHP;
$test->addInputFile(dirname(__FILE__) . "/sample.mp4");
$test->addFlagToInput("sample.mp4""-ss 00:00:01.000");

$test->addOutputFile(dirname(__FILE__) . "/sample_out.mp4");
$test->addFlagToOutput("sample_out.mp4""-s 100x100");
$test->execute();
?>
Have fun chaps!