I'm testing out converting some videos to HEVC encoding utilizing ffmpeg and libx265 and I've discovered that the the input width must be divisible by 8 in order to successfully re-encode. I would like to determine whether a re-encode will be successful without attempting the encode and then examining the output. Ideally I'd like to do this in a bash script. My skills are somewhat limited in this regard and much of what I have come up with thus far is far less than elegant.

For example I know that I can do the math with bc as in:

 echo 'scale=2;576/8' | bc 72.00 

and I can obtain the width via

width=$(mediainfo $filename | grep "Width" | sed 's/[^0-9]*//g') 

but the former doesn't exactly answer the question is the width divisible by 8 and the latter is ugly and uses too many pipes which research indicates is less then efficient.

I've got the ffmpeg command line for re-encoding sorted to my satisfaction using:

ffmpeg -i "$f" -c:a copy -c:v libx265 -preset "$preset" -crf 25 "$target"

and I intend to scale the video to a width divisible by 8 if it isn't already but I'm looking for better solutions than I've come up with thus far for determining if scaling is required and how to determine the closest width divisible by 8 to scale to.

1

2 Answers

The following will correct the width to a number divisible by 8 and then correctly rescale the height to a number divisible by 8 while maintaining correct aspect ratio:

ffmpeg -i <input> \ -c:a copy \ -c:v libx265 -preset medium -x265-params crf=28 \ -vf scale="trunc(iw/8)*8:-8" \ <output> 

As a bonus if the width is already divisible by 8 there will be no change in the output width and no error from FFmpeg.

An explanation for the scale syntax, remembering that the syntax is -vf scale=width:height:

1. Output Width Calculation:

  • iw/8: The width of the input video stream will be divided by 8. So an original width of 690 would create a number 86.25
  • trunc: The number 86.25 would be 'truncated' to 86
  • *8: 86 would be multiplied by 8 to give a final width of 688 which of course is divisible by 8!

2. Output Height Calculation:

  • -8: FFmpeg will calculate a height that is divisible by 8 but which also maintains the correct aspect ratio of the original file

In a perfect world hevc encoding is run with encoding units of 8x8, 16x16, 32x32 etc and this syntax guarantees this. More details of this here...

References:

8

Obtaining the width is relatively simple with mediainfo. If you don't have it you can install it with sudo apt-get install mediainfo

width=$(mediainfo '--Inform=Video;%Width%' $filename)

Determining divisibility by 8 can be done via

if [ $(( $width % 8 )) -eq 0 ] ; then echo "Your number is divisible by 8 – you may convert it” else echo "Video width is not divisible by 8 – it needs scaling to re-encode it." fi 

A far simpler and faster approach inspired by @andrew.46 and a bit more research and testing is to let ffmpeg do the work with

ffmpeg -i $inputfilename -c:a copy -c:v libx265 -preset veryfast -x265-params crf=25 -vf scale=-8:ih $outputfilename

the -vf scale=-8:ih setting insures that the width is divisible by 8 (-8) and uses the input height (ih) accordingly to maintain aspect ratio.

Sources: man mediainfo

How can I determine if a video can be encoded successfully with HEVC (x265) encoding

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy