How to reduze the size of a video to a target size

compressionffmpegvideo

I want to reduce the size of a video to be able to send it via email and such. I looked at this question: How can I reduce a video's size with ffmpeg? where I got good advice on how to reduce it. Problem is that I need to manually calculate the bitrate. And also when doing this I had to finish of with manual trial and error.

Is there any good way to use ffmpeg (or another tool) to reduce the size of a video to a target size?

Note due to a comment from frostschutz:

Worrying too much about size and going for a fixed filesize regardless of video length / resolution / framerate / content will not give satisfactory results most of the time… Upload it somewhere, email the link. If you must encode it, set a quality level, leave the bitrate dynamic. If it's obvious that size will not be met, cancel the encode and adapt quality level accordingly. Rinse and repeat.

Good advice in general, but it does not suit my usecase. Uploading to an external link is not an option due to technical limitations, one of them being that the receiver does not have http access.

I could also clarify that I'm NOT looking for exactly the size I'm specifying. It's enough if it is reasonably close to what I want (maybe up to 5 or 10% lower or so) but it should be guaranteed that it will not exceed my target limit.

Best Answer

It's relatively simple to put two answers together here:

Assuming you want a 10MB file (10485760 bytes) you could use ffprobe to find the duration and get the shell to perform the calculation.

Just be careful because ffprobe will report decimal places which will trip up the shell arithmetic. I've used ${length%.*} to strip off the decimal places:

size=10485760 
length=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4`
ffmpeg -i input.mp4 -b $(( $size / ${length%.*} )) output.mp4
Related Question