Skip to content

Commit

Permalink
Add support for CBR, VBV and CRF video encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
javer committed Nov 13, 2018
1 parent eef6abb commit a459c49
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 12 deletions.
140 changes: 140 additions & 0 deletions src/Profile/VideoProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class VideoProfile
const PRESET = 'preset';
const PIXEL_FORMAT = 'pixel_format';
const BITRATE = 'bitrate';
const MAX_BITRATE = 'max_bitrate';
const MIN_BITRATE = 'min_bitrate';
const BUFFER_SIZE = 'buffer_size';
const CRF = 'crf';
const FRAME_RATE = 'frame_rate';
const KEYFRAME_INTERVAL = 'keyframe_interval';
const ROTATE = 'rotate';
Expand Down Expand Up @@ -57,6 +61,26 @@ class VideoProfile
*/
private $bitrate;

/**
* @var integer|null
*/
private $maxBitrate;

/**
* @var integer|null
*/
private $minBitrate;

/**
* @var integer|null
*/
private $bufferSize;

/**
* @var integer|null
*/
private $crf;

/**
* @var float|null
*/
Expand Down Expand Up @@ -113,6 +137,22 @@ public static function fromArray(array $values): VideoProfile
$profile->setBitrate($value);
break;

case static::MAX_BITRATE:
$profile->setMaxBitrate($value);
break;

case static::MIN_BITRATE:
$profile->setMinBitrate($value);
break;

case static::BUFFER_SIZE:
$profile->setBufferSize($value);
break;

case static::CRF:
$profile->setCrf($value);
break;

case static::FRAME_RATE:
$profile->setFrameRate($value);
break;
Expand Down Expand Up @@ -145,6 +185,10 @@ public function toArray(): array
static::PRESET => $this->getPreset(),
static::PIXEL_FORMAT => $this->getPixelFormat(),
static::BITRATE => $this->getBitrate(),
static::MAX_BITRATE => $this->getMaxBitrate(),
static::MIN_BITRATE => $this->getMinBitrate(),
static::BUFFER_SIZE => $this->getBufferSize(),
static::CRF => $this->getCrf(),
static::FRAME_RATE => $this->getFrameRate(),
static::KEYFRAME_INTERVAL => $this->getKeyframeInterval(),
static::ROTATE => $this->getRotate(),
Expand Down Expand Up @@ -429,6 +473,102 @@ public function setBitrate($bitrate = null): VideoProfile
return $this;
}

/**
* Returns max bitrate.
*
* @return integer|null
*/
public function getMaxBitrate(): ?int
{
return $this->maxBitrate;
}

/**
* Set max bitrate.
*
* @param integer|string|null $maxBitrate
*
* @return VideoProfile
*/
public function setMaxBitrate($maxBitrate = null): VideoProfile
{
$this->maxBitrate = MediaProfile::convertMetricValue($maxBitrate);

return $this;
}

/**
* Returns min bitrate.
*
* @return integer|null
*/
public function getMinBitrate(): ?int
{
return $this->minBitrate;
}

/**
* Set min bitrate.
*
* @param integer|string|null $minBitrate
*
* @return VideoProfile
*/
public function setMinBitrate($minBitrate = null): VideoProfile
{
$this->minBitrate = MediaProfile::convertMetricValue($minBitrate);

return $this;
}

/**
* Returns buffer size.
*
* @return integer|null
*/
public function getBufferSize(): ?int
{
return $this->bufferSize;
}

/**
* Set buffer size.
*
* @param integer|string|null $bufferSize
*
* @return VideoProfile
*/
public function setBufferSize($bufferSize = null): VideoProfile
{
$this->bufferSize = MediaProfile::convertMetricValue($bufferSize);

return $this;
}

/**
* Returns crf.
*
* @return integer|null
*/
public function getCrf(): ?int
{
return $this->crf;
}

/**
* Set crf.
*
* @param integer|null $crf
*
* @return VideoProfile
*/
public function setCrf(int $crf = null): VideoProfile
{
$this->crf = $crf;

return $this;
}

/**
* Returns frame rate.
*
Expand Down
48 changes: 48 additions & 0 deletions src/Stream/VideoStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,54 @@ public function bitrate(string $bitrate): VideoStreamInterface
return $this->addStreamOption('-b', $bitrate);
}

/**
* Set max bitrate.
*
* @param string $maxBitrate
*
* @return VideoStreamInterface
*/
public function maxBitrate(string $maxBitrate): VideoStreamInterface
{
return $this->addStreamOption('-maxrate', $maxBitrate);
}

/**
* Set min bitrate.
*
* @param string $minBitrate
*
* @return VideoStreamInterface
*/
public function minBitrate(string $minBitrate): VideoStreamInterface
{
return $this->addStreamOption('-minrate', $minBitrate);
}

/**
* Set buffer size.
*
* @param string $bufferSize
*
* @return VideoStreamInterface
*/
public function bufferSize(string $bufferSize): VideoStreamInterface
{
return $this->addStreamOption('-bufsize', $bufferSize);
}

/**
* Set crf.
*
* @param integer $crf
*
* @return VideoStreamInterface
*/
public function crf(int $crf): VideoStreamInterface
{
return $this->addStreamOption('-crf', $crf);
}

/**
* Set pixel format.
*
Expand Down
44 changes: 44 additions & 0 deletions src/Stream/VideoStreamInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,50 @@ public function filter(string $filterGraph): VideoStreamInterface;
*/
public function bitrate(string $bitrate): VideoStreamInterface;

/**
* Set maxBitrate.
*
* Option: -maxrate:v maxBitrate
*
* @param string $maxBitrate
*
* @return VideoStreamInterface
*/
public function maxBitrate(string $maxBitrate): VideoStreamInterface;

/**
* Set minBitrate.
*
* Option: -minrate:v minBitrate
*
* @param string $minBitrate
*
* @return VideoStreamInterface
*/
public function minBitrate(string $minBitrate): VideoStreamInterface;

/**
* Set buffer size.
*
* Option: -bufsize:v bufferSize
*
* @param string $bufferSize
*
* @return VideoStreamInterface
*/
public function bufferSize(string $bufferSize): VideoStreamInterface;

/**
* Set crf.
*
* Option: -crf:v bitrate
*
* @param integer $crf
*
* @return VideoStreamInterface
*/
public function crf(int $crf): VideoStreamInterface;

/**
* Set pixel format.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Transformer/CommandTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CommandTransformer
*/
protected const CODEC_MAP = [
'h264' => 'libx264',
'h265' => 'libx265',
];

/**
Expand Down Expand Up @@ -141,6 +142,22 @@ public function applyVideoTransformation(VideoStreamInterface $videoStream, Vide
$videoStream->bitrate($bitrate);
}

if (!is_null($maxBitrate = $videoProfile->getMaxBitrate())) {
$videoStream->maxBitrate($maxBitrate);
}

if (!is_null($minBitrate = $videoProfile->getMinBitrate())) {
$videoStream->minBitrate($minBitrate);
}

if (!is_null($bufferSize = $videoProfile->getBufferSize())) {
$videoStream->bufferSize($bufferSize);
}

if (!is_null($crf = $videoProfile->getCrf())) {
$videoStream->crf($crf);
}

if (!is_null($frameRate = $videoProfile->getFrameRate())) {
$videoStream->frameRate($frameRate);
}
Expand Down
37 changes: 25 additions & 12 deletions src/Transformer/ProfileTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,30 +90,43 @@ public function transformVideo(VideoProfile $source, VideoProfile $target, bool
}
}

$sourceCodec = $source->getCodec();
$sourcePixelFormat = $source->getPixelFormat();
$sourceRotate = $source->getRotate();
$sourceBitrate = $source->getBitrate();
$sourceFrameRate = $source->getFrameRate();

$targetWidth = $this->alignNumber($targetWidth, $sizeAlign);
$targetHeight = $this->alignNumber($targetHeight, $sizeAlign);

$targetCodec = $target->getCodec() ?? $source->getCodec();
$targetCodec = $target->getCodec() ?? $sourceCodec;

$targetPixelFormat = $target->getPixelFormat() ?? $sourcePixelFormat;

$targetPixelFormat = $target->getPixelFormat() ?? $source->getPixelFormat();
$targetBitrate = $this->getLeastValue($sourceBitrate, $target->getBitrate());

$targetBitrate = $this->getLeastValue($source->getBitrate(), $target->getBitrate());
$targetMaxrate = $this->getLeastValue($sourceBitrate, $target->getMaxBitrate());

$targetFramerate = $this->getLeastValue($source->getFrameRate(), $target->getFrameRate());
$targetFramerate = $this->getLeastValue($sourceFrameRate, $target->getFrameRate());

if ($force
|| $source->getCodec() !== $targetCodec
|| $source->getPixelFormat() !== $targetPixelFormat
|| $source->getRotate() != 0
|| $source->getWidth() > $targetWidth
|| $source->getHeight() > $targetHeight
|| $source->getBitrate() > $targetBitrate
|| $source->getFrameRate() > $targetFramerate) {
|| $sourceCodec !== $targetCodec
|| $sourcePixelFormat !== $targetPixelFormat
|| $sourceRotate != 0
|| $sourceWidth > $targetWidth
|| $sourceHeight > $targetHeight
|| $sourceBitrate > $targetBitrate
|| $sourceBitrate > $targetMaxrate
|| $sourceFrameRate > $targetFramerate) {
$transform->setCodec($targetCodec);
$transform->setProfile($target->getProfile());
$transform->setPreset($this->getVideoCodecPreset($targetCodec, $target->getPreset(), $targetFramerate));
$transform->setPixelFormat($target->getPixelFormat());
$transform->setBitrate($targetBitrate);
$transform->setBitrate($target->getBitrate() ? $targetBitrate : null);
$transform->setMaxBitrate($target->getMaxBitrate());
$transform->setMinBitrate($target->getMinBitrate());
$transform->setBufferSize($target->getBufferSize());
$transform->setCrf($target->getCrf());
$transform->setFrameRate($targetFramerate);
$transform->setKeyframeInterval($target->getKeyframeInterval());

Expand Down

0 comments on commit a459c49

Please sign in to comment.