Login   Register  
PHP Classes
elePHPant
Icontem

File: src/PHPVideoToolkit/FfmpegProcess.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Oliver Lillie  >  PHP Video Toolkit  >  src/PHPVideoToolkit/FfmpegProcess.php  >  Download  
File: src/PHPVideoToolkit/FfmpegProcess.php
Role: Class source
Content type: text/plain
Description: Class source
Class: PHP Video Toolkit
Manipulate and convert videos with ffmpeg program
Author: By
Last change: .
Date: 3 months ago
Size: 18,214 bytes
 

Contents

Class file image Download
<?php
    
    /**
     * This file is part of the PHP Video Toolkit v2 package.
     *
     * @author Oliver Lillie (aka buggedcom) <publicmail@buggedcom.co.uk>
     * @license Dual licensed under MIT and GPLv2
     * @copyright Copyright (c) 2008-2014 Oliver Lillie <http://www.buggedcom.co.uk>
     * @package PHPVideoToolkit V2
     * @version 2.1.1
     * @uses ffmpeg http://ffmpeg.sourceforge.net/
     */
     
    namespace PHPVideoToolkit;
     
    /**
     * undocumented class
     *
     * @access public
     * @author Oliver Lillie
     * @package default
     */
    class FfmpegProcess extends ProcessBuilder
    {
        protected $_exec;
        protected $_pre_input_commands;
        protected $_post_input_commands;
        protected $_post_output_commands;
        protected $_input;
        protected $_output;
        protected $_progress_handler;
        protected $_detect_error;
        protected $_combined;
        
        /**
         * Constructor
         *
         * @access public
         * @author Oliver Lillie
         * @param string $binary_path The path of ffmpeg or ffprobe or whatever program you will be
         *  executing the command on.
         * @param string $temp_directory The path of the temp directory.
         */
        public function __construct($program, Config $config=null)
        {
            parent::__construct($program, $config);
            
            $this->_pre_input_commands = array();
            $this->_post_input_commands = array();
            $this->_post_output_commands = array();
            $this->_input = array();
            $this->_exec = null;
            $this->_progress_handler = null;
            $this->_combined = false;
        }
        
        /**
         * Sets the input at the given index. If -1 is used, the input is shifted
         * onto the begining of the input array.
         *
         * @access public
         * @param string $input
         * @param integer $index
         * @return self
         */
        public function setInputPath($input, $index=null)
        {
            if($index === null)
            {
                array_push($this->_input, $input);
            }
            else if($index === -1)
            {
                array_unshift($this->_input, $input);
            }
            else
            {
                $this->_input[$index] = $input;
            }
            return $this;
        }

        /**
         * Gets the input path at the given index.
         *
         * @access public
         * @param integer $index The index of which to return the input for.
         * @return string
         */
        public function getInputPath($index=0)
        {
            if(isset($this->_input[$index]) === true)
            {
                return $this->_input[$index];
            }
            
            throw new InvalidArgumentException('No input existed for given index `'.$index.'`');
        }
        
        /**
         * Sets the output.
         *
         * @access public
         * @param string $output
         * @return self
         */
        public function setOutputPath($output)
        {
            $this->_output = $output;
            return $this;
        }

        /**
         * Gets the output.
         *
         * @access public
         * @return string
         */
        public function getOutputPath()
        {
            return $this->_output;
        }

        /**
         * Adds a command to be bundled into command line call to be 
         * added to the command line call before the input file is added.
         *
         * @access public
         * @param string $command
         * @param mixed $argument
         * @return self
         */
        public function addPreInputCommand($command, $argument=false, $allow_command_repetition=false)
        {
            $this->_add($this->_pre_input_commands, $command, $argument, $allow_command_repetition);
            return $this;
        }

        /**
         * Adds a command to be bundled into command line call to be 
         * added to the command line call after the input file is added.
         *
         * @access public
         * @param string $command
         * @param mixed $argument
         * @return self
         */
        public function addCommand($command, $argument=false, $allow_command_repetition=false)
        {
            $this->_add($this->_post_input_commands, $command, $argument, $allow_command_repetition);
            return $this;
        }

        /**
         * Adds a command to be bundled into command line call to be 
         * added to the command line call after the ouput file is added.
         *
         * @access public
         * @param string $command
         * @param mixed $argument
         * @return self
         */
        public function addPostOutputCommand($command, $argument=false, $allow_command_repetition=false)
        {
            $this->_add($this->_post_output_commands, $command, $argument, $allow_command_repetition);
            return $this;
        }

        /**
         * Determines if the the command exits.
         *
         * @access public
         * @param string $command
         * @return mixed boolean if failure or value if exists.
         */
        public function hasPreInputCommand($command)
        {
            return isset($this->_pre_input_commands[$command]) === true ? ($this->_pre_input_commands[$command] === false ? true : $this->_pre_input_commands[$command]): false;
        }
        
        /**
         * Returns a pre input command.
         *
         * @access public
         * @param string $command
         * @return mixed boolean if failure or value if exists.
         */
        public function getPreInputCommand($command)
        {
            if($this->hasPreInputCommand($command) === false)
            {
                return false;
            }
            
            return $this->_pre_input_commands[$command];
        }
        
        /**
         * Determines if the the command exits.
         *
         * @access public
         * @param string $command
         * @return mixed boolean if failure or value if exists.
         */
        public function hasCommand($command)
        {
            return isset($this->_post_input_commands[$command]) === true ? ($this->_post_input_commands[$command] === false ? true : $this->_post_input_commands[$command]): false;
        }
        
        /**
         * Returns a pre input command.
         *
         * @access public
         * @param string $command
         * @return mixed boolean if failure or value if exists.
         */
        public function getCommand($command)
        {
            if($this->hasCommand($command) === false)
            {
                return false;
            }
            
            return $this->_post_input_commands[$command];
        }
        
        /**
         * Determines if the the command exits.
         *
         * @access public
         * @param string $command
         * @return mixed boolean if failure or value if exists.
         */
        public function hasPostOutputCommand($command)
        {
            return isset($this->_post_output_commands[$command]) === true ? ($this->_post_output_commands[$command] === false ? true : $this->_post_output_commands[$command]): false;
        }
        
        /**
         * Returns a post output command.
         *
         * @access public
         * @param string $command
         * @return mixed boolean if failure or value if exists.
         */
        public function getPostOutputCommand($command)
        {
            if($this->hasPostOutputCommand($command) === false)
            {
                return false;
            }
            
            return $this->_post_output_commands[$command];
        }
        
        /**
         * Combines the commands stored into a string
         *
         * @access protected
         * @return void
         */
        protected function _combineCommands()
        {
            if($this->_combined === true)
            {
                return;
            }
            $this->_combined = true;
            
            $args = $this->_arguments;
            $this->_arguments = array();
            
//          add the pre input commands
            if(empty($this->_pre_input_commands) === false)
            {
                $this->addCommands($this->_pre_input_commands);
            }
            
//          add in the input
            if(empty($this->_input) === false)
            {
                foreach ($this->_input as $input)
                {
                    $this->add('-i')
                         ->add($input);
                }
            }
            
//          build the post input commands
            if(empty($this->_post_input_commands) === false)
            {
                $this->addCommands($this->_post_input_commands);
            }
            if(empty($args) === false)
            {
                $this->_arguments = array_merge($this->_arguments, $args);
            }
            
//          add in the output
            if(empty($this->_output) === false)
            {
                $this->add($this->_output);
            }
            
//          build the post output commands
            if(empty($this->_post_output_commands) === false)
            {
                $this->addCommands($this->_post_output_commands);
            }
        }
        
        /**
         * Returns the command string to be executed.
         *
         * @access public
         * @author Oliver Lillie
         * @return string
         */
        public function getCommandString()
        {
            $this->_combineCommands();
            return parent::getCommandString();
        }
        
        /**
         * Get the ExecBuffer object by combining the commands the creating in the buffer.
         *
         * @access protected
         * @author Oliver Lillie
         * @return ExecBuffer
         */
        protected function _getExecBuffer()
        {
            $this->_combineCommands();
            return parent::getExecBuffer();
        }
        
        /**
         * Get the initialised ExecBuffer object.
         *
         * @access public
         * @author Oliver Lillie
         * @return ExecBuffer
         */
        public function &getExecBuffer()
        {
            if(empty($this->_exec) === true)
            {
                $this->_exec = $this->_getExecBuffer();
            }
            return $this->_exec;
        }
        
        /**
         * Execute the buffer command.
         *
         * @access public
         * @author Oliver Lillie
         * @return self
         */
        public function execute()
        {
            $this->getExecBuffer()
                 ->setBlocking(true)
                 ->execute();
            
            return $this;
        }
        
        /**
         * Protected private function for calling functions from the ExecBuffer.
         *
         * @access protected
         * @author Oliver Lillie
         * @param string $function 
         * @param array $arguments 
         * @return mixed
         */
        protected function _callExecBufferFunction($function, $arguments=array())
        {
//          if no exec has been created then it has not completed.
            if(empty($this->_exec) === true)
            {
                return false;
            }
            
            if(is_callable(array($this->_exec, $function)) === false)
            {
                throw new FfmpegProcessException('This function is not callable within ExecBuffer.', $this->_exec, $this);
            }
            
            return call_user_func_array(array($this->_exec, $function), $arguments);
        }
        
        /**
         * Returns any "[xxx @ xxxxx] message" messages set in the buffer by FFmpeg.
         *
         * @access public
         * @author Oliver Lillie
         * @return array
         */
        public function getMessages()
        {
            $messages = array();
            $buffer = $this->getBuffer();
            if(empty($buffer) === false)
            {
                // 0x7f9db9065a00
                if(preg_match_all('/\[([a-zA-Z0-9]+) @ (0x[a-z0-9]+)\] (.*)/', $buffer, $matches) > 0)
                {
                    foreach ($matches[1] as $key=>$match)
                    {
                        if(isset($messages[$match]) === false)
                        {
                            $messages[$match] = array();
                        }
                        if(isset($messages[$match][$matches[2][$key]]) === false)
                        {
                            $messages[$match][$matches[2][$key]] = array();
                        }
                        array_push($messages[$match][$matches[2][$key]], $matches[3][$key]);
                    }
                }
            }
            return $messages;
        }
        
        /**
         * Returns the current (or if called after isCompleted() returns true, the completed)
         * run time of the exec function.
         *
         * @access public
         * @author Oliver Lillie
         * @return mixed
         */
        public function getRunTime()
        {
            return $this->_callExecBufferFunction('getRunTime');
        }
        
        /**
         * Returns the buffers command or executed command.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::getExecutedCommand
         * @param boolean $raw If true then the raw command is returned from the buffer, otherwise
         *  the original command is returned.
         * @return mixed
         */
        public function getExecutedCommand($raw=false)
        {
            return $this->_callExecBufferFunction($raw === false ? 'getCommand' : 'getExecutedCommand');
        }
        
        /**
         * Returns the filtered buffer output of ExecBuffer.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::getBuffer
         * @return mixed
         */
        public function getBuffer($raw=false)
        {
            return $this->_callExecBufferFunction($raw === false ? 'getBuffer' : 'getRawBuffer');
        }
        
        /**
         * Returns the last line from the buffer output of ExecBuffer.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::getLastLine
         * @return mixed
         */
        public function getLastLine()
        {
            return $this->_callExecBufferFunction('getLastLine');
        }
        
        /**
         * Returns the last split from the buffer output of ExecBuffer.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::getLastSplit
         * @return mixed
         */
        public function getLastSplit()
        {
            return $this->_callExecBufferFunction('getLastSplit');
        }
        
        /**
         * Returns the error code encountered by the ExecBuffer.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::getErrorCode
         * @return mixed
         */
        public function getErrorCode()
        {
            return $this->_callExecBufferFunction('getErrorCode');
        }
        
        /**
         * Returns a boolean value determining if the process has encountered an error.
         * Typically if this returns true, it also means the process has completed.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::hasError
         * @param boolean $delete_output_on_error If true and an error has been encountered
         *  and the output has been set and the output exists, then the output is deleted.
         * @return boolean
         */
        public function hasError($delete_output_on_error=true)
        {
            $has_error = $this->_callExecBufferFunction('hasError');
            
//          if we have an error and we want to delete any output on the error
            if($delete_output_on_error === true && $has_error === true)
            {
                $output = $this->getOutputPath();
                if(empty($output) === false && is_file($output) === true)
                {
                    @unlink($output);
                }
            }
            
            return $has_error;
        }
        
        /**
         * Returns a boolean value determining if the process has completed.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::isCompleted
         * @return boolean
         */
        public function isCompleted()
        {
            return $this->_callExecBufferFunction('isCompleted');
        }
        
        /**
         * Returns the file name of the exec buffer output.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::getBufferOutput
         * @return string
         */
        public function getBufferOutput()
        {
            return $this->_callExecBufferFunction('getBufferOutput');
        }
        
        /**
         * Returns a boolean value determining if the process has completed.
         *
         * @access public
         * @author Oliver Lillie
         * @see ExecBuffer::isCompleted
         * @return boolean
         */
        public function getPortableId()
        {
            if($this->_callExecBufferFunction('getBlocking') === true)
            {
                throw new Exception('It is not possible to get a portable id as the exec process has been made blocking. To get a portable id make the process unblocking or call getPortableId() before the save occurs.');
            }
            
            $output = $this->getBufferOutput();
            return substr($output, strrpos($output, 'phpvideotoolkit_')+16).'.'.$this->_callExecBufferFunction('getBoundary').'.'.time();
        }
    }