This commit is contained in:
Brooke Vibber 2023-04-09 19:23:42 -07:00
parent 4757720ac4
commit c65e2a49b5

View file

@ -2,8 +2,8 @@
<?php
// Squishes given video input into sub-4000kb .mp4
// Crops or pads to 16:9 (crop default; --letterbox to pad)
// Strips audio (to override, pass --audio for 96 kbps AAC)
// Crops or pads to 16:9 (letterbox default; --crop to crop)
// Includes stereo audio (to strip, pass --no-audio)
// HDR to SDR tonemapping
// Picks bitrate to match
// Picks resolution based on bitrate target
@ -16,10 +16,10 @@ $maxBytes = 4000 * 1000; // fit in 4MB
$maxBytes = $maxBytes * 15 / 16; // leave some headroom
$options = [
'letterbox' => false,
'audio' => false,
'exposure' => '0',
'peak' => '10000',
'crop' => false,
'no-audio' => false,
'exposure' => '-0.5', // half stop down
'peak' => '1000', // '10000' is max
'fps' => '60',
'size' => $maxBytes,
'quality' => 0.75,
@ -40,8 +40,8 @@ if ( count ( $args ) < 2 ) {
die(
"Usage: $self [options...] <srcfile.mp4> <destfile.mp4>\n" .
"Options:\n" .
" --letterbox pad instead of cropping\n" .
" --audio include audio\n" .
" --crop crop instead of padding\n" .
" --no-audio strip audio\n" .
" --exposure=n adjust exposure\n" .
" --peak=n set HDR peak nits\n" .
" --fps=n frame rate limit\n" .
@ -141,16 +141,21 @@ function convert( $src, $dest, $options ) {
$bitrate = floor( $maxBits / $duration );
if ( $options[ 'audio' ] ) {
$audioBitrate = 96 * 1000;
$audio = [ '-b:a', $audioBitrate ];
$bitrate -= $audioBitrate;
} else {
if ( $options[ 'no-audio' ] ) {
$audio = [ '-an' ];
} else {
$audioBitrate = 96 * 1000;
$audio = [
'-ac', 2,
'-b:a', $audioBitrate,
];
$bitrate -= $audioBitrate;
}
$bitrate = max( $bitrate, 16000 );
$mbits = 1000 * 1000;
$base = intval( $mbits * $options['quality'] );
$base = intval( $mbits * floatval( $options['quality'] ) );
if ( $bitrate < 1 * $base || $height < 480 ) {
$frameWidth = 640;
$frameHeight = 360;
@ -167,22 +172,22 @@ function convert( $src, $dest, $options ) {
$aspect = $width / $height;
$wide = $aspect > ( $frameWidth / $frameHeight );
$pad = boolval( $options['letterbox'] );
if ( $pad ) {
$crop = boolval( $options['crop'] );
if ( $crop ) {
if ( $wide ) {
$scaleWidth = $frameWidth;
$scaleHeight = evenize( $frameWidth / $aspect );
} else {
$scaleHeight = $frameHeight;
$scaleWidth = evenize( $frameHeight * $aspect );
} else {
$scaleWidth = $frameWidth;
$scaleHeight = evenize( $frameWidth / $aspect );
}
} else {
if ( $wide ) {
$scaleHeight = $frameHeight;
$scaleWidth = evenize( $frameHeight * $aspect );
} else {
$scaleWidth = $frameWidth;
$scaleHeight = evenize( $frameWidth / $aspect );
} else {
$scaleHeight = $frameHeight;
$scaleWidth = evenize( $frameHeight * $aspect );
}
}
@ -201,12 +206,12 @@ function convert( $src, $dest, $options ) {
$filters[] = "zscale=t=bt709:m=bt709:r=full";
}
$filters[] = "format=yuv420p";
if ( $options['letterbox'] ) {
if ( $crop ) {
$filters[] = "crop=w=$frameWidth:h=$frameHeight";
} else {
$offsetX = round( ( $frameWidth - $scaleWidth) / 2 );
$offsetY = round( ( $frameHeight - $scaleHeight) / 2 );
$filters[] = "pad=w=$frameWidth:h=$frameHeight:x=$offsetX:y=$offsetY";
} else {
$filters[] = "crop=w=$frameWidth:h=$frameHeight";
}
$vf = implode( ',', $filters );