I have some 4K 3840x2160 footage in MP4 format that I need to bring down to 1080p. I tried running

ffmpeg -i orig.mp4 -vf scale=1920:1080 smaller.mp4  

but the result is very poor quality, with the entire image being composed of square "tiles" as if I was magnifying 4:1.

Here is the output of running this command:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'origs/P1000003.MP4':
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp42avc1
    creation_time   : 2015-02-19 17:10:38
  Duration: 00:05:14.48, start: 0.000000, bitrate: 95903 kb/s
    Stream #0.0(und): Video: h264 (High), yuvj420p, 3840x2160 [PAR 1:1 DAR 16:9], 95792 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
      creation_time   : 2015-02-19 17:10:38
    Stream #0.1(und): Audio: aac, 48000 Hz, stereo, s16, 125 kb/s
      creation_time   : 2015-02-19 17:10:38
Incompatible pixel format 'yuvj420p' for codec 'mpeg4', auto-selecting format 'yuv420p'
[buffer @ 0x22a3420] w:3840 h:2160 pixfmt:yuvj420p
[scale @ 0x22a3ce0] w:3840 h:2160 fmt:yuvj420p -> w:1920 h:1080 fmt:yuv420p flags:0x4
Output #0, mp4, to '1-short.mp4':
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp42avc1
    creation_time   : 2015-02-19 17:10:38
    encoder         : Lavf53.21.1
    Stream #0.0(und): Video: mpeg4, yuv420p, 1920x1080 [PAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 25 tbn, 25 tbc
      creation_time   : 2015-02-19 17:10:38
    Stream #0.1(und): Audio: libvo_aacenc, 48000 Hz, stereo, s16, 200 kb/s
      creation_time   : 2015-02-19 17:10:38
Stream mapping:
  Stream #0.0 -> #0.0
  Stream #0.1 -> #0.1
Press ctrl-c to stop encoding
frame=  125 fps=  6 q=31.0 Lsize=     968kB time=5.00 bitrate=1586.7kbits/s    
video:842kB audio:123kB global headers:0kB muxing overhead 0.421047%

I know from experience that ffmpeg is an excellent tool, so I must be screwing up the options/parameters somehow...

How can I do this?

  • Please show the full, complete console output from your command. You can just encode a short segment, so add -t 10 to make a 10 second output. Why do you want to downscale? What is the use case for your scaled output? This info will help me provide a more accurate answer. – llogan Feb 19 '15 at 20:22
  • @LordNeckbeard I have just added the console output. I want to downscale so that I can more easily share these clips with people who are working with me. – lara michaels Feb 20 '15 at 0:10
  • 1
    Don't forget -c:a copy, since you don't want or need to re-encode the audio stream. Use -map 0 to copy any chapter metadata, or other stuff. (ffmpeg only takes 1 vid + 1 aud by default.) – Peter Cordes Feb 23 '15 at 3:10
  • 1
    Also, -sws_flags lanczos+print_info will use a better scaling algo than the default (bilinear I think). stlb's answer covers the video encoding part of the process. – Peter Cordes Feb 23 '15 at 3:14
  • 2
    @PeterCordes Alternatively, scale=1920:-2:flags=lanczos. I was also going to mention the -2 for scale in my non-existent answer. For those who don't know you can put -2 in width or height, and it will automatically provide the correct value while preserving aspect ratio and making the value divisible by 2 (required by libx264 for yuv420p outputs). – llogan Feb 23 '15 at 18:04

The default settings for ffmpeg are very low quality, and since you don't specify any codec or quality parameters it's just using the defaults (I don't know why the devs don't fix that because it generates a lot of questions on forums everywhere).

Edit: the defaults are now quite sane. With a recent build of ffmpeg you don't need to specify anything more than input and output files to achieve good useable results. You can, of course tweak to your heart's desire.

Try adding -c:v libx264 -crf 20 -preset slow to the command.

  • -c:v libx264 tells it to use the libx264 encoder,
  • crf 20 uses the Constant Rate Factor quantiser (which paradoxially means variable bit rate, but constant quality) with a value of 20 (pretty good quality; lower is better quality / larger files, higher is crappier / smaller),
  • the slow preset is a shortcut for a bunch of encoder settings that means it puts a bit more effort into it than the default (medium).

You can tweak these settings, see the h.264 encoding guide for instructions on what knobs to twiddle.

And if you're using the audio as-is, add c:a copy. That will do a straight copy of the audio stream without re-encoding.

  • The defaults depends on the encoder. libx264 is usually used for MP4 output by default, and it produces a nice quality output with no additional options, but the ffmpeg build in the question appears to not support this encoder and therefore uses the ancient encoder mpeg4 producing MPEG-4 Part 2 video, and the defaults for it were more sane during its heyday (such as for 320x240, etc). – llogan Feb 21 '15 at 6:24
  • It's good to hear that libx264 is the default now. – stib Feb 23 '15 at 1:00
  • I'd say crf 20 is pretty darn good. 18 is functionally lossless. I do most of my videos at 23. – user24601 Sep 15 '17 at 12:36
  • Most of my work gets displayed on playback devices working locally from an SD card. I don't need to optimise much for size, so I leave the quality as high as I can. I agree, I'd dial it down if I was delivering over the web. – stib Sep 16 '17 at 13:47
  • This didn't help me. I still have blocky weirdness wherever motion occurs in the video. crf of 18, preset to slow. 2.7k->1080p. – rewolf Oct 3 '17 at 13:59

Use avconv if you want:

avconv -i 4kfile.mp4 -s hd1080 -c:v libx264 -c:a copy fullhdfile.mp4

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.