Listeners

This commit is contained in:
Dan Jones 2022-09-05 21:17:44 -05:00
commit 18c3cbb284
3 changed files with 47 additions and 60 deletions

2
.gitignore vendored
View file

@ -12,3 +12,5 @@ vendor
.php-cs-fixer.cache .php-cs-fixer.cache
*.mkv *.mkv
tags
*.mp3

View file

@ -2,6 +2,9 @@
namespace Danjones\FFMpeg; namespace Danjones\FFMpeg;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\ProgressListener\AbstractProgressListener;
class Map class Map
{ {
use Traits\HasMetadata; use Traits\HasMetadata;
@ -10,6 +13,8 @@ class Map
protected string $path; protected string $path;
/** @var Stream[] */ /** @var Stream[] */
protected array $streams = []; protected array $streams = [];
/** @var AbstractProgressListener[] */
protected array $listeners = [];
public function __construct(MappableMedia $media) public function __construct(MappableMedia $media)
{ {
@ -46,10 +51,24 @@ class Map
public function saveStream(Stream $stream): static public function saveStream(Stream $stream): static
{ {
$this->streams[] = $stream; $this->streams[] = $stream;
$format = $stream->getCodec();
if ($format instanceof ProgressableInterface) {
$listener = $format->createProgressListener(
$this->media,
$this->media->getFFProbe(),
1, 1, 0
);
$this->listeners = array_merge($this->listeners, $listener);
}
return $this; return $this;
} }
public function getListeners(): array
{
return $this->listeners;
}
public function buildCommand(): array public function buildCommand(): array
{ {
$commands = []; $commands = [];

View file

@ -3,6 +3,8 @@
namespace Danjones\FFMpeg; namespace Danjones\FFMpeg;
use Alchemy\BinaryDriver\Exception\ExecutionFailureException; use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use Evenement\EventEmitterInterface;
use Evenement\EventEmitterTrait;
use FFMpeg\Driver\FFMpegDriver; use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\Exception\RuntimeException; use FFMpeg\Exception\RuntimeException;
use FFMpeg\FFMpeg; use FFMpeg\FFMpeg;
@ -14,20 +16,23 @@ use FFMpeg\Filters\AdvancedMedia\ComplexFilters;
use FFMpeg\Filters\FiltersCollection; use FFMpeg\Filters\FiltersCollection;
use FFMpeg\Format\AudioInterface; use FFMpeg\Format\AudioInterface;
use FFMpeg\Format\FormatInterface; use FFMpeg\Format\FormatInterface;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\ProgressListener\AbstractProgressListener; use FFMpeg\Format\ProgressListener\AbstractProgressListener;
use FFMpeg\Format\ProgressListener\VideoProgressListener;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\VideoInterface; use FFMpeg\Format\VideoInterface;
use FFMpeg\Media\AbstractMediaType; use FFMpeg\Media\AbstractMediaType;
/** /**
* AdvancedMedia may have multiple inputs and multiple outputs. * MappableMedia may have multiple inputs and multiple outputs.
* This class accepts only filters for -filter_complex option. * This class does not accept filters.
* But you can set initial and additional parameters of the ffmpeg command. * But you can set initial and additional parameters of the ffmpeg command.
* *
* @see http://trac.ffmpeg.org/wiki/Creating%20multiple%20outputs * @see http://trac.ffmpeg.org/wiki/Creating%20multiple%20outputs
*/ */
class MappableMedia extends AbstractMediaType class MappableMedia extends AbstractMediaType implements EventEmitterInterface
{ {
use EventEmitterTrait;
/** /**
* @var string[] * @var string[]
*/ */
@ -46,10 +51,8 @@ class MappableMedia extends AbstractMediaType
*/ */
protected array $additionalParameters = []; protected array $additionalParameters = [];
/** /** @var AbstractProgressListener[] */
* @var AbstractProgressListener[] protected array $progressListeners = [];
*/
protected array $listeners = [];
public function __construct(FFMpegDriver $driver, FFProbe $ffprobe) public function __construct(FFMpegDriver $driver, FFProbe $ffprobe)
{ {
@ -152,72 +155,35 @@ class MappableMedia extends AbstractMediaType
public function saveMap(Map $map): static public function saveMap(Map $map): static
{ {
$this->maps[] = $map; $this->maps[] = $map;
$this->progressListeners = array_merge($this->progressListeners, $map->getListeners());
return $this; return $this;
} }
/**
* Select the streams for output.
*
* @param string[] $outs output labels of the -filter_complex part
* @param FormatInterface $format format of the output file
* @param string $outputFilename output filename
* @param bool $forceDisableAudio
* @param bool $forceDisableVideo
*
* @return $this
* @todo Redo all of this.
* @see https://ffmpeg.org/ffmpeg.html#Manual-stream-selection
*/
private function map2(
array $outs,
FormatInterface $format,
$outputFilename,
$forceDisableAudio = false,
$forceDisableVideo = false
) {
$commands = [];
foreach ($outs as $label) {
$commands[] = '-map';
$commands[] = $label;
}
// Apply format params.
$commands = array_merge(
$commands,
$this->applyFormatParams($format, $forceDisableAudio, $forceDisableVideo)
);
// Set output file.
$commands[] = $outputFilename;
// Create a listener.
if ($format instanceof ProgressableInterface) {
$listener = $format->createProgressListener($this, $this->ffprobe, 1, 1, 0);
$this->listeners = array_merge($this->listeners, $listener);
}
$this->mapCommands = array_merge($this->mapCommands, $commands);
return $this;
}
/**
* Apply added filters and execute ffmpeg command.
*
* @throws RuntimeException
*/
public function save(): void public function save(): void
{ {
$command = $this->buildCommand(); $command = $this->buildCommand();
$this->addListener();
try { try {
$this->driver->command($command, false, $this->listeners); $this->driver->command($command, false, $this->progressListeners);
} catch (ExecutionFailureException $e) { } catch (ExecutionFailureException $e) {
throw new RuntimeException('Encoding failed', $e->getCode(), $e); throw new RuntimeException('Encoding failed', $e->getCode(), $e);
} }
} }
protected function addListener(): void
{
$self = $this;
$listener = new VideoProgressListener($this->ffprobe, $this->getPathfile(), 1, 1, 0);
$listener->on('progress', function (...$args) use ($self) {
$self->emit('progress', array_merge([$self, null], $args));
});
$this->progressListeners[] = $listener;
}
/** /**
* @param bool $forceDisableAudio * @param bool $forceDisableAudio
* @param bool $forceDisableVideo * @param bool $forceDisableVideo