Reducing video size with same format and reducing frame size
Asked Answered
P

6

76

This question might be very basic

Is there a way to reduce the frame size/rate of Lossy compressed (WMV, MPEG) format, to get a smaller video, of lesser size, with same format.

Are there any open source or proprietary apis for this?

Propose answered 20/12, 2010 at 13:39 Comment(0)
N
95

ffmpeg provides this functionality. All you need to do is run someting like

ffmpeg -i <inputfilename> -s 640x480 -b 512k -vcodec mpeg1video -acodec copy <outputfilename>

For newer versions of ffmpeg you need to change -b to -b:v:

ffmpeg -i <inputfilename> -s 640x480 -b:v 512k -vcodec mpeg1video -acodec copy <outputfilename>

to convert the input video file to a video with a size of 640 x 480 and a bitrate of 512 kilobits/sec using the MPEG 1 video codec and just copying the original audio stream. Of course, you can plug in any values you need and play around with the size and bitrate to achieve the quality/size tradeoff you are looking for. There are also a ton of other options described in the documentation

Run ffmpeg -formats or ffmpeg -codecs for a list of all of the available formats and codecs. If you don't have to target a specific codec for the final output, you can achieve better compression ratios with minimal quality loss using a state of the art codec like H.264.

Newcomen answered 20/12, 2010 at 16:2 Comment(7)
-b needs to be -b:v for vid bit rateBalliett
@MrAH, thanks for the update. It appears that the interface has changed since I posted this. It used to be -b for video bitrate and -ab for audio bitrate, but it has changed to -b:[stream specifier].Newcomen
The command is slightly incomplete. It is missing that you need to put also the name of your output file: ffmpeg -i <inputfilename> -s 640x480 -b 512k -vcodec mpeg1video -acodec copy <outputfilename>Potherb
@JasonB Hey buddy, this is great. Do you know how to do this using NodeJS ?Nolita
@JasonB i have one video of 9MB when i use your code it's size is increased to 16mb please helpHampson
you don't have to specify the video codec when i did it broke. the following worked for me ffmpeg -i input.mp4 -s 640x480 -b:v 512k -acodec copy output.mp4 which reduced a 21M video to 4.6M fine.Supplicatory
MPEG1 is an obsolete codec, not a good recommendation vs. x264 or VP9. And often you get better results with a quality target, not absolute bitrate. e.g. x264 default of -crf 23 is pretty reasonable across a range of resolutions and types of content.Holinshed
B
41

If you want to keep same screen size, you can consider using crf factor: https://trac.ffmpeg.org/wiki/Encode/H.264

Here is the command which works for me: (on mac you need to add -strict -2 to be able to use aac audio codec.

ffmpeg -i input.mp4 -c:v libx264 -crf 24 -b:v 1M -c:a aac output.mp4
Buchan answered 27/8, 2014 at 12:39 Comment(2)
Good suggestion, except don't use FFmpeg's built-in AAC encoder: it sounds like crap. If you want AAC, at least use libfdk-aac, or these days prefer Opus audio (totally free / open source / not patent encumbered, and competitive with the best AAC encoders. Far better than the worst AAC encoders, like FFmpeg's -c:a aac). Use -c:a libopus -b:a 64k or something like that. (But note that MP4 containers can't hold Opus audio.)Holinshed
-b:v 1M overrides -crf. Don't use both. Just use CRF.Holinshed
J
30

Instead of chosing fixed bit rates, with the H.264 codec, you can also chose a different preset as described at https://trac.ffmpeg.org/wiki/x264EncodingGuide. I also found Video encoder comparison at KeyJ's blog (archived version) an interesting read, it compares H.264 against Theora and others.

Following is a comparison of various options I tried. The recorded video was originally 673M in size, taken on an iPad using RecordMyScreen. It has a duration of about 20 minutes with a resolution of 1024x768 (with half of the video being blank, so I cropped it to 768x768). In order to reduce size, I lowered the resolution to 480x480. There is no audio.

The results, taking the same 1024x768 as base (and applying cropping, scaling and a filter):

  • With no special options: 95M (encoding time: 1m19s).
  • With only -b 512k added, the size dropped to 77M (encoding time: 1m17s).
  • With only -preset veryslow (and no -b), it became 70M (encoding time: 6m14s)
  • With both -b 512k and -preset veryslow, the size becomes 77M (100K smaller than just -b 512k).
  • With -preset veryslow -crf 28, I get a file of 39M which took 5m47s (with no visual quality difference to me).

N=1, so take the results with a grain of salt and perform your own tests.

Jacklin answered 1/12, 2013 at 23:2 Comment(1)
Without any rate options, the x264 default is -crf 23. But yes, for encode-once stream-many you should use something like -preset veryslow. Not surprising this does very well on a screen-capture. Usually you don't need to downscale unless you're aiming for very low bitrates; leaving the details spread out over more pixels tends to help codecs keep detail better. Artifacts around sharp edges tend to be a fixed number of pixels so higher rez makes the artifacts smaller. (Even though fewer bits per pixel means more quantization, some of that is blurring instead of artifacts.)Holinshed
C
4

There is an application for both Mac & Windows call Handbrake, i know this isn't command line stuff but for a quick open file - select output file format & rough output size whilst keeping most of the good stuff about the video then this is good, it's a just a graphical view of ffmpeg at its best ... It does support command line input for those die hard texters.. https://handbrake.fr/downloads.php

Copartner answered 29/6, 2018 at 14:25 Comment(1)
it supports command line handbrake.fr/docs/en/latest/cli/cli-options.htmlAsthmatic
S
4

I found myself wanting to do this too recently, so I created a tool called Shrinkwrap that uses FFmpeg to transcode videos, while preserving as much of the original metadata as possible (including file modification timestamps).

You can run it as a docker container:

docker run -v /path/to/your/videos:/vids bennetimo/shrinkwrap \
--input-extension mp4 --ffmpeg-opts crf=22,preset=fast /vids

Where:

  • /path/to/your/videos/ is where the videos are that you want to convert
  • --input-extension is the type of videos you want to process, here .mp4
  • --ffmpeg-opts is any arbitrary FFmpeg options you want to use to customise the transcode

Then it will recursively find all of the video files that match the extension and transcode them all into files of the same name with a -tc suffix.

For more configuration options, presets for GoPro etc, see the readme.

Hope this helps someone!

Superimpose answered 8/11, 2018 at 22:23 Comment(0)
F
3
ffmpeg -i <input.mp4> -b:v 2048k -s 1000x600 -fs 2048k -vcodec mpeg4 -acodec copy <output.mp4>
  • -i input file

  • -b:v videobitrate of output video in kilobytes (you have to try)

  • -s dimensions of output video

  • -fs FILESIZE of output video in kilobytes

  • -vcodec videocodec (use ffmpeg -codecs to list all available codecs)

  • -acodec audio codec for output video (only copy the audiostream, don't temper)
Ferneferneau answered 27/5, 2018 at 7:37 Comment(1)
-fs makes FFmpeg stop encoding after that filesize is reached. It's not a target filesize for rate calculation. If you got -b:v right, your file will be the right size anyway, and if you got it wrong it will be smaller or truncated.Holinshed

© 2022 - 2024 — McMap. All rights reserved.