php - ffmpeg ubuntu
Cálculo/optimización de velocidad de bits FFMPEG (3)
Escribí el siguiente contenedor para FFMPEG:
function Video($input, $crop = null, $scale = null, $output = null, $extra = null)
{
$input = @new ffmpeg_movie($input);
if ((is_object($input) === true) && ($input->hasVideo() === true))
{
$size = array($input->getFrameWidth(), $input->getFrameHeight());
$crop = array_values(array_filter(explode(''/'', $crop), ''is_numeric''));
$scale = array_values(array_filter(explode(''*'', $scale), ''is_numeric''));
if ((is_callable(''shell_exec'') === true) && (is_executable($ffmpeg = trim(shell_exec(''which ffmpeg''))) === true))
{
if (count($crop) == 2)
{
$crop = array($size[0] / $size[1], $crop[0] / $crop[1]);
if ($crop[0] > $crop[1])
{
$size[0] = round($size[1] * $crop[1]);
}
else if ($crop[0] < $crop[1])
{
$size[1] = round($size[0] / $crop[1]);
}
$crop = array($input->getFrameWidth() - $size[0], $input->getFrameHeight() - $size[1]);
}
else
{
$crop = array(0, 0);
}
if (count($scale) >= 1)
{
if (empty($scale[0]) === true)
{
$scale[0] = round($scale[1] * $size[0] / $size[1] / 2) * 2;
}
else if (empty($scale[1]) === true)
{
$scale[1] = round($scale[0] * $size[1] / $size[0] / 2) * 2;
}
}
else
{
$scale = array(round($size[0] / 2) * 2, round($size[1] / 2) * 2);
}
$result = array();
if (array_product($scale) > 0)
{
$result[] = sprintf(''%s -i %s'', escapeshellcmd($ffmpeg), escapeshellarg($input->getFileName()));
if (array_sum($crop) > 0)
{
if (stripos(shell_exec(escapeshellcmd($ffmpeg) . '' -h | grep crop''), ''removed'') !== false)
{
$result[] = sprintf(''-vf "crop=in_w-2*%u:in_h-2*%u"'', round($crop[0] / 4) * 2, round($crop[1] / 4) * 2);
}
else if ($crop[0] > 0)
{
$result[] = sprintf(''-cropleft %u -cropright %u'', round($crop[0] / 4) * 2, round($crop[0] / 4) * 2);
}
else if ($crop[1] > 0)
{
$result[] = sprintf(''-croptop %u -cropbottom %u'', round($crop[1] / 4) * 2, round($crop[1] / 4) * 2);
}
}
if ($input->hasAudio() === true)
{
$result[] = sprintf(''-ab %u -ar %u'', $input->getAudioBitRate(), $input->getAudioSampleRate());
}
$result[] = sprintf(''-b %u -r %u -s %s'', $input->getBitRate(), min(25, $input->getFrameRate()), implode(''x'', $scale));
if (strlen($format = strtolower(ltrim(strrchr($output, ''.''), ''.''))) > 0)
{
$result[] = sprintf(''-f %s %s -y %s'', $format, escapeshellcmd($extra), escapeshellarg($output . ''.ffmpeg''));
if ((strncmp(''flv'', $format, 3) === 0) && (is_executable($flvtool2 = trim(shell_exec(''which flvtool2''))) === true))
{
$result[] = sprintf(''&& %s -U %s %s'', escapeshellcmd($flvtool2), escapeshellarg($output . ''.ffmpeg''), escapeshellarg($output . ''.ffmpeg''));
}
$result[] = sprintf(''&& mv -u %s %s'', escapeshellarg($output . ''.ffmpeg''), escapeshellarg($output));
if ((is_writable(dirname($output)) === true) && (is_resource($stream = popen(''('' . implode('' '', $result) . '') 2>&1 &'', ''r'')) === true))
{
while (($buffer = fgets($stream)) !== false)
{
if (strpos($buffer, ''to stop encoding'') !== false)
{
return (is_int(pclose($stream)) === true) ? true : false;
}
}
if (is_file($output . ''.ffmpeg'') === true)
{
unlink($output . ''.ffmpeg'');
}
pclose($stream);
}
}
}
}
}
return false;
}
Como puede ver, estoy usando la entrada de audio y video en mi salida, incluso si el video de entrada es recortado o redimensionado, lo que parece bastante ineficiente en términos de espacio en HD.
Sé muy poco acerca de estos asuntos pero, desde mi punto de vista, los bitrates están directamente relacionados con la duración, calidad y resolución de los medios, ¿no? Si es así, ¿cómo puedo usar esos valores para determinar una tasa de bits de audio y video adecuada para mantener la calidad de entrada y reducir el tamaño del archivo?
¡Gracias por adelantado!
Desea buscar la Shannon-Entropy -log (P) / log (2). Estos son los bits mínimos en los que se puede pensar cualquier información. Pero no estoy seguro de si es útil para ti.
En general, no debe especificar una tasa de bits en absoluto. Solo es útil para la transmisión, en cuyo caso debe respetar VBV también (que especifica una tasa de bits máxima a lo largo del tiempo, así como la tasa de bits promedio).
Usa x264 crf 23, su modo predeterminado de calidad constante, y sé feliz. En el caso de ffmpeg, esto es algo así como:
ffmpeg -i <file> -vcodec libx264 -vpre slower -acodec copy <outfile>
En cuanto al audio, lo mejor es copiarlo directamente si la entrada fue comprimida. Esto no es posible en algunas situaciones, como si la entrada fuera vorbis y el resultado fuera un archivo .flv. En ese caso, me quedaría con lo que sea el predeterminado del codificador de audio seleccionado.
Terminé usando el indicador -sameq
, leí en alguna parte que esto no se traduce a la misma calidad, pero por ahora esto es mejor que forzar la tasa de bits original.
De todos modos, me he encontrado con este script de Bash que sugiere que mi pensamiento es correcto, todavía no sé cómo calcular la velocidad de bits de salida sin tener el tamaño de salida como una restricción. ¡Si alguien sabe, por favor comparta!