Version 0.3
This commit is contained in:
parent
0d69145ec3
commit
ad3a5af623
130 changed files with 7283 additions and 2627 deletions
|
|
@ -11,23 +11,24 @@
|
|||
|
||||
namespace FFMpeg\Format\Audio;
|
||||
|
||||
use Evenement\EventEmitter;
|
||||
use FFMpeg\Exception\InvalidArgumentException;
|
||||
use FFMpeg\Format\AudioInterface;
|
||||
use FFMpeg\Media\MediaTypeInterface;
|
||||
use FFMpeg\Format\ProgressableInterface;
|
||||
use FFMpeg\Format\ProgressListener\AudioProgressListener;
|
||||
use FFMpeg\FFProbe;
|
||||
|
||||
/**
|
||||
* The abstract default Audio format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
abstract class DefaultAudio implements Resamplable, Interactive
|
||||
abstract class DefaultAudio extends EventEmitter implements AudioInterface, ProgressableInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $audioCodec;
|
||||
protected $audioSampleRate = 44100;
|
||||
protected $kiloBitrate = 128;
|
||||
|
||||
/** @var integer */
|
||||
protected $audioKiloBitrate = 128;
|
||||
|
||||
/**
|
||||
* Returns extra parameters for the encoding
|
||||
*
|
||||
* @return string
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getExtraParams()
|
||||
{
|
||||
|
|
@ -43,11 +44,12 @@ abstract class DefaultAudio implements Resamplable, Interactive
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the audio codec, Should be in the available ones, otherwise an
|
||||
* Sets the audio codec, Should be in the available ones, otherwise an
|
||||
* exception is thrown
|
||||
*
|
||||
* @param string $audioCodec
|
||||
* @throws \InvalidArgumentException
|
||||
* @param string $audioCodec
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setAudioCodec($audioCodec)
|
||||
{
|
||||
|
|
@ -66,24 +68,24 @@ abstract class DefaultAudio implements Resamplable, Interactive
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAudioSampleRate()
|
||||
public function getAudioKiloBitrate()
|
||||
{
|
||||
return $this->audioSampleRate;
|
||||
return $this->audioKiloBitrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the audio sample rate
|
||||
* Sets the kiloBitrate value
|
||||
*
|
||||
* @param integer $audioSampleRate
|
||||
* @throws \InvalidArgumentException
|
||||
* @param integer $kiloBitrate
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setAudioSampleRate($audioSampleRate)
|
||||
public function setAudioKiloBitrate($kiloBitrate)
|
||||
{
|
||||
if ($audioSampleRate < 1) {
|
||||
throw new InvalidArgumentException('Wrong audio sample rate value');
|
||||
if ($kiloBitrate < 1) {
|
||||
throw new InvalidArgumentException('Wrong kiloBitrate value');
|
||||
}
|
||||
|
||||
$this->audioSampleRate = (int) $audioSampleRate;
|
||||
$this->audioKiloBitrate = (int) $kiloBitrate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -91,25 +93,14 @@ abstract class DefaultAudio implements Resamplable, Interactive
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getKiloBitrate()
|
||||
public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total)
|
||||
{
|
||||
return $this->kiloBitrate;
|
||||
}
|
||||
$format = $this;
|
||||
$listener = new AudioProgressListener($ffprobe, $media->getPathfile(), $pass, $total);
|
||||
$listener->on('progress', function () use ($media, $format) {
|
||||
$format->emit('progress', array_merge(array($media, $format), func_get_args()));
|
||||
});
|
||||
|
||||
/**
|
||||
* Set the kiloBitrate value
|
||||
*
|
||||
* @param int integer $kiloBitrate
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setKiloBitrate($kiloBitrate)
|
||||
{
|
||||
if ($kiloBitrate < 1) {
|
||||
throw new InvalidArgumentException('Wrong kiloBitrate value');
|
||||
}
|
||||
|
||||
$this->kiloBitrate = (int) $kiloBitrate;
|
||||
|
||||
return $this;
|
||||
return array($listener);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,13 @@ namespace FFMpeg\Format\Audio;
|
|||
|
||||
/**
|
||||
* The Flac audio format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class Flac extends DefaultAudio
|
||||
{
|
||||
protected $audioCodec = 'flac';
|
||||
public function __construct()
|
||||
{
|
||||
$this->audioCodec = 'flac';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Audio;
|
||||
|
||||
/**
|
||||
* The interactive audio interface. This provide a method to list available
|
||||
* codecs. This is usefull to build interactive development and switch between
|
||||
* different codecs
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Interactive extends Transcodable
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the list of available audio codecs for this format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableAudioCodecs();
|
||||
}
|
||||
|
|
@ -13,12 +13,13 @@ namespace FFMpeg\Format\Audio;
|
|||
|
||||
/**
|
||||
* The MP3 audio format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class Mp3 extends DefaultAudio
|
||||
{
|
||||
protected $audioCodec = 'libmp3lame';
|
||||
public function __construct()
|
||||
{
|
||||
$this->audioCodec = 'libmp3lame';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Audio;
|
||||
|
||||
use FFMpeg\Format\AudioInterface;
|
||||
|
||||
/**
|
||||
* The resamplable audio interface
|
||||
*
|
||||
* This provide a method to define the AudiosampleRate
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Resamplable extends AudioInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the audio sample rate
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getAudioSampleRate();
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Audio;
|
||||
|
||||
use FFMpeg\Format\AudioInterface;
|
||||
|
||||
/**
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Transcodable extends AudioInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the audio codec
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAudioCodec();
|
||||
}
|
||||
|
|
@ -8,23 +8,16 @@
|
|||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format;
|
||||
|
||||
/**
|
||||
* The base audio interface
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface AudioInterface
|
||||
interface AudioInterface extends FormatInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the kiloBitrate value
|
||||
* Get the audio kiloBitrate value
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getKiloBitrate();
|
||||
public function getAudioKiloBitrate();
|
||||
|
||||
/**
|
||||
* Return an array of extra parameters to add to ffmpeg commandline
|
||||
|
|
@ -33,4 +26,17 @@ interface AudioInterface
|
|||
*/
|
||||
public function getExtraParams();
|
||||
|
||||
/**
|
||||
* Returns the audio codec
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAudioCodec();
|
||||
|
||||
/**
|
||||
* Returns the list of available audio codecs for this format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableAudioCodecs();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format;
|
||||
|
||||
use FFMpeg\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Dimension object, used for manipulating width and height couples
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class Dimension
|
||||
{
|
||||
protected $width;
|
||||
protected $height;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param integer $width
|
||||
* @param integer $height
|
||||
* @throws InvalidArgumentException when one of the parameteres is invalid
|
||||
*/
|
||||
public function __construct($width, $height)
|
||||
{
|
||||
if ($width <= 0 || $height <= 0) {
|
||||
throw new InvalidArgumentException('Width and height should be positive integer');
|
||||
}
|
||||
|
||||
$this->width = (int) $width;
|
||||
$this->height = (int) $height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return width
|
||||
*
|
||||
* @return width
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return height
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
}
|
||||
15
src/FFMpeg/Format/FormatInterface.php
Normal file
15
src/FFMpeg/Format/FormatInterface.php
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace FFMpeg\Format;
|
||||
|
||||
interface FormatInterface
|
||||
{
|
||||
}
|
||||
16
src/FFMpeg/Format/FrameInterface.php
Normal file
16
src/FFMpeg/Format/FrameInterface.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <dev.team@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format;
|
||||
|
||||
interface FrameInterface extends FormatInterface
|
||||
{
|
||||
}
|
||||
238
src/FFMpeg/Format/ProgressListener/AbstractProgressListener.php
Normal file
238
src/FFMpeg/Format/ProgressListener/AbstractProgressListener.php
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\ProgressListener;
|
||||
|
||||
use Alchemy\BinaryDriver\Listeners\ListenerInterface;
|
||||
use Evenement\EventEmitter;
|
||||
use FFMpeg\FFProbe;
|
||||
use FFMpeg\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* @author Robert Gruendler <r.gruendler@gmail.com>
|
||||
*/
|
||||
abstract class AbstractProgressListener extends EventEmitter implements ListenerInterface
|
||||
{
|
||||
/** @var integer */
|
||||
private $duration;
|
||||
|
||||
/** @var integer */
|
||||
private $totalSize;
|
||||
|
||||
/** @var integer */
|
||||
private $currentSize;
|
||||
|
||||
/** @var integer */
|
||||
private $currentTime;
|
||||
|
||||
/** @var double */
|
||||
private $lastOutput = null;
|
||||
|
||||
/** @var FFProbe */
|
||||
private $ffprobe;
|
||||
|
||||
/** @var string */
|
||||
private $pathfile;
|
||||
|
||||
/** @var Boolean */
|
||||
private $initialized = false;
|
||||
|
||||
/** @var integer */
|
||||
private $currentPass;
|
||||
|
||||
/** @var integer */
|
||||
private $totalPass;
|
||||
|
||||
/**
|
||||
* Transcoding rate in kb/s
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $rate;
|
||||
|
||||
/**
|
||||
* Percentage of transcoding progress (0 - 100)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $percent = 0;
|
||||
|
||||
/**
|
||||
* Time remaining (seconds)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $remaining = null;
|
||||
|
||||
/**
|
||||
* @param FFProbe $ffprobe
|
||||
* @param string $pathfile
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __construct(FFProbe $ffprobe, $pathfile, $currentPass, $totalPass)
|
||||
{
|
||||
$this->ffprobe = $ffprobe;
|
||||
$this->pathfile = $pathfile;
|
||||
$this->currentPass = $currentPass;
|
||||
$this->totalPass = $totalPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FFProbe
|
||||
*/
|
||||
public function getFFProbe()
|
||||
{
|
||||
return $this->ffprobe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPathfile()
|
||||
{
|
||||
return $this->pathfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getCurrentPass()
|
||||
{
|
||||
return $this->currentPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getTotalPass()
|
||||
{
|
||||
return $this->totalPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle($type, $data)
|
||||
{
|
||||
if (null !== $progress = $this->parseProgress($data)) {
|
||||
$this->emit('progress', array_values($progress));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function forwardedEvents()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the regex pattern to match a ffmpeg stderr status line
|
||||
*/
|
||||
abstract protected function getPattern();
|
||||
|
||||
/**
|
||||
* @param string $progress A ffmpeg stderr progress output
|
||||
*
|
||||
* @return array the progressinfo array or null if there's no progress available yet.
|
||||
*/
|
||||
private function parseProgress($progress)
|
||||
{
|
||||
if (!$this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
|
||||
if (preg_match($this->getPattern(), $progress, $matches) !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$currentDuration = $this->convertDuration($matches[2]);
|
||||
$currentTime = microtime(true);
|
||||
$currentSize = trim(str_replace('kb', '', strtolower(($matches[1]))));
|
||||
$percent = max(0, min(1, $currentDuration / $this->duration));
|
||||
|
||||
if ($this->lastOutput !== null) {
|
||||
$delta = $currentTime - $this->lastOutput;
|
||||
$deltaSize = $currentSize - $this->currentSize;
|
||||
$rate = $deltaSize * $delta;
|
||||
if ($rate > 0) {
|
||||
$totalDuration = $this->totalSize / $rate;
|
||||
$this->remaining = floor($totalDuration - ($totalDuration * $percent));
|
||||
$this->rate = floor($rate);
|
||||
} else {
|
||||
$this->remaining = 0;
|
||||
$this->rate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$percent = $percent / $this->totalPass + ($this->currentPass - 1) / $this->totalPass;
|
||||
|
||||
$this->percent = floor($percent * 100);
|
||||
$this->lastOutput = $currentTime;
|
||||
$this->currentSize = (int) $currentSize;
|
||||
$this->currentTime = $currentDuration;
|
||||
|
||||
return $this->getProgressInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $rawDuration in the format 00:00:00.00
|
||||
* @return number
|
||||
*/
|
||||
private function convertDuration($rawDuration)
|
||||
{
|
||||
$ar = array_reverse(explode(":", $rawDuration));
|
||||
$duration = floatval($ar[0]);
|
||||
if (!empty($ar[1])) {
|
||||
$duration += intval($ar[1]) * 60;
|
||||
}
|
||||
if (!empty($ar[2])) {
|
||||
$duration += intval($ar[2]) * 60 * 60;
|
||||
}
|
||||
|
||||
return $duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getProgressInfo()
|
||||
{
|
||||
if ($this->remaining === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array(
|
||||
'percent' => $this->percent,
|
||||
'remaining' => $this->remaining,
|
||||
'rate' => $this->rate
|
||||
);
|
||||
}
|
||||
|
||||
private function initialize()
|
||||
{
|
||||
$format = $this->ffprobe->format($this->pathfile);
|
||||
|
||||
if (false === $format->has('size') || false === $format->has('duration')) {
|
||||
throw new RuntimeException(sprintf('Unable to probe format for %s', $this->pathfile));
|
||||
}
|
||||
|
||||
$this->totalSize = $format->get('size') / 1024;
|
||||
$this->duration = $format->get('duration');
|
||||
|
||||
$this->initialized = true;
|
||||
}
|
||||
}
|
||||
29
src/FFMpeg/Format/ProgressListener/AudioProgressListener.php
Normal file
29
src/FFMpeg/Format/ProgressListener/AudioProgressListener.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\ProgressListener;
|
||||
|
||||
/**
|
||||
* Parses ffmpeg stderr progress information. An example:
|
||||
*
|
||||
* <pre>
|
||||
* size= 3552kB time=00:03:47.29 bitrate= 128.0kbits/s
|
||||
* </pre>
|
||||
*
|
||||
* @author Robert Gruendler <r.gruendler@gmail.com>
|
||||
*/
|
||||
class AudioProgressListener extends AbstractProgressListener
|
||||
{
|
||||
public function getPattern()
|
||||
{
|
||||
return '/size=(.*?) time=(.*?) /';
|
||||
}
|
||||
}
|
||||
29
src/FFMpeg/Format/ProgressListener/VideoProgressListener.php
Normal file
29
src/FFMpeg/Format/ProgressListener/VideoProgressListener.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\ProgressListener;
|
||||
|
||||
/**
|
||||
* Parses ffmpeg stderr progress information for video files. An example:
|
||||
*
|
||||
* <pre>
|
||||
* frame= 171 fps=0.0 q=10.0 size= 18kB time=00:00:05.72 bitrate= 26.4kbits/s dup=8 drop=0
|
||||
* </pre>
|
||||
*
|
||||
* @author Robert Gruendler <r.gruendler@gmail.com>
|
||||
*/
|
||||
class VideoProgressListener extends AbstractProgressListener
|
||||
{
|
||||
public function getPattern()
|
||||
{
|
||||
return '/size=(.*?) time=(.*?) /';
|
||||
}
|
||||
}
|
||||
31
src/FFMpeg/Format/ProgressableInterface.php
Normal file
31
src/FFMpeg/Format/ProgressableInterface.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <dev.team@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format;
|
||||
|
||||
use Evenement\EventEmitterInterface;
|
||||
use FFMpeg\FFProbe;
|
||||
use FFMpeg\Media\MediaTypeInterface;
|
||||
|
||||
interface ProgressableInterface extends EventEmitterInterface
|
||||
{
|
||||
/**
|
||||
* Creates the progress listener
|
||||
*
|
||||
* @param MediaTypeInterface $media
|
||||
* @param FFProbe $ffprobe
|
||||
* @param Integer $pass The current pas snumber
|
||||
* @param Integer $total The total pass number
|
||||
*
|
||||
* @return array An array of listeners
|
||||
*/
|
||||
public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total);
|
||||
}
|
||||
|
|
@ -11,171 +11,48 @@
|
|||
|
||||
namespace FFMpeg\Format\Video;
|
||||
|
||||
use FFMpeg\Format\Audio\DefaultAudio;
|
||||
use FFMpeg\Format\Dimension;
|
||||
use FFMpeg\FFProbe;
|
||||
use FFMpeg\Exception\InvalidArgumentException;
|
||||
use FFMpeg\Format\Audio\DefaultAudio;
|
||||
use FFMpeg\Format\VideoInterface;
|
||||
use FFMpeg\Media\MediaTypeInterface;
|
||||
use FFMpeg\Format\ProgressListener\VideoProgressListener;
|
||||
|
||||
/**
|
||||
* The abstract default Video format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
abstract class DefaultVideo extends DefaultAudio implements Interactive, Resamplable, Resizable
|
||||
abstract class DefaultVideo extends DefaultAudio implements VideoInterface
|
||||
{
|
||||
const RESIZEMODE_FIT = 'fit';
|
||||
const RESIZEMODE_INSET = 'inset';
|
||||
const RESIZEMODE_SCALE_WIDTH = 'width';
|
||||
const RESIZEMODE_SCALE_HEIGHT = 'height';
|
||||
|
||||
protected $width;
|
||||
protected $height;
|
||||
protected $frameRate = 25;
|
||||
protected $resizeMode = self::RESIZEMODE_FIT;
|
||||
/** @var string */
|
||||
protected $videoCodec;
|
||||
protected $GOPsize = 25;
|
||||
|
||||
/** @var Integer */
|
||||
protected $kiloBitrate = 1000;
|
||||
|
||||
/** @var Integer */
|
||||
protected $modulus = 16;
|
||||
|
||||
/**
|
||||
* Returns the width setting.
|
||||
* The return of this method should not depend on a media file size
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height setting
|
||||
* The return of this method should not depend on a media file size
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dimensions
|
||||
*
|
||||
* @param integer $width The heigth
|
||||
* @param integer $height The width
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setDimensions($width, $height)
|
||||
{
|
||||
if ($width < 1) {
|
||||
throw new InvalidArgumentException('Wrong width value');
|
||||
}
|
||||
if ($height < 1) {
|
||||
throw new InvalidArgumentException('Wrong height value');
|
||||
}
|
||||
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc)
|
||||
*/
|
||||
public function getComputedDimensions($originalWidth, $originalHeight)
|
||||
{
|
||||
$originalRatio = $originalWidth / $originalHeight;
|
||||
|
||||
switch ($this->getResizeMode()) {
|
||||
case self::RESIZEMODE_SCALE_WIDTH:
|
||||
$height = $this->height;
|
||||
$width = round($originalRatio * $this->height);
|
||||
break;
|
||||
case self::RESIZEMODE_SCALE_HEIGHT:
|
||||
$width = $this->width;
|
||||
$height = round($this->width / $originalRatio);
|
||||
break;
|
||||
case self::RESIZEMODE_INSET:
|
||||
$targetRatio = $this->width / $this->height;
|
||||
|
||||
if ($targetRatio > $originalRatio) {
|
||||
$height = $this->height;
|
||||
$width = round($originalRatio * $this->height);
|
||||
} else {
|
||||
$width = $this->width;
|
||||
$height = round($this->width / $originalRatio);
|
||||
}
|
||||
break;
|
||||
case self::RESIZEMODE_FIT:
|
||||
default:
|
||||
if (null !== $this->width && null !== $this->height) {
|
||||
$width = $this->width;
|
||||
$height = $this->height;
|
||||
} else {
|
||||
$width = $originalWidth;
|
||||
$height = $originalHeight;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return new Dimension($width, $height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resize mode
|
||||
*
|
||||
* @param string $mode The mode, one of the self::RESIZEMODE_* constants
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setResizeMode($mode)
|
||||
{
|
||||
if ( ! in_array($mode, array(self::RESIZEMODE_FIT, self::RESIZEMODE_INSET, self::RESIZEMODE_SCALE_WIDTH, self::RESIZEMODE_SCALE_HEIGHT))) {
|
||||
throw new InvalidArgumentException(
|
||||
'Resize mode `%s` is not valid , avalaible values are %s',
|
||||
$mode,
|
||||
implode(', ', array(self::RESIZEMODE_FIT, self::RESIZEMODE_INSET, self::RESIZEMODE_SCALE_WIDTH, self::RESIZEMODE_SCALE_HEIGHT))
|
||||
);
|
||||
}
|
||||
|
||||
$this->resizeMode = $mode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current resize mode name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getResizeMode()
|
||||
{
|
||||
return $this->resizeMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFrameRate()
|
||||
public function getKiloBitrate()
|
||||
{
|
||||
return $this->frameRate;
|
||||
return $this->kiloBitrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the framerate
|
||||
* Sets the kiloBitrate value
|
||||
*
|
||||
* @param integer $frameRate
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @param integer $kiloBitrate
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setFrameRate($frameRate)
|
||||
public function setKiloBitrate($kiloBitrate)
|
||||
{
|
||||
if ($frameRate < 1) {
|
||||
throw new InvalidArgumentException('Wrong framerate value');
|
||||
if ($kiloBitrate < 1) {
|
||||
throw new InvalidArgumentException('Wrong kiloBitrate value');
|
||||
}
|
||||
|
||||
$this->frameRate = (int) $frameRate;
|
||||
$this->kiloBitrate = (int) $kiloBitrate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -189,11 +66,11 @@ abstract class DefaultVideo extends DefaultAudio implements Interactive, Resampl
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the video codec, Should be in the available ones, otherwise an
|
||||
* Sets the video codec, Should be in the available ones, otherwise an
|
||||
* exception is thrown
|
||||
*
|
||||
* @param string $videoCodec
|
||||
* @throws \InvalidArgumentException
|
||||
* @param string $videoCodec
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setVideoCodec($videoCodec)
|
||||
{
|
||||
|
|
@ -209,32 +86,6 @@ abstract class DefaultVideo extends DefaultAudio implements Interactive, Resampl
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGOPsize()
|
||||
{
|
||||
return $this->GOPsize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the GOP size
|
||||
*
|
||||
* @param integer $GOPsize
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setGOPsize($GOPsize)
|
||||
{
|
||||
if ($GOPsize < 1) {
|
||||
throw new InvalidArgumentException('Wrong GOP size value');
|
||||
}
|
||||
|
||||
$this->GOPsize = (int) $GOPsize;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
@ -244,24 +95,27 @@ abstract class DefaultVideo extends DefaultAudio implements Interactive, Resampl
|
|||
}
|
||||
|
||||
/**
|
||||
* Used to determine what resolutions sizes are valid.
|
||||
*
|
||||
* @param int $value
|
||||
*/
|
||||
public function setModulus($value)
|
||||
{
|
||||
if(!in_array($value, array(2, 4, 8, 16))){
|
||||
throw new InvalidArgumentException('Wrong modulus division value. Valid values are 2, 4, 8 or 16');
|
||||
}
|
||||
|
||||
$this->modulus = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @return integer
|
||||
*/
|
||||
public function getModulus()
|
||||
{
|
||||
return $this->modulus;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total)
|
||||
{
|
||||
$format = $this;
|
||||
$listeners = array(new VideoProgressListener($ffprobe, $media->getPathfile(), $pass, $total));
|
||||
|
||||
foreach ($listeners as $listener) {
|
||||
$listener->on('progress', function () use ($format, $media) {
|
||||
$format->emit('progress', array_merge(array($media, $format), func_get_args()));
|
||||
});
|
||||
}
|
||||
|
||||
return $listeners;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Video;
|
||||
|
||||
/**
|
||||
* The interactive video interface. This provide a method to list available
|
||||
* codecs. This is usefull to build interactive development and switch between
|
||||
* different codecs
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Interactive extends Transcodable
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the list of available video codecs for this format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableVideoCodecs();
|
||||
}
|
||||
|
|
@ -13,13 +13,15 @@ namespace FFMpeg\Format\Video;
|
|||
|
||||
/**
|
||||
* The Ogg video format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class Ogg extends DefaultVideo
|
||||
{
|
||||
protected $audioCodec = 'libvorbis';
|
||||
protected $videoCodec = 'libtheora';
|
||||
public function __construct($audioCodec = 'libvorbis', $videoCodec = 'libtheora')
|
||||
{
|
||||
$this
|
||||
->setAudioCodec($audioCodec)
|
||||
->setVideoCodec($videoCodec);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Video;
|
||||
|
||||
use FFMpeg\Format\VideoInterface;
|
||||
|
||||
/**
|
||||
* The resamplable video interface
|
||||
*
|
||||
* This interface provides frame rate and GOP size settings for video encoding
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Resamplable extends VideoInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the frame rate
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getFrameRate();
|
||||
|
||||
/**
|
||||
* Returns true if the current format supports B-Frames
|
||||
*
|
||||
* @see https://wikipedia.org/wiki/Video_compression_picture_types
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function supportBFrames();
|
||||
|
||||
/**
|
||||
* Returns the GOP size
|
||||
*
|
||||
* @see https://wikipedia.org/wiki/Group_of_pictures
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getGOPSize();
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Video;
|
||||
|
||||
use FFMpeg\Format\VideoInterface;
|
||||
use FFMpeg\Format\Dimension;
|
||||
|
||||
/**
|
||||
* The resizable video interface
|
||||
*
|
||||
* This interface provides methods for video resizing.
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Resizable extends VideoInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the computed dimensions for the resize, after operation.
|
||||
* This method return the actual dimensions that FFmpeg will use.
|
||||
*
|
||||
* @param integer $originalWidth
|
||||
* @param integer $originalHeight
|
||||
* @return Dimension A dimension
|
||||
*/
|
||||
public function getComputedDimensions($originalWidth, $originalHeight);
|
||||
|
||||
/**
|
||||
* Returns the modulus used by the Resizable video.
|
||||
*
|
||||
* This used to calculate the target dimensions while maintaining the best
|
||||
* aspect ratio.
|
||||
*
|
||||
* @see http://www.undeadborn.net/tools/rescalculator.php
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getModulus();
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of PHP-FFmpeg.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FFMpeg\Format\Video;
|
||||
|
||||
use FFMpeg\Format\VideoInterface;
|
||||
|
||||
/**
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface Transcodable extends VideoInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the video codec
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVideoCodec();
|
||||
}
|
||||
|
|
@ -13,13 +13,15 @@ namespace FFMpeg\Format\Video;
|
|||
|
||||
/**
|
||||
* The WMV video format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class WMV extends DefaultVideo
|
||||
{
|
||||
protected $audioCodec = 'wmav2';
|
||||
protected $videoCodec = 'wmv2';
|
||||
public function __construct($audioCodec = 'wmav2', $videoCodec = 'wmv2')
|
||||
{
|
||||
$this
|
||||
->setAudioCodec($audioCodec)
|
||||
->setVideoCodec($videoCodec);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@ namespace FFMpeg\Format\Video;
|
|||
|
||||
/**
|
||||
* The WMV video format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class WMV3 extends DefaultVideo
|
||||
{
|
||||
protected $audioCodec = 'wmav3';
|
||||
protected $videoCodec = 'wmv3';
|
||||
public function __construct($audioCodec = 'wmav3', $videoCodec = 'wmv3')
|
||||
{
|
||||
$this
|
||||
->setAudioCodec($audioCodec)
|
||||
->setVideoCodec($videoCodec);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@ namespace FFMpeg\Format\Video;
|
|||
|
||||
/**
|
||||
* The WebM video format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class WebM extends DefaultVideo
|
||||
{
|
||||
protected $audioCodec = 'libvorbis';
|
||||
protected $videoCodec = 'libvpx';
|
||||
public function __construct($audioCodec = 'libvorbis', $videoCodec = 'libvpx')
|
||||
{
|
||||
$this
|
||||
->setAudioCodec($audioCodec)
|
||||
->setVideoCodec($videoCodec);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@ namespace FFMpeg\Format\Video;
|
|||
|
||||
/**
|
||||
* The X264 video format
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
class X264 extends DefaultVideo
|
||||
{
|
||||
protected $audioCodec = 'libmp3lame';
|
||||
protected $videoCodec = 'libx264';
|
||||
public function __construct($audioCodec = 'libfaac', $videoCodec = 'libx264')
|
||||
{
|
||||
$this
|
||||
->setAudioCodec($audioCodec)
|
||||
->setVideoCodec($videoCodec);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
|||
|
|
@ -11,17 +11,54 @@
|
|||
|
||||
namespace FFMpeg\Format;
|
||||
|
||||
/**
|
||||
* The base video interface
|
||||
*
|
||||
* @author Romain Neutron imprec@gmail.com
|
||||
*/
|
||||
interface VideoInterface extends AudioInterface
|
||||
{
|
||||
/**
|
||||
* Get the kiloBitrate value
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getKiloBitrate();
|
||||
|
||||
/**
|
||||
* Returns the number of passes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPasses();
|
||||
|
||||
/**
|
||||
* Returns the modulus used by the Resizable video.
|
||||
*
|
||||
* This used to calculate the target dimensions while maintaining the best
|
||||
* aspect ratio.
|
||||
*
|
||||
* @see http://www.undeadborn.net/tools/rescalculator.php
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getModulus();
|
||||
|
||||
/**
|
||||
* Returns the video codec
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVideoCodec();
|
||||
|
||||
/**
|
||||
* Returns true if the current format supports B-Frames
|
||||
*
|
||||
* @see https://wikipedia.org/wiki/Video_compression_picture_types
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function supportBFrames();
|
||||
|
||||
/**
|
||||
* Returns the list of available video codecs for this format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableVideoCodecs();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue