Skip to content

Instantly share code, notes, and snippets.

@d4rkne55
Last active July 15, 2020 18:26
Show Gist options
  • Save d4rkne55/91843ee8ffc070ed7f1c7bf6b2bd3974 to your computer and use it in GitHub Desktop.
Save d4rkne55/91843ee8ffc070ed7f1c7bf6b2bd3974 to your computer and use it in GitHub Desktop.
Class with some calculations and informations for media files
<?php
class Media
{
public $calcBase = 1024;
public $fileSize = 0;
public $sizePrefixes = array(
1000 => array(
'',
'K',
'M',
'G',
'T'
),
1024 => array(
'',
'Ki',
'Mi',
'Gi',
'Ti'
)
);
public function getFileSize($precision = 2) {
$size = $this->fileSize;
$base = $this->calcBase;
for ($i = 0; $size >= $base; $i++) {
$size /= $base;
}
$size = round($size, $precision);
$sizeStr = "$size " . $this->sizePrefixes[$base][$i] . 'B';
return $sizeStr;
}
public static function parseFileSize($sizeStr) {
$prefixMulti = array(
'k' => 2**10,
'm' => 2**20,
'g' => 2**30,
't' => 2**40
);
preg_match('/[a-z]/i', $sizeStr, $prefix);
$prefix = !empty($prefix) ? lcfirst($prefix[0]) : '';
$sizeFloat = (float) strtr($sizeStr, ',', '.');
if (array_key_exists($prefix, $prefixMulti)) {
$sizeFloat *= $prefixMulti[$prefix];
}
return ceil($sizeFloat);
}
public static function parseTime($timeStr) {
$times = explode(':', $timeStr);
$seconds = 0;
foreach (array_reverse($times) as $i => $time) {
$seconds += $time * 60**$i;
}
return $seconds;
}
}
class Image extends Media
{
public $width;
public $height;
public $pixelDepth;
public function __construct($width, $height, $pixelDepth = 24) {
$this->width = (int) $width;
$this->height = (int) $height;
$this->pixelDepth = $pixelDepth;
$this->calcFileSize();
}
protected function calcFileSize() {
$this->fileSize = $this->width * $this->height * $this->pixelDepth / 8;
}
}
class Audio extends Media
{
public $length;
public $bitrate;
public $channels;
public $samplingRate;
public $bitDepth;
public function __construct($length, $bitrateKbps = 0, $channels = 2, $samplingRate = 44100, $bitDepth = 16) {
$this->length = parent::parseTime($length);
$this->bitrate = $bitrateKbps * 1000;
$this->channels = $channels;
$this->samplingRate = $samplingRate;
$this->bitDepth = $bitDepth;
if (is_string($channels)) {
$this->channels = (int) array_sum(explode('.', $channels));
}
// calculate uncompressed bitrate when not given
if ($bitrateKbps == 0) {
$this->bitrate = $this->samplingRate * $this->bitDepth * $this->channels;
}
$this->calcFileSize();
}
public function setBitrate($bitrateKbps) {
$this->bitrate = $bitrateKbps * 1000;
}
public function getBitrate() {
return $this->bitrate / 1000;
}
protected function calcFileSize() {
$this->fileSize = $this->length * $this->bitrate / 8;
}
}
class Video extends Media
{
public $length;
public $bitrate;
public $framerate;
public $width;
public $height;
public function __construct($length, $bitrateKbps, $width = null, $height = null, $framerate = 23.976) {
$this->length = parent::parseTime($length);
$this->bitrate = $bitrateKbps * 1000;
$this->framerate = $framerate;
$this->width = (int) $width;
$this->height = (int) $height;
$this->calcFileSize();
}
public function setBitrate($bitrateKbps) {
$this->bitrate = $bitrateKbps * 1000;
}
public function getBitrate() {
return $this->bitrate / 1000;
}
public function getQualityFactor() {
$qf = $this->bitrate / ($this->width * $this->height * $this->framerate);
return sprintf('%.3f', $qf);
}
public function calcBitrateForQf($qualityFactor) {
$bitrate = $qualityFactor * $this->width * $this->height * $this->framerate;
return round($bitrate / 1000);
}
public function calcBitrateForSize($fileSize) {
if (is_string($fileSize)) {
$fileSize = parent::parseFileSize($fileSize);
}
$bitrate = $fileSize / $this->length * 8;
return round($bitrate / 1000);
}
public function getAspectRatio() {
return round($this->width / $this->height, 2);
}
public static function calcMaxRefs($width, $height, $profileLevel) {
$maxDPB = array(
'1' => 396,
'1.1' => 900,
'1.2' => 2376,
'1.3' => 2376,
'2' => 2376,
'2.1' => 4752,
'2.2' => 8100,
'3' => 8100,
'3.1' => 18000,
'3.2' => 20480,
'4' => 32768,
'4.1' => 32768,
'4.2' => 34816,
'5' => 110400,
'5.1' => 184320,
'5.2' => 184320
);
if (!array_key_exists($profileLevel, $maxDPB)) {
throw new InvalidArgumentException("Given profile level doesn't exist!");
}
$maxDPB = $maxDPB[$profileLevel];
// macroblock counts
$horMbs = ($width + ($width % 16)) / 16;
$vertMbs = ($height + ($height % 16)) / 16;
$maxRefs = (int) floor($maxDPB / ($horMbs * $vertMbs));
return min($maxRefs, 16);
}
protected function calcFileSize() {
$this->fileSize = $this->length * $this->bitrate / 8;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment