Go Back   CodingForums.com > :: Server side development > PHP > Post a PHP snippet

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 09-12-2012, 06:07 PM   PM User | #1
idalatob
Regular Coder

 
Join Date: Sep 2007
Location: Grahamstown, South Africa
Posts: 237
Thanks: 6
Thanked 17 Times in 17 Posts
idalatob is on a distinguished road
FFMPEG Mini Library

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!
idalatob is offline   Reply With Quote
Reply

Bookmarks

Tags
ffmpeg, php, video

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 05:56 AM.


Advertisement
Log in to turn off these ads.