0

Introduction

I use this command to deshake and stabilize a video:

ffmpeg2 -i SHAKY_INPUT_VIDEO.mp4 -vf \
  vidstabdetect=stepsize=6:shakiness=8:accuracy=9:result=transform_vectors.trf \
  -f null -

ffmpeg2 -i SHAKY_INPUT_VIDEO.mp4 -vf \
  vidstabtransform=input=transform_vectors.trf:zoom=1:smoothing=30,unsharp=5:5:0.8:3:3:0.4 \
-vcodec libx264 -preset slow -tune film -crf 18 -acodec copy SMOOTH_OUTPUT_VIDEO.mkv

(I use mkv since mp4 output results in this error: Could not find tag for codec pcm_s16le in stream #1, codec not currently supported in container)

Source: https://www.epifocal.net/blog/video-stabilization-with-ffmpeg

I use ffmpeg2 (See Deshaking videos using script)

How to reduce the video size?

Above two lines stabilize the video size. How can I reduce the size?

I see two aspects:

  • audio
  • resolution. If I understand the following output the resolution is at the moment 1920x1080. I think 720p would be enough.

My video meta data:

===> ffprobe2 20170217_114248.MOV 
ffprobe version git-2017-02-19-3206ea4 Copyright (c) 2007-2017 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
  configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libfreetype --enable-gnutls --disable-ffserver --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvidstab --enable-libtheora --enable-libwavpack --enable-libopenjpeg --enable-libgsm --enable-nvenc
  libavutil      55. 47.100 / 55. 47.100
  libavcodec     57. 80.101 / 57. 80.101
  libavformat    57. 66.102 / 57. 66.102
  libavdevice    57.  2.100 / 57.  2.100
  libavfilter     6. 73.100 /  6. 73.100
  libavresample   3.  2.  0 /  3.  2.  0
  libswscale      4.  3.101 /  4.  3.101
  libswresample   2.  4.100 /  2.  4.100
  libpostproc    54.  2.100 / 54.  2.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '20170217_114248-Felix-Jáchymovská.MOV':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    creation_time   : 2017-02-17T10:39:32.000000Z
  Duration: 00:03:15.00, start: 0.000000, bitrate: 23478 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 22060 kb/s, 60 fps, 60 tbr, 60k tbn, 120k tbc (default)
    Metadata:
      creation_time   : 2017-02-17T10:39:32.000000Z
      handler_name    : iCatch Alias Data Handler
      encoder         : iCatch AVCC
    Stream #0:1(eng): Audio: pcm_s16le (sowt / 0x74776F73), 44100 Hz, 2 channels, s16, 1411 kb/s (default)
    Metadata:
      creation_time   : 2017-02-17T10:39:32.000000Z
      handler_name    : iCat Alias Data Handler
1

You have several methods to reduce output file size:

Encode the audio

As you mentioned you can encode the audio instead of stream copying the hefty, lossless, uncompressed PCM format.

Using libfdk_aac

Your ffmpeg supports the AAC encoder libfdk_aac, which is the best AAC encoder supported by ffmpeg now. To use it replace -c:a copy with -c:a libfdk_aac -vbr 5.

Using the native FFmpeg AAC Encoder

Alternatively, you could use the native FFmpeg AAC encoder. To use it replace -c:a copy with -c:a aac -b:a 128k. It's not as good as libfdk_aac, but give it more bits and it will be acceptable.

Now you can use the MP4 output container format if you prefer it over Matroska (MKV).

For more info on both of these encoders see FFmpeg Wiki: AAC.

Use a higher -crf value

When using libx264 to encode H.264 video the -crf option is one method of rate control to control the quality. A value of ~18 or so will more or less result in a visually lossless output, but depending on content, it can also result in a somewhat large file. Increasing the value +6 will usually decrease the output file size by 50%. General recommendation is to use the highest -crf value that still provides an acceptable quality.

If you are targeting a specific output file size, such as due to storage media constraints, then you should encode using two-pass mode. However, unless a specific target file size is of utmost importance it is easier and faster to just use -crf (I haven't used two-pass in years).

For more info see FFmpeg Wiki: H.264.

Use a different encoder

If used properly encoding to H.265/HEVC with libx265 may result in a lower file size at the same perceived quality. The tradeoff is the slowness of the encoding, and player/device support is not yet as prevalent as H.264.

I haven't used this encoder very much myself, so I don't know what -crf values to suggest, but it should be worth a try. You may have to use -preset veryslow to really outperform x264 if you're already using one of the slower presets in x264.

See FFmpeg Wiki: H.265.

Scaling

If you want to downscale it may be faster to scale first in both commands as opposed to scaling last in the second command. You'll have to experiment because I'm not familiar with vidstab* or if it is a bottleneck or not.

-vf scale=-2:720,vidstab*...

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.