Android: Compressing video with FFmpeg

Ray Chong
4 min readJan 4, 2022
Photo by Jakob Owens on Unsplash

FFmpeg is a free and open-source software project that includes a library and tools for dealing with video, audio, and other multimedia files and streams. The command-line FFmpeg utility, which is used to process video and audio data, is at its heart. Format transcoding, basic editing (trimming and concatenation), video scaling, video post-production effects, and standards compliance are all common uses (SMPTE, ITU).

FFmpeg is a sophisticated tool that can handle practically anything with multimedia files you can think of. We’re only interested in using it to compress video files in this tutorial, so I won’t go through all of its features. To avoid reinventing the wheel, I will demonstrate the use of FFmpeg-Android-Java in this article. According to a few sample use cases I found on the internet, FFmpeg can compress a 30 seconds video with an 80MB file size down to 4MB in 90 seconds. That’s 95% smaller in size!

Compress Techniques

Before we dive into the tutorial steps, let's understand how FFmpeg works in general. There are a few techniques that influence the quality of a video when it is compressed to a lower size.

  1. Bitrate

The most straightforward technique is to alter the bitrate, with -b flag, which may or may not result in a difference in quality. The ability of humans to see and hear isn’t as simple and straightforward as we’d like to believe. Changing bitrates can sometimes make a significant impact on subjective quality. In other situations, it may only affect the file size. It’s sometimes difficult to predict what will happen without putting something to the test. For example, the below query will copy the audio (-c:a copy) from input.mp4 and convert the video to a VP9 codec (-c:v vp9) with a bit rate of 1M/s (-b:v), all bundled up in a Matroska container (output.mp4).

ffmpeg -i input.mp4 -c:a copy -c:v vp9 -b:v 1M output.mp4

2. Frame rate

Another technique to improve video quality is to use the -r option to change the frame rate. The command below creates a new Matroska with the audio stream copied over and the video stream’s frame rate forced to 30 frames per second, instead of using the frame rate from the input (-r 30).

ffmpeg -i input.mp4 -c:a copy -c:v vp9 -r 30 output.mp4

3. Dimension

You can also use FFmpeg to change the dimensions of your video. The most straightforward method is to set a preset video size:

ffmpeg -i input.mp4 -c:a copy -s hd720 output.mp4

Frame rate and bitrate adjustments are two simple yet efficient methods for changing media quality. If the quality of an existing source is already poor, increasing these values will not enhance it.

Changing these settings is the most efficient way to compress a high-quality stream into a smaller file. The compression process can be highly subjective at times, and it may not always perform as planned. Making some modifications and seeing if it looks or sounds better is the best technique.

Implementation

This tutorial is based on the Github library attached above. To start with the implementation, you’ll need to amend your app .gradle file to include the library source either in AAR format or via a grade import statement.

repositories {
flatDir {
dirs 'libs'
}
}

dependencies {
implementation(name:'FFmpegAndroid', ext:'aar')
// orimplementation 'com.writingminds:FFmpegAndroid:0.3.2'
}

The minimum support version for this library starts at Android 4.1+ and it currently supports these architectures listed below,

  • armv7
  • armv7-neon
  • armv8
  • x86
  • x86_64

Before we can use this library, we must first load the binary for initialization. The device may also be subject to the FFmpegNotSupported exception in rare circumstances. It’s usually a good idea to send a message to users via Toast / Dialog so that they are aware of the situation. If it’s in the plans, you can also send the user to a different method.

Once the library is successfully inits, you may start compressing the source video selected by the user. Usage as below;

execFFmpegBinary(new String[]{“-y”, “-i”, “source-path”, “-s”, “480x320”, “-r”, “25”, “-vcodec”, “mpeg4”, “-b:v”, “300k”, “-b:a”, “48000”, “-ac”, “2”, “-ar”, “22050”, “output-path”})

The above query also can be translated to this manner if a cmd statement is preferred.

ffmpeg -y -i /source-path/input.mp4 -s 480x320 -r 25 -vcodec mpeg4 -b:v 300k -b:a 48000 -ac 2 -ar 22050 /source/output.mp4

command cheatsheet

You can begin experimenting with the command based on the situation. Please check this website for further options on the command for advanced video/audio processing. Have a great time exploring and having fun!

Reference:

--

--