retooling a bit
* allow setting vcodec * remove the min/max bitrate caps * allow a non-square-output with --stretch * cleanup bitrate setup * don't force audio channels * allow setting audio sample rate * don't force preset
This commit is contained in:
parent
0533b141a2
commit
96f4cf2f72
1 changed files with 106 additions and 120 deletions
226
pack-vid
226
pack-vid
|
|
@ -21,10 +21,11 @@ $options = [
|
|||
'letterbox' => false,
|
||||
'no-audio' => false,
|
||||
'audio-bitrate' => 96000,
|
||||
'audio-channels' => 2,
|
||||
'audio-rate' => false,
|
||||
'audio-channels' => false,
|
||||
'exposure' => '0', // stops
|
||||
'peak' => '1000', // '10000' is max
|
||||
'preset' => 'medium',
|
||||
'preset' => false,
|
||||
'fps' => '60',
|
||||
'size' => $maxBytes,
|
||||
'quality' => 1.0,
|
||||
|
|
@ -41,6 +42,8 @@ $options = [
|
|||
'crop-top' => false,
|
||||
'tonemap' => 'hable',
|
||||
'color-temperature' => false,
|
||||
'vcodec' => 'libx264',
|
||||
'stretch' => false,
|
||||
];
|
||||
|
||||
while ( count( $args ) > 0 && substr( $args[0], 0, 2 ) == '--' ) {
|
||||
|
|
@ -153,8 +156,6 @@ function extractTracks( $streams, $type ) {
|
|||
}
|
||||
|
||||
function convert( $src, $dest, $options ) {
|
||||
$maxBits = 8 * sizify( $options['size'] );
|
||||
|
||||
$probe = ffprobe( $src );
|
||||
|
||||
$videoTracks = extractTracks( $probe->streams, 'video' );
|
||||
|
|
@ -198,9 +199,14 @@ function convert( $src, $dest, $options ) {
|
|||
$keyframeInt = intval( ceil( $duration * 60 ) );
|
||||
}
|
||||
|
||||
$bitrate = floor( $maxBits / $duration );
|
||||
if ( $options['bitrate'] ) {
|
||||
$bitrate = sizify( $options['bitrate'] );
|
||||
} else if ( $options[ 'size' ] ) {
|
||||
$maxBits = 8 * sizify( $options['size'] );
|
||||
$bitrate = floor( $maxBits / $duration );
|
||||
} else {
|
||||
// Calculate a target bitrate from the size later
|
||||
$bitrate = null;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -208,127 +214,93 @@ function convert( $src, $dest, $options ) {
|
|||
$audio = [ '-an' ];
|
||||
} else {
|
||||
$audioBitrate = $options[ 'audio-bitrate' ];
|
||||
$audioChannels = $options[ 'audio-channels' ];
|
||||
$audio = [
|
||||
'-ac', $audioChannels,
|
||||
'-b:a', $audioBitrate,
|
||||
];
|
||||
if ( $options['audio-channels'] ) {
|
||||
$audio[] = '-ac';
|
||||
$audio[] = $options[ 'audio-channels' ];
|
||||
}
|
||||
if ( $options[ 'audio-rate' ] ) {
|
||||
$audio[] = '-ar';
|
||||
$audio[] = $options[ 'audio-rate' ];
|
||||
}
|
||||
$bitrate -= $audioBitrate;
|
||||
}
|
||||
|
||||
$bitrate = max( $bitrate, 16000 );
|
||||
$mbits = 1000 * 1000;
|
||||
$base = intval( $mbits * floatval( $options['quality'] ) );
|
||||
if ( $bitrate < 0.125 * $base || $height < 144 ) {
|
||||
$frameWidth = 256;
|
||||
$frameHeight = 144;
|
||||
$bitrate = min( $bitrate, $base * 0.25 );
|
||||
} elseif ( $bitrate < 0.25 * $base || $height < 180 ) {
|
||||
$frameWidth = 320;
|
||||
$frameHeight = 180;
|
||||
$bitrate = min( $bitrate, $base * 0.5 );
|
||||
} elseif ( $bitrate < 0.5 * $base || $height < 288 ) {
|
||||
$frameWidth = 512;
|
||||
$frameHeight = 288;
|
||||
$bitrate = min( $bitrate, $base * 0.5 );
|
||||
} elseif ( $bitrate < 1 * $base || $height < 480 ) {
|
||||
$frameWidth = 640;
|
||||
$frameHeight = 360;
|
||||
$bitrate = min( $bitrate, $base );
|
||||
} elseif ( $bitrate < 2 * $base || $height < 540) {
|
||||
$frameWidth = 854;
|
||||
$frameHeight = 480;
|
||||
$bitrate = min( $bitrate, $base * 2 );
|
||||
} elseif ( $bitrate < 2.5 * $base || $height < 720) {
|
||||
$frameWidth = 960;
|
||||
$frameHeight = 540;
|
||||
$bitrate = min( $bitrate, $base * 2.5 );
|
||||
} elseif ( $bitrate < 4 * $base || $height < 1080) {
|
||||
$frameWidth = 1280;
|
||||
$frameHeight = 720;
|
||||
$bitrate = min( $bitrate, $base * 4 );
|
||||
} elseif ( $bitrate < 8 * $base || $height < 1440) {
|
||||
$frameWidth = 1920;
|
||||
$frameHeight = 1080;
|
||||
$bitrate = min( $bitrate, $base * 8 );
|
||||
} elseif ( $bitrate < 16 * $base || $height < 2160) {
|
||||
$frameWidth = 2560;
|
||||
$frameHeight = 1440;
|
||||
$bitrate = min( $bitrate, $base * 16 );
|
||||
if ( $options[ 'width' ] && $options[ 'height' ] ) {
|
||||
// Use exact given dimensions.
|
||||
$frameWidth = intval( $options[ 'width' ] );
|
||||
$frameHeight = intval( $options[ 'height' ] );
|
||||
} else {
|
||||
$frameWidth = 3840;
|
||||
$frameHeight = 2160;
|
||||
$bitrate = min( $bitrate, $base * 32 );
|
||||
// Select target resolution from the target bitrate...
|
||||
if ( !$bitrate ) {
|
||||
// If we didn't get given one, default to 5Mbits 1080HD
|
||||
$bitrate = 5000000;
|
||||
}
|
||||
$mbits = 1000 * 1000;
|
||||
$base = intval( $mbits * floatval( $options['quality'] ) );
|
||||
if ( $bitrate < 0.125 * $base || $height < 144 ) {
|
||||
$frameWidth = 256;
|
||||
$frameHeight = 144;
|
||||
} elseif ( $bitrate < 0.25 * $base || $height < 180 ) {
|
||||
$frameWidth = 320;
|
||||
$frameHeight = 180;
|
||||
} elseif ( $bitrate < 0.5 * $base || $height < 288 ) {
|
||||
$frameWidth = 512;
|
||||
$frameHeight = 288;
|
||||
} elseif ( $bitrate < 1 * $base || $height < 480 ) {
|
||||
$frameWidth = 640;
|
||||
$frameHeight = 360;
|
||||
} elseif ( $bitrate < 2 * $base || $height < 540) {
|
||||
$frameWidth = 854;
|
||||
$frameHeight = 480;
|
||||
} elseif ( $bitrate < 2.5 * $base || $height < 720) {
|
||||
$frameWidth = 960;
|
||||
$frameHeight = 540;
|
||||
} elseif ( $bitrate < 4 * $base || $height < 1080) {
|
||||
$frameWidth = 1280;
|
||||
$frameHeight = 720;
|
||||
} elseif ( $bitrate < 8 * $base || $height < 1440) {
|
||||
$frameWidth = 1920;
|
||||
$frameHeight = 1080;
|
||||
} elseif ( $bitrate < 16 * $base || $height < 2160) {
|
||||
$frameWidth = 2560;
|
||||
$frameHeight = 1440;
|
||||
} else {
|
||||
$frameWidth = 3840;
|
||||
$frameHeight = 2160;
|
||||
}
|
||||
}
|
||||
|
||||
$aspect = $width / $height;
|
||||
$pixels = $width * $height;
|
||||
|
||||
// canonical min rate is 0.125 megabit at 144p
|
||||
$bitrate = max( $bitrate, 0.125 * $base );
|
||||
|
||||
/*
|
||||
$minWidth = 640;
|
||||
$minHeight = 360;
|
||||
|
||||
$baseWidth = 854;
|
||||
$baseHeight = 480;
|
||||
$pixelsPerBit = ( $baseWidth * $baseHeight ) / $base;
|
||||
|
||||
$maxWidth = 1920;
|
||||
$maxHeight = 1080;
|
||||
$maxrate = $base * ( $maxWidth * $maxHeight ) / ( $baseWidth * $baseHeight );
|
||||
|
||||
$pixels = $bitrate * $pixelsPerBit;
|
||||
$frameHeight = evenize( sqrt( $pixels / $aspect ) );
|
||||
$frameWidth = evenize( $frameHeight * $aspect );
|
||||
|
||||
if ( $aspect > 16 / 9 ) {
|
||||
if ( $frameWidth < $minWidth ) {
|
||||
$frameWidth = $minWidth;
|
||||
$frameHeight = evenize( $frameWidth / $aspect );
|
||||
} elseif ( $frameWidth > $maxWidth ) {
|
||||
$frameWidth = $maxWidth;
|
||||
$frameHeight = evenize( $frameWidth / $aspect );
|
||||
$bitrate = min( $bitrate, $maxrate );
|
||||
}
|
||||
if ( $options[ 'stretch' ] ) {
|
||||
// Use this option when making non-square output
|
||||
$scaleWidth = $frameWidth;
|
||||
$scaleHeight = $frameHeight;
|
||||
} else {
|
||||
if ( $frameHeight < $minHeight ) {
|
||||
$frameHeight = $minHeight;
|
||||
$frameWidth = evenize( $frameHeight * $aspect );
|
||||
} elseif ( $frameWidth > $maxWidth ) {
|
||||
$frameHeight = $maxHeight;
|
||||
$frameWidth = evenize( $frameHeight * $aspect );
|
||||
$bitrate = min( $bitrate, $maxrate );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ( $options['width'] ) {
|
||||
$frameWidth = intval( $options['width'] );
|
||||
}
|
||||
if ( $options['height'] ) {
|
||||
$frameHeight = intval( $options['height'] );
|
||||
}
|
||||
|
||||
$wide = $aspect > ( $frameWidth / $frameHeight );
|
||||
$crop = boolval( $options['crop'] );
|
||||
$letterbox = boolval( $options['letterbox'] );
|
||||
if ( $crop ) {
|
||||
if ( $wide ) {
|
||||
$scaleHeight = $frameHeight;
|
||||
$scaleWidth = evenize( $frameHeight * $aspect );
|
||||
// Assumes square pixels
|
||||
$wide = $aspect > ( $frameWidth / $frameHeight );
|
||||
$crop = boolval( $options['crop'] );
|
||||
$letterbox = boolval( $options['letterbox'] );
|
||||
if ( $crop ) {
|
||||
if ( $wide ) {
|
||||
$scaleHeight = $frameHeight;
|
||||
$scaleWidth = evenize( $frameHeight * $aspect );
|
||||
} else {
|
||||
$scaleWidth = $frameWidth;
|
||||
$scaleHeight = evenize( $frameWidth / $aspect );
|
||||
}
|
||||
} else {
|
||||
$scaleWidth = $frameWidth;
|
||||
$scaleHeight = evenize( $frameWidth / $aspect );
|
||||
}
|
||||
} else {
|
||||
if ( $wide ) {
|
||||
$scaleWidth = $frameWidth;
|
||||
$scaleHeight = evenize( $frameWidth / $aspect );
|
||||
} else {
|
||||
$scaleHeight = $frameHeight;
|
||||
$scaleWidth = evenize( $frameHeight * $aspect );
|
||||
if ( $wide ) {
|
||||
$scaleWidth = $frameWidth;
|
||||
$scaleHeight = evenize( $frameWidth / $aspect );
|
||||
} else {
|
||||
$scaleHeight = $frameHeight;
|
||||
$scaleWidth = evenize( $frameHeight * $aspect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -376,7 +348,22 @@ function convert( $src, $dest, $options ) {
|
|||
|
||||
$fps = $options['fps'];
|
||||
|
||||
$preset = $options['preset'];
|
||||
if ( $options['preset'] ) {
|
||||
$preset = [ '-preset', $options[ 'preset' ] ];
|
||||
} else {
|
||||
$preset = [];
|
||||
}
|
||||
|
||||
$extension = pathinfo( $dest )[ 'extension' ];
|
||||
if ( $extension === 'mp4' || $extension === 'mov' ) {
|
||||
$format = [ '-movflags', '+faststart' ];
|
||||
} else if ( $extension === 'webm' || $extension === 'mkv' ) {
|
||||
$format = [ '-cues_to_front', 1 ];
|
||||
} else {
|
||||
$format = [];
|
||||
}
|
||||
|
||||
$vcodec = $options['vcodec'];
|
||||
|
||||
$tempPrefix = 'pack-vid-passlog' . rand(0,1 << 31);
|
||||
$passlog = tempnam( '.', $tempPrefix );
|
||||
|
|
@ -386,13 +373,13 @@ function convert( $src, $dest, $options ) {
|
|||
'-f', 'mp4',
|
||||
'-fpsmax', $fps,
|
||||
'-vf', $vf,
|
||||
'-c:v', 'libx264',
|
||||
'-c:v', $vcodec,
|
||||
'-b:v', $bitrate,
|
||||
'-preset', $preset,
|
||||
], $preset, [
|
||||
'-pass', '1',
|
||||
'-passlogfile', $passlog,
|
||||
'-g', $keyframeInt,
|
||||
], $audio, [
|
||||
'-an',
|
||||
'-y', '/dev/null'
|
||||
] )
|
||||
);
|
||||
|
|
@ -401,14 +388,13 @@ function convert( $src, $dest, $options ) {
|
|||
'-i', $src,
|
||||
'-vf', $vf,
|
||||
'-fpsmax', $fps,
|
||||
'-c:v', 'libx264',
|
||||
'-c:v', $vcodec,
|
||||
'-b:v', $bitrate,
|
||||
'-preset', $preset,
|
||||
], $preset, [
|
||||
'-pass', '2',
|
||||
'-passlogfile', $passlog,
|
||||
'-g', $keyframeInt,
|
||||
], $audio, [
|
||||
'-movflags', '+faststart',
|
||||
], $audio, $format, [
|
||||
'-y', $dest
|
||||
] )
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue