scratch

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 114  →  ?path2? @ 115
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/AbstractMediaType.php
@@ -0,0 +1,113 @@
<?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\Media;
 
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe;
use FFMpeg\Filters\FiltersCollection;
 
abstract class AbstractMediaType implements MediaTypeInterface
{
/** @var string */
protected $pathfile;
/** @var FFMpegDriver */
protected $driver;
/** @var FFProbe */
protected $ffprobe;
/** @var FiltersCollection */
protected $filters;
 
public function __construct($pathfile, FFMpegDriver $driver, FFProbe $ffprobe)
{
$this->pathfile = $pathfile;
$this->driver = $driver;
$this->ffprobe = $ffprobe;
$this->filters = new FiltersCollection();
}
 
/**
* @return FFMpegDriver
*/
public function getFFMpegDriver()
{
return $this->driver;
}
 
/**
* @param FFMpegDriver $driver
*
* @return MediaTypeInterface
*/
public function setFFMpegDriver(FFMpegDriver $driver)
{
$this->driver = $driver;
 
return $this;
}
 
/**
* @return FFProbe
*/
public function getFFProbe()
{
return $this->ffprobe;
}
 
/**
* @param FFProbe $ffprobe
*
* @return MediaTypeInterface
*/
public function setFFProbe(FFProbe $ffprobe)
{
$this->ffprobe = $ffprobe;
 
return $this;
}
 
/**
* @return string
*/
public function getPathfile()
{
return $this->pathfile;
}
 
/**
* @param FiltersCollection $filters
*
* @return MediaTypeInterface
*/
public function setFiltersCollection(FiltersCollection $filters)
{
$this->filters = $filters;
 
return $this;
}
 
/**
* @return MediaTypeInterface
*/
public function getFiltersCollection()
{
return $this->filters;
}
 
protected function cleanupTemporaryFile($filename)
{
if (file_exists($filename) && is_writable($filename)) {
unlink($filename);
}
 
return $this;
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/AbstractStreamableMedia.php
@@ -0,0 +1,40 @@
<?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\Media;
 
use FFMpeg\FFProbe\DataMapping\Format;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
 
abstract class AbstractStreamableMedia extends AbstractMediaType
{
private $streams;
 
/**
* @return StreamCollection
*/
public function getStreams()
{
if (null === $this->streams) {
$this->streams = $this->ffprobe->streams($this->pathfile);
}
 
return $this->streams;
}
 
/**
* @return Format
*/
public function getFormat()
{
return $this->ffprobe->format($this->pathfile);
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/Audio.php
@@ -0,0 +1,117 @@
<?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\Media;
 
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Filters\Audio\AudioFilters;
use FFMpeg\Format\FormatInterface;
use FFMpeg\Filters\Audio\SimpleFilter;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Exception\InvalidArgumentException;
use FFMpeg\Filters\Audio\AudioFilterInterface;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\ProgressableInterface;
 
class Audio extends AbstractStreamableMedia
{
/**
* {@inheritdoc}
*
* @return AudioFilters
*/
public function filters()
{
return new AudioFilters($this);
}
 
/**
* {@inheritdoc}
*
* @return Audio
*/
public function addFilter(FilterInterface $filter)
{
if (!$filter instanceof AudioFilterInterface) {
throw new InvalidArgumentException('Audio only accepts AudioFilterInterface filters');
}
 
$this->filters->add($filter);
 
return $this;
}
 
/**
* Exports the audio in the desired format, applies registered filters.
*
* @param FormatInterface $format
* @param string $outputPathfile
*
* @return Audio
*
* @throws RuntimeException
*/
public function save(FormatInterface $format, $outputPathfile)
{
$listeners = null;
 
if ($format instanceof ProgressableInterface) {
$listeners = $format->createProgressListener($this, $this->ffprobe, 1, 1);
}
 
$commands = array('-y', '-i', $this->pathfile);
 
$filters = clone $this->filters;
$filters->add(new SimpleFilter($format->getExtraParams(), 10));
 
if ($this->driver->getConfiguration()->has('ffmpeg.threads')) {
$filters->add(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads'))));
}
if (null !== $format->getAudioCodec()) {
$filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec())));
}
 
foreach ($filters as $filter) {
$commands = array_merge($commands, $filter->apply($this, $format));
}
 
if (null !== $format->getAudioKiloBitrate()) {
$commands[] = '-b:a';
$commands[] = $format->getAudioKiloBitrate() . 'k';
}
if (null !== $format->getAudioChannels()) {
$commands[] = '-ac';
$commands[] = $format->getAudioChannels();
}
$commands[] = $outputPathfile;
 
try {
$this->driver->command($commands, false, $listeners);
} catch (ExecutionFailureException $e) {
$this->cleanupTemporaryFile($outputPathfile);
throw new RuntimeException('Encoding failed', $e->getCode(), $e);
}
 
return $this;
}
 
/**
* Gets the waveform of the video.
*
* @param integer $width
* @param integer $height
* @return Waveform
*/
public function waveform($width = 640, $height = 120)
{
return new Waveform($this, $this->driver, $this->ffprobe, $width, $height);
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/Concat.php
@@ -0,0 +1,264 @@
<?php
 
/*
* This file is part of PHP-FFmpeg.
*
* (c) Strime <contact@strime.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
 
namespace FFMpeg\Media;
 
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use Alchemy\BinaryDriver\Exception\InvalidArgumentException;
use FFMpeg\Filters\Concat\ConcatFilterInterface;
use FFMpeg\Filters\Concat\ConcatFilters;
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe;
use FFMpeg\Filters\Audio\SimpleFilter;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Format\FormatInterface;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Format\VideoInterface;
use Neutron\TemporaryFilesystem\Manager as FsManager;
 
class Concat extends AbstractMediaType
{
/** @var array */
private $sources;
 
public function __construct($sources, FFMpegDriver $driver, FFProbe $ffprobe)
{
parent::__construct($sources, $driver, $ffprobe);
$this->sources = $sources;
}
 
/**
* Returns the path to the sources.
*
* @return string
*/
public function getSources()
{
return $this->sources;
}
 
/**
* {@inheritdoc}
*
* @return ConcatFilters
*/
public function filters()
{
return new ConcatFilters($this);
}
 
/**
* {@inheritdoc}
*
* @return Concat
*/
public function addFilter(ConcatFilterInterface $filter)
{
$this->filters->add($filter);
 
return $this;
}
 
/**
* Saves the concatenated video in the given array, considering that the sources videos are all encoded with the same codec.
*
* @param array $outputPathfile
* @param string $streamCopy
*
* @return Concat
*
* @throws RuntimeException
*/
public function saveFromSameCodecs($outputPathfile, $streamCopy = TRUE)
{
/**
* @see https://ffmpeg.org/ffmpeg-formats.html#concat
* @see https://trac.ffmpeg.org/wiki/Concatenate
*/
 
// Create the file which will contain the list of videos
$fs = FsManager::create();
$sourcesFile = $fs->createTemporaryFile('ffmpeg-concat');
 
// Set the content of this file
$fileStream = @fopen($sourcesFile, 'w');
 
if($fileStream === false) {
throw new ExecutionFailureException('Cannot open the temporary file.');
}
 
$count_videos = 0;
if(is_array($this->sources) && (count($this->sources) > 0)) {
foreach ($this->sources as $videoPath) {
$line = "";
 
if($count_videos != 0)
$line .= "\n";
 
$line .= "file ".$videoPath;
 
fwrite($fileStream, $line);
 
$count_videos++;
}
}
else {
throw new InvalidArgumentException('The list of videos is not a valid array.');
}
fclose($fileStream);
 
 
$commands = array(
'-f', 'concat', '-safe', '0',
'-i', $sourcesFile
);
 
// Check if stream copy is activated
if($streamCopy === TRUE) {
$commands[] = '-c';
$commands[] = 'copy';
}
 
// If not, we can apply filters
else {
foreach ($this->filters as $filter) {
$commands = array_merge($commands, $filter->apply($this));
}
}
 
// Set the output file in the command
$commands = array_merge($commands, array($outputPathfile));
 
// Execute the command
try {
$this->driver->command($commands);
} catch (ExecutionFailureException $e) {
$this->cleanupTemporaryFile($outputPathfile);
$this->cleanupTemporaryFile($sourcesFile);
throw new RuntimeException('Unable to save concatenated video', $e->getCode(), $e);
}
 
$this->cleanupTemporaryFile($sourcesFile);
return $this;
}
 
/**
* Saves the concatenated video in the given filename, considering that the sources videos are all encoded with the same codec.
*
* @param string $outputPathfile
*
* @return Concat
*
* @throws RuntimeException
*/
public function saveFromDifferentCodecs(FormatInterface $format, $outputPathfile)
{
/**
* @see https://ffmpeg.org/ffmpeg-formats.html#concat
* @see https://trac.ffmpeg.org/wiki/Concatenate
*/
 
// Check the validity of the parameter
if(!is_array($this->sources) || (count($this->sources) == 0)) {
throw new InvalidArgumentException('The list of videos is not a valid array.');
}
 
// Create the commands variable
$commands = array();
 
// Prepare the parameters
$nbSources = 0;
$files = array();
 
// For each source, check if this is a legit file
// and prepare the parameters
foreach ($this->sources as $videoPath) {
$files[] = '-i';
$files[] = $videoPath;
$nbSources++;
}
 
$commands = array_merge($commands, $files);
 
// Set the parameters of the request
$commands[] = '-filter_complex';
 
$complex_filter = '';
for($i=0; $i<$nbSources; $i++) {
$complex_filter .= '['.$i.':v:0] ['.$i.':a:0] ';
}
$complex_filter .= 'concat=n='.$nbSources.':v=1:a=1 [v] [a]';
 
$commands[] = $complex_filter;
$commands[] = '-map';
$commands[] = '[v]';
$commands[] = '-map';
$commands[] = '[a]';
 
// Prepare the filters
$filters = clone $this->filters;
$filters->add(new SimpleFilter($format->getExtraParams(), 10));
 
if ($this->driver->getConfiguration()->has('ffmpeg.threads')) {
$filters->add(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads'))));
}
if ($format instanceof VideoInterface) {
if (null !== $format->getVideoCodec()) {
$filters->add(new SimpleFilter(array('-vcodec', $format->getVideoCodec())));
}
}
if ($format instanceof AudioInterface) {
if (null !== $format->getAudioCodec()) {
$filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec())));
}
}
 
// Add the filters
foreach ($this->filters as $filter) {
$commands = array_merge($commands, $filter->apply($this));
}
 
if ($format instanceof AudioInterface) {
if (null !== $format->getAudioKiloBitrate()) {
$commands[] = '-b:a';
$commands[] = $format->getAudioKiloBitrate() . 'k';
}
if (null !== $format->getAudioChannels()) {
$commands[] = '-ac';
$commands[] = $format->getAudioChannels();
}
}
 
// If the user passed some additional parameters
if ($format instanceof VideoInterface) {
if (null !== $format->getAdditionalParameters()) {
foreach ($format->getAdditionalParameters() as $additionalParameter) {
$commands[] = $additionalParameter;
}
}
}
 
// Set the output file in the command
$commands[] = $outputPathfile;
 
$failure = null;
 
try {
$this->driver->command($commands);
} catch (ExecutionFailureException $e) {
throw new RuntimeException('Encoding failed', $e->getCode(), $e);
}
 
return $this;
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/Frame.php
@@ -0,0 +1,133 @@
<?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\Media;
 
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Filters\Frame\FrameFilterInterface;
use FFMpeg\Filters\Frame\FrameFilters;
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Coordinate\TimeCode;
 
class Frame extends AbstractMediaType
{
/** @var TimeCode */
private $timecode;
/** @var Video */
private $video;
 
public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe, TimeCode $timecode)
{
parent::__construct($video->getPathfile(), $driver, $ffprobe);
$this->timecode = $timecode;
$this->video = $video;
}
 
/**
* Returns the video related to the frame.
*
* @return Video
*/
public function getVideo()
{
return $this->video;
}
 
/**
* {@inheritdoc}
*
* @return FrameFilters
*/
public function filters()
{
return new FrameFilters($this);
}
 
/**
* {@inheritdoc}
*
* @return Frame
*/
public function addFilter(FrameFilterInterface $filter)
{
$this->filters->add($filter);
 
return $this;
}
 
/**
* @return TimeCode
*/
public function getTimeCode()
{
return $this->timecode;
}
 
/**
* Saves the frame in the given filename.
*
* Uses the `unaccurate method by default.`
*
* @param string $pathfile
* @param Boolean $accurate
*
* @return Frame
*
* @throws RuntimeException
*/
public function save($pathfile, $accurate = false, $returnBase64 = false)
{
/**
* might be optimized with http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg
* @see http://ffmpeg.org/ffmpeg.html#Main-options
*/
$outputFormat = $returnBase64 ? "image2pipe" : "image2";
if (!$accurate) {
$commands = array(
'-y', '-ss', (string) $this->timecode,
'-i', $this->pathfile,
'-vframes', '1',
'-f', $outputFormat
);
} else {
$commands = array(
'-y', '-i', $this->pathfile,
'-vframes', '1', '-ss', (string) $this->timecode,
'-f', $outputFormat
);
}
if($returnBase64) {
array_push($commands, "-");
}
 
foreach ($this->filters as $filter) {
$commands = array_merge($commands, $filter->apply($this));
}
 
$commands = array_merge($commands, array($pathfile));
 
try {
if(!$returnBase64) {
$this->driver->command($commands);
return $this;
}
else {
return $this->driver->command($commands);
}
} catch (ExecutionFailureException $e) {
$this->cleanupTemporaryFile($pathfile);
throw new RuntimeException('Unable to save frame', $e->getCode(), $e);
}
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/Gif.php
@@ -0,0 +1,137 @@
<?php
 
/*
* This file is part of PHP-FFmpeg.
*
* (c) Strime <contact@strime.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
 
namespace FFMpeg\Media;
 
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Filters\Gif\GifFilterInterface;
use FFMpeg\Filters\Gif\GifFilters;
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Coordinate\Dimension;
 
class Gif extends AbstractMediaType
{
/** @var TimeCode */
private $timecode;
/** @var Dimension */
private $dimension;
/** @var integer */
private $duration;
/** @var Video */
private $video;
 
public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe, TimeCode $timecode, Dimension $dimension, $duration = null)
{
parent::__construct($video->getPathfile(), $driver, $ffprobe);
$this->timecode = $timecode;
$this->dimension = $dimension;
$this->duration = $duration;
$this->video = $video;
}
 
/**
* Returns the video related to the gif.
*
* @return Video
*/
public function getVideo()
{
return $this->video;
}
 
/**
* {@inheritdoc}
*
* @return GifFilters
*/
public function filters()
{
return new GifFilters($this);
}
 
/**
* {@inheritdoc}
*
* @return Gif
*/
public function addFilter(GifFilterInterface $filter)
{
$this->filters->add($filter);
 
return $this;
}
 
/**
* @return TimeCode
*/
public function getTimeCode()
{
return $this->timecode;
}
 
/**
* @return Dimension
*/
public function getDimension()
{
return $this->dimension;
}
 
/**
* Saves the gif in the given filename.
*
* @param string $pathfile
*
* @return Gif
*
* @throws RuntimeException
*/
public function save($pathfile)
{
/**
* @see http://ffmpeg.org/ffmpeg.html#Main-options
*/
$commands = array(
'-ss', (string)$this->timecode
);
 
if(null !== $this->duration) {
$commands[] = '-t';
$commands[] = (string)$this->duration;
}
 
$commands[] = '-i';
$commands[] = $this->pathfile;
$commands[] = '-vf';
$commands[] = 'scale=' . $this->dimension->getWidth() . ':-1';
$commands[] = '-gifflags';
$commands[] = '+transdiff';
$commands[] = '-y';
 
foreach ($this->filters as $filter) {
$commands = array_merge($commands, $filter->apply($this));
}
 
$commands = array_merge($commands, array($pathfile));
 
try {
$this->driver->command($commands);
} catch (ExecutionFailureException $e) {
$this->cleanupTemporaryFile($pathfile);
throw new RuntimeException('Unable to save gif', $e->getCode(), $e);
}
 
return $this;
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/MediaTypeInterface.php
@@ -0,0 +1,25 @@
<?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\Media;
 
interface MediaTypeInterface
{
/**
* Returns the available filters.
*/
public function filters();
 
/**
* @return string
*/
public function getPathfile();
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/Video.php
@@ -0,0 +1,268 @@
<?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\Media;
 
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Filters\Audio\SimpleFilter;
use FFMpeg\Exception\InvalidArgumentException;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Filters\Video\VideoFilters;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\FormatInterface;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Format\VideoInterface;
use Neutron\TemporaryFilesystem\Manager as FsManager;
 
class Video extends Audio
{
/**
* {@inheritdoc}
*
* @return VideoFilters
*/
public function filters()
{
return new VideoFilters($this);
}
 
/**
* {@inheritdoc}
*
* @return Video
*/
public function addFilter(FilterInterface $filter)
{
$this->filters->add($filter);
 
return $this;
}
 
/**
* Exports the video in the desired format, applies registered filters.
*
* @param FormatInterface $format
* @param string $outputPathfile
*
* @return Video
*
* @throws RuntimeException
*/
public function save(FormatInterface $format, $outputPathfile)
{
$commands = array('-y', '-i', $this->pathfile);
 
$filters = clone $this->filters;
$filters->add(new SimpleFilter($format->getExtraParams(), 10));
 
if ($this->driver->getConfiguration()->has('ffmpeg.threads')) {
$filters->add(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads'))));
}
if ($format instanceof VideoInterface) {
if (null !== $format->getVideoCodec()) {
$filters->add(new SimpleFilter(array('-vcodec', $format->getVideoCodec())));
}
}
if ($format instanceof AudioInterface) {
if (null !== $format->getAudioCodec()) {
$filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec())));
}
}
 
foreach ($filters as $filter) {
$commands = array_merge($commands, $filter->apply($this, $format));
}
 
if ($format instanceof VideoInterface) {
$commands[] = '-b:v';
$commands[] = $format->getKiloBitrate() . 'k';
$commands[] = '-refs';
$commands[] = '6';
$commands[] = '-coder';
$commands[] = '1';
$commands[] = '-sc_threshold';
$commands[] = '40';
$commands[] = '-flags';
$commands[] = '+loop';
$commands[] = '-me_range';
$commands[] = '16';
$commands[] = '-subq';
$commands[] = '7';
$commands[] = '-i_qfactor';
$commands[] = '0.71';
$commands[] = '-qcomp';
$commands[] = '0.6';
$commands[] = '-qdiff';
$commands[] = '4';
$commands[] = '-trellis';
$commands[] = '1';
}
 
if ($format instanceof AudioInterface) {
if (null !== $format->getAudioKiloBitrate()) {
$commands[] = '-b:a';
$commands[] = $format->getAudioKiloBitrate() . 'k';
}
if (null !== $format->getAudioChannels()) {
$commands[] = '-ac';
$commands[] = $format->getAudioChannels();
}
}
 
// If the user passed some additional parameters
if ($format instanceof VideoInterface) {
if (null !== $format->getAdditionalParameters()) {
foreach ($format->getAdditionalParameters() as $additionalParameter) {
$commands[] = $additionalParameter;
}
}
}
 
// Merge Filters into one command
$videoFilterVars = $videoFilterProcesses = [];
for($i=0;$i<count($commands);$i++) {
$command = $commands[$i];
if ( $command == '-vf' ) {
$commandSplits = explode(";", $commands[$i + 1]);
if ( count($commandSplits) == 1 ) {
$commandSplit = $commandSplits[0];
$command = trim($commandSplit);
if ( preg_match("/^\[in\](.*?)\[out\]$/is", $command, $match) ) {
$videoFilterProcesses[] = $match[1];
} else {
$videoFilterProcesses[] = $command;
}
} else {
foreach($commandSplits as $commandSplit) {
$command = trim($commandSplit);
if ( preg_match("/^\[[^\]]+\](.*?)\[[^\]]+\]$/is", $command, $match) ) {
$videoFilterProcesses[] = $match[1];
} else {
$videoFilterVars[] = $command;
}
}
}
unset($commands[$i]);
unset($commands[$i + 1]);
$i++;
}
}
$videoFilterCommands = $videoFilterVars;
$lastInput = 'in';
foreach($videoFilterProcesses as $i => $process) {
$command = '[' . $lastInput .']';
$command .= $process;
$lastInput = 'p' . $i;
if ( $i == count($videoFilterProcesses) - 1 ) {
$command .= '[out]';
} else {
$command .= '[' . $lastInput . ']';
}
$videoFilterCommands[] = $command;
}
$videoFilterCommand = implode(";", $videoFilterCommands);
if ( $videoFilterCommand ) {
$commands[] = '-vf';
$commands[] = $videoFilterCommand;
}
$fs = FsManager::create();
$fsId = uniqid('ffmpeg-passes');
$passPrefix = $fs->createTemporaryDirectory(0777, 50, $fsId) . '/' . uniqid('pass-');
$passes = array();
$totalPasses = $format->getPasses();
 
if (1 > $totalPasses) {
throw new InvalidArgumentException('Pass number should be a positive value.');
}
 
for ($i = 1; $i <= $totalPasses; $i++) {
$pass = $commands;
 
if ($totalPasses > 1) {
$pass[] = '-pass';
$pass[] = $i;
$pass[] = '-passlogfile';
$pass[] = $passPrefix;
}
 
$pass[] = $outputPathfile;
 
$passes[] = $pass;
}
 
$failure = null;
 
foreach ($passes as $pass => $passCommands) {
try {
/** add listeners here */
$listeners = null;
 
if ($format instanceof ProgressableInterface) {
$listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, $totalPasses);
}
 
$this->driver->command($passCommands, false, $listeners);
} catch (ExecutionFailureException $e) {
$failure = $e;
break;
}
}
 
$fs->clean($fsId);
 
if (null !== $failure) {
throw new RuntimeException('Encoding failed', $failure->getCode(), $failure);
}
 
return $this;
}
 
/**
* Gets the frame at timecode.
*
* @param TimeCode $at
* @return Frame
*/
public function frame(TimeCode $at)
{
return new Frame($this, $this->driver, $this->ffprobe, $at);
}
 
/**
* Extracts a gif from a sequence of the video.
*
* @param TimeCode $at
* @param Dimension $dimension
* @param integer $duration
* @return Gif
*/
public function gif(TimeCode $at, Dimension $dimension, $duration = null)
{
return new Gif($this, $this->driver, $this->ffprobe, $at, $dimension, $duration);
}
 
/**
* Concatenates a list of videos into one unique video.
*
* @param array $sources
* @return Concat
*/
public function concat($sources)
{
return new Concat($sources, $this->driver, $this->ffprobe);
}
}
/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/Waveform.php
@@ -0,0 +1,104 @@
<?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\Media;
 
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Filters\Waveform\WaveformFilterInterface;
use FFMpeg\Filters\Waveform\WaveformFilters;
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe;
use FFMpeg\Exception\RuntimeException;
 
class Waveform extends AbstractMediaType
{
/** @var Video */
private $audio;
private $width;
private $height;
 
public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height)
{
parent::__construct($audio->getPathfile(), $driver, $ffprobe);
$this->audio = $audio;
$this->width = $width;
$this->height = $height;
}
 
/**
* Returns the audio related to the waveform.
*
* @return Audio
*/
public function getAudio()
{
return $this->audio;
}
 
/**
* {@inheritdoc}
*
* @return WaveformFilters
*/
public function filters()
{
return new WaveformFilters($this);
}
 
/**
* {@inheritdoc}
*
* @return Waveform
*/
public function addFilter(WaveformFilterInterface $filter)
{
$this->filters->add($filter);
 
return $this;
}
 
/**
* Saves the waveform in the given filename.
*
* @param string $pathfile
*
* @return Waveform
*
* @throws RuntimeException
*/
public function save($pathfile)
{
/**
* might be optimized with http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg
* @see http://ffmpeg.org/ffmpeg.html#Main-options
*/
$commands = array(
'-i', $this->pathfile, '-filter_complex',
'showwavespic=s='.$this->width.'x'.$this->height,
'-frames:v', '1'
);
 
foreach ($this->filters as $filter) {
$commands = array_merge($commands, $filter->apply($this));
}
 
$commands = array_merge($commands, array($pathfile));
 
try {
$this->driver->command($commands);
} catch (ExecutionFailureException $e) {
$this->cleanupTemporaryFile($pathfile);
throw new RuntimeException('Unable to save waveform', $e->getCode(), $e);
}
 
return $this;
}
}