2013-06-25 10:03:20 +02:00
|
|
|
<?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;
|
2013-06-26 00:21:12 +02:00
|
|
|
use FFMpeg\Filters\Audio\SimpleFilter;
|
2013-06-25 10:03:20 +02:00
|
|
|
use FFMpeg\Exception\RuntimeException;
|
2013-06-25 21:43:01 +02:00
|
|
|
use FFMpeg\Exception\InvalidArgumentException;
|
2013-06-25 10:03:20 +02:00
|
|
|
use FFMpeg\Filters\Audio\AudioFilterInterface;
|
2013-06-25 21:43:01 +02:00
|
|
|
use FFMpeg\Filters\FilterInterface;
|
2013-06-25 10:03:20 +02:00
|
|
|
use FFMpeg\Format\ProgressableInterface;
|
|
|
|
|
|
|
|
|
|
class Audio extends AbstractStreamableMedia
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritdoc}
|
|
|
|
|
*
|
|
|
|
|
* @return AudioFilters
|
|
|
|
|
*/
|
|
|
|
|
public function filters()
|
|
|
|
|
{
|
|
|
|
|
return new AudioFilters($this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritdoc}
|
|
|
|
|
*
|
|
|
|
|
* @return Audio
|
|
|
|
|
*/
|
2013-06-25 21:43:01 +02:00
|
|
|
public function addFilter(FilterInterface $filter)
|
2013-06-25 10:03:20 +02:00
|
|
|
{
|
2013-06-25 21:43:01 +02:00
|
|
|
if (!$filter instanceof AudioFilterInterface) {
|
|
|
|
|
throw new InvalidArgumentException('Audio only accepts AudioFilterInterface filters');
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-25 10:03:20 +02:00
|
|
|
$this->filters->add($filter);
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2013-06-25 10:40:20 +02:00
|
|
|
* Exports the audio in the desired format, applies registered filters.
|
2013-06-25 10:03:20 +02:00
|
|
|
*
|
2017-11-05 17:35:41 +01:00
|
|
|
* @param FormatInterface $format
|
|
|
|
|
* @param string $outputPathfile
|
2013-06-25 10:03:20 +02:00
|
|
|
* @return Audio
|
|
|
|
|
* @throws RuntimeException
|
|
|
|
|
*/
|
|
|
|
|
public function save(FormatInterface $format, $outputPathfile)
|
|
|
|
|
{
|
|
|
|
|
$listeners = null;
|
|
|
|
|
|
|
|
|
|
if ($format instanceof ProgressableInterface) {
|
2018-02-18 13:57:06 +01:00
|
|
|
$listeners = $format->createProgressListener($this, $this->ffprobe, 1, 1, 0);
|
2013-06-25 10:03:20 +02:00
|
|
|
}
|
|
|
|
|
|
2017-11-05 17:35:41 +01:00
|
|
|
$commands = $this->buildCommand($format, $outputPathfile);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$this->driver->command($commands, false, $listeners);
|
|
|
|
|
} catch (ExecutionFailureException $e) {
|
|
|
|
|
$this->cleanupTemporaryFile($outputPathfile);
|
|
|
|
|
throw new RuntimeException('Encoding failed', $e->getCode(), $e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the final command as a string, useful for debugging purposes.
|
|
|
|
|
*
|
|
|
|
|
* @param FormatInterface $format
|
|
|
|
|
* @param string $outputPathfile
|
|
|
|
|
* @return string
|
|
|
|
|
* @since 0.11.0
|
|
|
|
|
*/
|
2017-11-05 18:45:35 +01:00
|
|
|
public function getFinalCommand(FormatInterface $format, $outputPathfile) {
|
2017-11-05 17:35:41 +01:00
|
|
|
return implode(' ', $this->buildCommand($format, $outputPathfile));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Builds the command which will be executed with the provided format
|
|
|
|
|
*
|
|
|
|
|
* @param FormatInterface $format
|
|
|
|
|
* @param string $outputPathfile
|
|
|
|
|
* @return string[] An array which are the components of the command
|
|
|
|
|
* @since 0.11.0
|
|
|
|
|
*/
|
2017-11-05 18:45:35 +01:00
|
|
|
protected function buildCommand(FormatInterface $format, $outputPathfile) {
|
2013-06-26 00:21:12 +02:00
|
|
|
$commands = array('-y', '-i', $this->pathfile);
|
2013-06-25 10:03:20 +02:00
|
|
|
|
2013-08-05 14:19:12 +02:00
|
|
|
$filters = clone $this->filters;
|
|
|
|
|
$filters->add(new SimpleFilter($format->getExtraParams(), 10));
|
2013-06-25 10:03:20 +02:00
|
|
|
|
|
|
|
|
if ($this->driver->getConfiguration()->has('ffmpeg.threads')) {
|
2013-08-05 14:19:12 +02:00
|
|
|
$filters->add(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads'))));
|
2013-06-25 10:03:20 +02:00
|
|
|
}
|
|
|
|
|
if (null !== $format->getAudioCodec()) {
|
2013-08-05 14:19:12 +02:00
|
|
|
$filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec())));
|
2013-06-26 00:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-05 14:19:12 +02:00
|
|
|
foreach ($filters as $filter) {
|
2013-06-26 00:21:12 +02:00
|
|
|
$commands = array_merge($commands, $filter->apply($this, $format));
|
2013-06-25 10:03:20 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-05 14:19:12 +02:00
|
|
|
if (null !== $format->getAudioKiloBitrate()) {
|
|
|
|
|
$commands[] = '-b:a';
|
|
|
|
|
$commands[] = $format->getAudioKiloBitrate() . 'k';
|
|
|
|
|
}
|
2014-06-25 09:55:00 +02:00
|
|
|
if (null !== $format->getAudioChannels()) {
|
|
|
|
|
$commands[] = '-ac';
|
|
|
|
|
$commands[] = $format->getAudioChannels();
|
|
|
|
|
}
|
2013-06-25 10:03:20 +02:00
|
|
|
$commands[] = $outputPathfile;
|
|
|
|
|
|
2017-11-05 17:35:41 +01:00
|
|
|
return $commands;
|
2013-06-25 10:03:20 +02:00
|
|
|
}
|
2016-11-16 12:55:48 -03:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the waveform of the video.
|
|
|
|
|
*
|
|
|
|
|
* @param integer $width
|
|
|
|
|
* @param integer $height
|
2017-11-05 16:28:24 +02:00
|
|
|
* @param array $colors Array of colors for ffmpeg to use. Color format is #000000 (RGB hex string with #)
|
2016-11-16 12:55:48 -03:00
|
|
|
* @return Waveform
|
|
|
|
|
*/
|
2017-11-08 18:32:56 +02:00
|
|
|
public function waveform($width = 640, $height = 120, $colors = array(Waveform::DEFAULT_COLOR))
|
2016-11-16 12:55:48 -03:00
|
|
|
{
|
2017-11-02 17:28:12 +02:00
|
|
|
return new Waveform($this, $this->driver, $this->ffprobe, $width, $height, $colors);
|
2016-11-16 12:55:48 -03:00
|
|
|
}
|
2013-06-25 10:03:20 +02:00
|
|
|
}
|