Version 0.3

This commit is contained in:
Romain Neutron 2013-06-25 10:03:20 +02:00
commit ad3a5af623
130 changed files with 7283 additions and 2627 deletions

View file

@ -0,0 +1,29 @@
<?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\Filters\Audio;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Media\Audio;
interface AudioFilterInterface extends FilterInterface
{
/**
* Applies the filter on the the Audio media given an format.
*
* @param Audio $audio
* @param AudioInterface $format
*
* @return array An array of arguments
*/
public function apply(Audio $audio, AudioInterface $format);
}

View file

@ -0,0 +1,30 @@
<?php
namespace FFMpeg\Filters\Audio;
use FFMpeg\Media\Audio;
use FFMpeg\Filters\Audio\AudioResamplableFilter;
class AudioFilters
{
private $audio;
public function __construct(Audio $audio)
{
$this->audio = $audio;
}
/**
* Resamples the audio file.
*
* @param Integer $rate
*
* @return AudioFilters
*/
public function resample($rate)
{
$this->audio->addFilter(new AudioResamplableFilter($rate));
return $this;
}
}

View file

@ -0,0 +1,43 @@
<?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\Filters\Audio;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Media\Audio;
class AudioResamplableFilter implements AudioFilterInterface
{
/** @var string */
private $rate;
public function __construct($rate)
{
$this->rate = $rate;
}
/**
*
* @return Integer
*/
public function getRate()
{
return $this->rate;
}
/**
* {@inheritdoc}
*/
public function apply(Audio $audio, AudioInterface $format)
{
return array('-ac', 2, '-ar', $this->rate);
}
}

View 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\Filters;
interface FilterInterface
{
}

View file

@ -0,0 +1,45 @@
<?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\Filters;
class FiltersCollection implements \Countable, \IteratorAggregate
{
private $filters = array();
/**
* @param FilterInterface $filter
*
* @return FiltersCollection
*/
public function add(FilterInterface $filter)
{
$this->filters[] = $filter;
return $this;
}
/**
* {@inheritdoc}
*/
public function count()
{
return count($this->filters);
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
return new \ArrayIterator($this->filters);
}
}

View file

@ -0,0 +1,21 @@
<?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\Filters\Frame;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Media\Frame;
use FFMpeg\Format\FrameInterface;
interface FrameFilterInterface extends FilterInterface
{
public function apply(Frame $frame, FrameInterface $format);
}

View file

@ -0,0 +1,24 @@
<?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\Filters\Frame;
use FFMpeg\Media\Frame;
class FrameFilters
{
private $frame;
public function __construct(Frame $frame)
{
$this->frame = $frame;
}
}

View file

@ -0,0 +1,126 @@
<?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\Filters\Video;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Media\Video;
use FFMpeg\Format\VideoInterface;
class ResizeFilter implements VideoFilterInterface
{
const RESIZEMODE_FIT = 'fit';
const RESIZEMODE_INSET = 'inset';
const RESIZEMODE_SCALE_WIDTH = 'width';
const RESIZEMODE_SCALE_HEIGHT = 'height';
/** @var Dimension */
private $dimension;
/** @var string */
private $mode;
/** @var Boolean */
private $forceStandards;
public function __construct(Dimension $dimension, $mode = self::RESIZEMODE_FIT, $forceStandards = true)
{
$this->dimension = $dimension;
$this->mode = $mode;
$this->forceStandards = $forceStandards;
}
/**
* @return Dimension
*/
public function getDimension()
{
return $this->dimension;
}
/**
* @return string
*/
public function getMode()
{
return $this->mode;
}
/**
* @return Boolean
*/
public function areStandardsForced()
{
return $this->forceStandards;
}
/**
* {@inheritdoc}
*/
public function apply(Video $video, VideoInterface $format)
{
$originalWidth = $originalHeight = null;
foreach ($video->getStreams() as $stream) {
if ($stream->isVideo()) {
if ($stream->has('width')) {
$originalWidth = $stream->get('width');
}
if ($stream->has('height')) {
$originalHeight = $stream->get('height');
}
}
}
$commands = array();
if ($originalHeight !== null && $originalWidth !== null) {
$dimensions = $this->getComputedDimensions(new Dimension($originalWidth, $originalHeight), $format->getModulus());
$commands[] = '-s';
$commands[] = $dimensions->getWidth() . 'x' . $dimensions->getHeight();
}
return $commands;
}
private function getComputedDimensions(Dimension $dimension, $modulus)
{
$originalRatio = $dimension->getRatio($this->forceStandards);
switch ($this->mode) {
case self::RESIZEMODE_SCALE_WIDTH:
$height = $this->dimension->getHeight();
$width = $originalRatio->calculateWidth($height, $modulus);
break;
case self::RESIZEMODE_SCALE_HEIGHT:
$width = $this->dimension->getWidth();
$height = $originalRatio->calculateHeight($width, $modulus);
break;
case self::RESIZEMODE_INSET:
$targetRatio = $this->dimension->getRatio($this->forceStandards);
if ($targetRatio->getValue() > $originalRatio->getValue()) {
$height = $this->dimension->getHeight();
$width = $originalRatio->calculateWidth($height, $modulus);
} else {
$width = $this->dimension->getWidth();
$height = $originalRatio->calculateHeight($width, $modulus);
}
break;
case self::RESIZEMODE_FIT:
default:
$width = $this->dimension->getWidth();
$height = $this->dimension->getHeight();
break;
}
return new Dimension($width, $height);
}
}

