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
130
pack-vid
130
pack-vid
|
|
@ -21,10 +21,11 @@ $options = [
|
||||||
'letterbox' => false,
|
'letterbox' => false,
|
||||||
'no-audio' => false,
|
'no-audio' => false,
|
||||||
'audio-bitrate' => 96000,
|
'audio-bitrate' => 96000,
|
||||||
'audio-channels' => 2,
|
'audio-rate' => false,
|
||||||
|
'audio-channels' => false,
|
||||||
'exposure' => '0', // stops
|
'exposure' => '0', // stops
|
||||||
'peak' => '1000', // '10000' is max
|
'peak' => '1000', // '10000' is max
|
||||||
'preset' => 'medium',
|
'preset' => false,
|
||||||
'fps' => '60',
|
'fps' => '60',
|
||||||
'size' => $maxBytes,
|
'size' => $maxBytes,
|
||||||
'quality' => 1.0,
|
'quality' => 1.0,
|
||||||
|
|
@ -41,6 +42,8 @@ $options = [
|
||||||
'crop-top' => false,
|
'crop-top' => false,
|
||||||
'tonemap' => 'hable',
|
'tonemap' => 'hable',
|
||||||
'color-temperature' => false,
|
'color-temperature' => false,
|
||||||
|
'vcodec' => 'libx264',
|
||||||
|
'stretch' => false,
|
||||||
];
|
];
|
||||||
|
|
||||||
while ( count( $args ) > 0 && substr( $args[0], 0, 2 ) == '--' ) {
|
while ( count( $args ) > 0 && substr( $args[0], 0, 2 ) == '--' ) {
|
||||||
|
|
@ -153,8 +156,6 @@ function extractTracks( $streams, $type ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function convert( $src, $dest, $options ) {
|
function convert( $src, $dest, $options ) {
|
||||||
$maxBits = 8 * sizify( $options['size'] );
|
|
||||||
|
|
||||||
$probe = ffprobe( $src );
|
$probe = ffprobe( $src );
|
||||||
|
|
||||||
$videoTracks = extractTracks( $probe->streams, 'video' );
|
$videoTracks = extractTracks( $probe->streams, 'video' );
|
||||||
|
|
@ -198,9 +199,14 @@ function convert( $src, $dest, $options ) {
|
||||||
$keyframeInt = intval( ceil( $duration * 60 ) );
|
$keyframeInt = intval( ceil( $duration * 60 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$bitrate = floor( $maxBits / $duration );
|
|
||||||
if ( $options['bitrate'] ) {
|
if ( $options['bitrate'] ) {
|
||||||
$bitrate = sizify( $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,109 +214,74 @@ function convert( $src, $dest, $options ) {
|
||||||
$audio = [ '-an' ];
|
$audio = [ '-an' ];
|
||||||
} else {
|
} else {
|
||||||
$audioBitrate = $options[ 'audio-bitrate' ];
|
$audioBitrate = $options[ 'audio-bitrate' ];
|
||||||
$audioChannels = $options[ 'audio-channels' ];
|
|
||||||
$audio = [
|
$audio = [
|
||||||
'-ac', $audioChannels,
|
|
||||||
'-b:a', $audioBitrate,
|
'-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 -= $audioBitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
$bitrate = max( $bitrate, 16000 );
|
if ( $options[ 'width' ] && $options[ 'height' ] ) {
|
||||||
|
// Use exact given dimensions.
|
||||||
|
$frameWidth = intval( $options[ 'width' ] );
|
||||||
|
$frameHeight = intval( $options[ 'height' ] );
|
||||||
|
} else {
|
||||||
|
// 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;
|
$mbits = 1000 * 1000;
|
||||||
$base = intval( $mbits * floatval( $options['quality'] ) );
|
$base = intval( $mbits * floatval( $options['quality'] ) );
|
||||||
if ( $bitrate < 0.125 * $base || $height < 144 ) {
|
if ( $bitrate < 0.125 * $base || $height < 144 ) {
|
||||||
$frameWidth = 256;
|
$frameWidth = 256;
|
||||||
$frameHeight = 144;
|
$frameHeight = 144;
|
||||||
$bitrate = min( $bitrate, $base * 0.25 );
|
|
||||||
} elseif ( $bitrate < 0.25 * $base || $height < 180 ) {
|
} elseif ( $bitrate < 0.25 * $base || $height < 180 ) {
|
||||||
$frameWidth = 320;
|
$frameWidth = 320;
|
||||||
$frameHeight = 180;
|
$frameHeight = 180;
|
||||||
$bitrate = min( $bitrate, $base * 0.5 );
|
|
||||||
} elseif ( $bitrate < 0.5 * $base || $height < 288 ) {
|
} elseif ( $bitrate < 0.5 * $base || $height < 288 ) {
|
||||||
$frameWidth = 512;
|
$frameWidth = 512;
|
||||||
$frameHeight = 288;
|
$frameHeight = 288;
|
||||||
$bitrate = min( $bitrate, $base * 0.5 );
|
|
||||||
} elseif ( $bitrate < 1 * $base || $height < 480 ) {
|
} elseif ( $bitrate < 1 * $base || $height < 480 ) {
|
||||||
$frameWidth = 640;
|
$frameWidth = 640;
|
||||||
$frameHeight = 360;
|
$frameHeight = 360;
|
||||||
$bitrate = min( $bitrate, $base );
|
|
||||||
} elseif ( $bitrate < 2 * $base || $height < 540) {
|
} elseif ( $bitrate < 2 * $base || $height < 540) {
|
||||||
$frameWidth = 854;
|
$frameWidth = 854;
|
||||||
$frameHeight = 480;
|
$frameHeight = 480;
|
||||||
$bitrate = min( $bitrate, $base * 2 );
|
|
||||||
} elseif ( $bitrate < 2.5 * $base || $height < 720) {
|
} elseif ( $bitrate < 2.5 * $base || $height < 720) {
|
||||||
$frameWidth = 960;
|
$frameWidth = 960;
|
||||||
$frameHeight = 540;
|
$frameHeight = 540;
|
||||||
$bitrate = min( $bitrate, $base * 2.5 );
|
|
||||||
} elseif ( $bitrate < 4 * $base || $height < 1080) {
|
} elseif ( $bitrate < 4 * $base || $height < 1080) {
|
||||||
$frameWidth = 1280;
|
$frameWidth = 1280;
|
||||||
$frameHeight = 720;
|
$frameHeight = 720;
|
||||||
$bitrate = min( $bitrate, $base * 4 );
|
|
||||||
} elseif ( $bitrate < 8 * $base || $height < 1440) {
|
} elseif ( $bitrate < 8 * $base || $height < 1440) {
|
||||||
$frameWidth = 1920;
|
$frameWidth = 1920;
|
||||||
$frameHeight = 1080;
|
$frameHeight = 1080;
|
||||||
$bitrate = min( $bitrate, $base * 8 );
|
|
||||||
} elseif ( $bitrate < 16 * $base || $height < 2160) {
|
} elseif ( $bitrate < 16 * $base || $height < 2160) {
|
||||||
$frameWidth = 2560;
|
$frameWidth = 2560;
|
||||||
$frameHeight = 1440;
|
$frameHeight = 1440;
|
||||||
$bitrate = min( $bitrate, $base * 16 );
|
|
||||||
} else {
|
} else {
|
||||||
$frameWidth = 3840;
|
$frameWidth = 3840;
|
||||||
$frameHeight = 2160;
|
$frameHeight = 2160;
|
||||||
$bitrate = min( $bitrate, $base * 32 );
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aspect = $width / $height;
|
$aspect = $width / $height;
|
||||||
$pixels = $width * $height;
|
$pixels = $width * $height;
|
||||||
|
|
||||||
// canonical min rate is 0.125 megabit at 144p
|
if ( $options[ 'stretch' ] ) {
|
||||||
$bitrate = max( $bitrate, 0.125 * $base );
|
// Use this option when making non-square output
|
||||||
|
$scaleWidth = $frameWidth;
|
||||||
/*
|
$scaleHeight = $frameHeight;
|
||||||
$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 );
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if ( $frameHeight < $minHeight ) {
|
// Assumes square pixels
|
||||||
$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 );
|
$wide = $aspect > ( $frameWidth / $frameHeight );
|
||||||
$crop = boolval( $options['crop'] );
|
$crop = boolval( $options['crop'] );
|
||||||
$letterbox = boolval( $options['letterbox'] );
|
$letterbox = boolval( $options['letterbox'] );
|
||||||
|
|
@ -331,6 +302,7 @@ function convert( $src, $dest, $options ) {
|
||||||
$scaleWidth = evenize( $frameHeight * $aspect );
|
$scaleWidth = evenize( $frameHeight * $aspect );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$exposure = floatval( $options['exposure'] );
|
$exposure = floatval( $options['exposure'] );
|
||||||
$peakNits = floatval( $options['peak'] );
|
$peakNits = floatval( $options['peak'] );
|
||||||
|
|
@ -376,7 +348,22 @@ function convert( $src, $dest, $options ) {
|
||||||
|
|
||||||
$fps = $options['fps'];
|
$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);
|
$tempPrefix = 'pack-vid-passlog' . rand(0,1 << 31);
|
||||||
$passlog = tempnam( '.', $tempPrefix );
|
$passlog = tempnam( '.', $tempPrefix );
|
||||||
|
|
@ -386,13 +373,13 @@ function convert( $src, $dest, $options ) {
|
||||||
'-f', 'mp4',
|
'-f', 'mp4',
|
||||||
'-fpsmax', $fps,
|
'-fpsmax', $fps,
|
||||||
'-vf', $vf,
|
'-vf', $vf,
|
||||||
'-c:v', 'libx264',
|
'-c:v', $vcodec,
|
||||||
'-b:v', $bitrate,
|
'-b:v', $bitrate,
|
||||||
'-preset', $preset,
|
], $preset, [
|
||||||
'-pass', '1',
|
'-pass', '1',
|
||||||
'-passlogfile', $passlog,
|
'-passlogfile', $passlog,
|
||||||
'-g', $keyframeInt,
|
'-g', $keyframeInt,
|
||||||
], $audio, [
|
'-an',
|
||||||
'-y', '/dev/null'
|
'-y', '/dev/null'
|
||||||
] )
|
] )
|
||||||
);
|
);
|
||||||
|
|
@ -401,14 +388,13 @@ function convert( $src, $dest, $options ) {
|
||||||
'-i', $src,
|
'-i', $src,
|
||||||
'-vf', $vf,
|
'-vf', $vf,
|
||||||
'-fpsmax', $fps,
|
'-fpsmax', $fps,
|
||||||
'-c:v', 'libx264',
|
'-c:v', $vcodec,
|
||||||
'-b:v', $bitrate,
|
'-b:v', $bitrate,
|
||||||
'-preset', $preset,
|
], $preset, [
|
||||||
'-pass', '2',
|
'-pass', '2',
|
||||||
'-passlogfile', $passlog,
|
'-passlogfile', $passlog,
|
||||||
'-g', $keyframeInt,
|
'-g', $keyframeInt,
|
||||||
], $audio, [
|
], $audio, $format, [
|
||||||
'-movflags', '+faststart',
|
|
||||||
'-y', $dest
|
'-y', $dest
|
||||||
] )
|
] )
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue