n00mkrad / nmkoder

Media encoding, muxing, analysis toolkit for Windows
GNU General Public License v3.0
427 stars 21 forks source link

[Feature Request] Conditional boundary rescaling #14

Open lastrosade opened 2 years ago

lastrosade commented 2 years ago

Add a way to set a maximum height and width for when batch processing.

This allows us to downscale videos to fit inside a set box while keeping aspect ratio.

This only downscales.

This is an example of how I do it in powershell.

# Determine rescaling values
$original_width = $info.streams[0].width;
$original_height = $info.streams[0].height;
$boundary_width = 2560;
$boundary_height = 1440;

$new_width = $original_width;
$new_height = $original_height;

# first check if we need to scale width
if ($original_width -gt $boundary_width) {
    # scale width to fit
    $new_width = $boundary_width
    # scale height to maintain aspect ratio
    $new_height = [Math]::Round(($new_width * $original_height) / $original_width)
}
# then check if we need to scale even with the new height
if ($new_height -gt $boundary_height) {
    # scale height to fit instead
    $new_height = $boundary_height
    # scale width to maintain aspect ratio
    $new_width = [Math]::Round(($new_height * $original_width) / $original_height)
}

# Make divisible by 2 by striping a pixel line to avoid rescaling weirdnesses.
$new_height_div = [Math]::Floor($new_height/2)*2
$new_width_div = [Math]::Floor($new_width/2)*2

$vf = "scale=w=$($new_width):h=$($new_height):flags=sinc,crop=w=$($new_width_crop):h=$($new_height_crop)"
lastrosade commented 2 years ago

A few examples of scaling:

input 3800x3000 in box of size 2560x1440 scaled to 1824x1440 input 1920x1080 in box of size 2560x1440 scaled to 1920x1080 input 1080x1920 in box of size 2560x1440 scaled to 810x1440 input 2000x2000 in box of size 2560x1440 scaled to 1440x1440 input 3840x2160 in box of size 2560x1440 scaled to 2560x1440 input 4096x2160 in box of size 2560x1440 scaled to 2560x1350 input 3072x1920 in box of size 2560x1440 scaled to 2304x1440

input 1920x1001 in box of size 2560x1440 scaled to 1920x1001 with a crop to 1920x1000

input 4096x2160 in box of size 1280x720 scaled to 1280x675 with a crop to 1280x674 input 1920x1080 in box of size 1280x720 scaled to 1280x720

input 4096x2160 in box of size 1920x1080 scaled to 1920x1012 input 3072x1920 in box of size 1920x1080 scaled to 1728x1080

n00mkrad commented 2 years ago

So it will scale whenever the width/height is larger than the specified max width/height? And always crop mod2?

lastrosade commented 2 years ago

Yes, and both

  1. keep the aspect resolution
  2. make the new resolution mod 2, I guess you don't have to do it via cropping but I think it's cleaner.
lastrosade commented 2 years ago

So uhhh, as it turns out ffmpeg's scale can already do this.

scale=w=2560:h=1440:force_original_aspect_ratio=decrease:force_divisible_by=2

force_original_aspect_ratio
    Enable decreasing or increasing output video width or height if necessary to keep the original aspect ratio. Possible values: 

force_divisible_by
    Ensures that both the output dimensions, width and height, are divisible by the given integer when used together with force_original_aspect_ratio. This works similar to using -n in the w and h options. 

https://ffmpeg.org/ffmpeg-filters.html#scale-1