View file

@ -0,0 +1,49 @@
<?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\Filters\Video;
use FFMpeg\Format\VideoInterface;
use FFMpeg\Media\Video;
class SynchronizeFilter implements VideoFilterInterface
{
public function apply(Video $video, VideoInterface $format)
{
$streams = $video->getStreams();
if (null === $videoStream = $streams->videos()->first()) {
return array();
}
if (!$videoStream->has('start_time')) {
return array();
}
$params = array(
'-itsoffset',
$videoStream->get('start_time'),
'-i',
$video->getPathfile(),
);
foreach ($streams as $stream) {
if ($videoStream === $stream) {
$params[] = '-map';
$params[] = '1:' . $stream->get('index');
} else {
$params[] = '-map';
$params[] = '0:' . $stream->get('index');
}
}
return $params;
}
}

View file

@ -0,0 +1,29 @@
<?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\Filters\Video;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\VideoInterface;
use FFMpeg\Media\Video;
interface VideoFilterInterface extends FilterInterface
{
/**
* Applies the filter on the the Video media given an format.
*
* @param Video $video
* @param VideoInterface $format
*
* @return array An array of arguments
*/
public function apply(Video $video, VideoInterface $format);
}

View file

@ -0,0 +1,69 @@
<?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\Filters\Video;
use FFMpeg\Media\Video;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Coordinate\FrameRate;
class VideoFilters
{
private $video;
public function __construct(Video $video)
{
$this->video = $video;
}
/**
* Resizes a video to a given dimension
*
* @param Dimension $dimension
* @param string $mode
* @param Boolean $forceStandards
*
* @return VideoFilters
*/
public function resize(Dimension $dimension, $mode = ResizeFilter::RESIZEMODE_FIT, $forceStandards = true)
{
$this->video->addFilter(new ResizeFilter($dimension, $mode, $forceStandards));
return $this;
}
/**
* Resamples the video to the given framerate.
*
* @param FrameRate $framerate
* @param type $gop
*
* @return VideoFilters
*/
public function resample(FrameRate $framerate, $gop)
{
$this->video->addFilter(new VideoResampleFilter($framerate, $gop));
return $this;
}
/**
* Synchronizes audio and video.
*
* @return VideoFilters
*/
public function synchronize()
{
$this->video->addFilter(new SynchronizeFilter());
return $this;
}
}

View file

@ -0,0 +1,72 @@
<?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\Filters\Video;
use FFMpeg\Coordinate\FrameRate;
use FFMpeg\Media\Video;
use FFMpeg\Format\VideoInterface;
class VideoResampleFilter implements VideoFilterInterface
{
private $rate;
private $gop;
public function __construct(FrameRate $rate, $gop)
{
$this->rate = $rate;
$this->gop = $gop;
}
/**
* Returns the frame rate
*
* @return FrameRate
*/
public function getFrameRate()
{
return $this->rate;
}
/**
* Returns the GOP size
*
* @see https://wikipedia.org/wiki/Group_of_pictures
*
* @return Integer
*/
public function getGOP()
{
return $this->gop;
}
/**
* {@inheritdoc}
*/
public function apply(Video $video, VideoInterface $format)
{
$commands = array('-r', $this->rate->getValue());
/**
* @see http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
*/
if ($format->supportBFrames()) {
$commands[] = '-b_strategy';
$commands[] = '1';
$commands[] = '-bf';
$commands[] = '3';
$commands[] = '-g';
$commands[] = $this->gop;
}
return $commands;
}
}