ffmpeg-mappable-media/src/Stream.php
2022-08-29 10:02:04 -05:00

200 lines
4.4 KiB
PHP

<?php
namespace Danjones\FFMpeg;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Format\FormatInterface;
use FFMpeg\Format\ProgressListener\AbstractProgressListener;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\VideoInterface;
class Stream
{
use Traits\HasMetadata;
protected Map $map;
protected FormatInterface $codec;
protected string $input = '0:0';
protected array $flags = [];
public function __construct(Map $map)
{
$this->map = $map;
}
public function setInput(string $input): static
{
$this->input = $input;
return $this;
}
public function addFlag(string $key, string $value): static
{
$this->flags[$key] = $value;
return $this;
}
public function setCodec(FormatInterface $codec): static
{
$this->codec = $codec;
return $this;
}
public function video(string $codec, callable $callback = null): static
{
$this->setCodec(new Format\DefaultVideo($codec));
if ($callback) {
return $this->editCodec($callback);
}
return $this;
}
public function audio(string $codec, callable $callback = null): static
{
$this->setCodec(new Format\DefaultAudio($codec));
if ($callback) {
return $this->editCodec($callback);
}
return $this;
}
public function subtitle(string $codec, callable $callback = null): static
{
$this->setCodec(new Format\DefaultSubtitle($codec));
if ($callback) {
return $this->editCodec($callback);
}
return $this;
}
public function copy(): static
{
return $this->setCodec(new Format\Copy());
}
public function getCodec(): FormatInterface
{
return $this->codec;
}
public function editCodec(callable $callback): static
{
$callback($this->codec);
return $this;
}
protected function parseCodec(): static
{
if ($this->codec instanceof VideoInterface) {
$this->parseVideo();
} elseif ($this->codec instanceof AudioInterface) {
$this->parseAudio();
} elseif ($this->codec instanceof Format\SubtitleInterface) {
$this->parseSubtitle();
} elseif ($this->codec instanceof Format\Copy) {
$this->addFlag('c', 'copy');
}
$this->parseExtras($this->codec->getExtraParams());
return $this;
}
protected function parseSubtitle(): static
{
if (null !== ($codec = $this->codec->getSubtitleCodec())) {
$this->addFlag('c', $codec);
}
return $this;
}
protected function parseAudio(): static
{
if (null !== ($codec = $this->codec->getAudioCodec())) {
$this->addFlag('c', $codec);
}
if (null !== ($kb = $this->codec->getAudioKiloBitrate())) {
$this->addFlag('b', "{$kb}k");
}
if (null !== ($channels = $this->codec->getAudioChannels())) {
$this->addFlag('ac', $channels);
}
return $this;
}
protected function parseVideo(): static
{
if (null !== ($codec = $this->codec->getVideoCodec())) {
$this->addFlag('c', $codec);
}
if (0 !== ($kb = $this->codec->getKiloBitrate())) {
$this->addFlag('b', "{$kb}k");
}
$this->parseExtras($this->codec->getAdditionalParameters());
return $this;
}
protected function parseExtras (?array $params): void
{
if (is_null($params)) {
return;
}
reset($params);
while(null !== key($params)) {
$key = current($params);
$value = next($params);
if (null == key($params)) {
continue;
}
$this->addFlag(ltrim($key, '-k'), $value);
}
}
public function saveStream(): Map
{
$this->map->saveStream($this);
return $this->map;
}
public function buildCommand(int $idx = 0): array
{
$this->parseCodec();
$commands = [];
$commands[] = '-map';
$commands[] = $this->input;
foreach ($this->flags as $k => $v) {
array_push($commands, "-{$k}:{$idx}", $v);
}
foreach ($this->metadata as $k => $v) {
array_push($commands, "-metadata:s:{$idx}", "{$k}={$v}");
}
return $commands;
}
}