
If you want to compress your videos with high compression efficiency and high video quality, then HEVC encoding using FFMpeg is the way to go.
HEVC (High-Efficiency Video Coding), or H.265 is a video compression standard that was developed to address the limitations of its predecessor, H.264/AVC. It uses more advanced coding techniques (compared to H.264) to achieve higher compression efficiency. It can encode a video with the same quality as H.264 but at a much lower bitrate.
To understand the power of HEVC, read this article that compares the compression efficiency of HEVC vs. H.264/AVC – you can see that a 35-50% savings on bitrate is possible by switching to HEVC. Predictions by experts in transcoding also point towards a gradual move towards the HEVC codec in the years to come.
HEVC achieves this high quality at lower bitrates by using larger blocks for motion compensation, quadtree decomposition, better prediction techniques, and more flexible coding tools such as the DST (Discrete Sine Transform), SAO, and others.
HEVC is widely used in applications requiring high-quality video at lower bitrates, such as streaming, video conferencing, and broadcasting. However, HEVC encoding & decoding requires more processing power than its predecessor and may not be supported by older devices or software.
In this article, we will explore encoding using HEVC and FFmpeg. To learn more about FFmpeg, please check out OTTVerse’s comprehensive FFmpeg tutorials. Additionally, you might find FFprobe very useful for examining your encodes and getting metadata – learn how to use FFprobe here.
System Parameters and Test Sequences
- I ran these tests using FFmpeg 6.0 on an M1 MacBook Pro (M1 Pro Chip with 8 cores, 16 GB RAM, and 512 GB SSD).
- The test sequence I used is a 1080p version of the Big Buck Bunny downloadable from here (https://test-videos.co.uk/bigbuckbunny/mp4-h264).
- I use the
benchmark
parameter in FFmpeg in all my command lines. It shows the real, system, and user time used; and the encoding speed (in fps).
HEVC Encoding using FFmpeg – the Basic Commands
Let’s start off with a simple example and build up from there. To use FFmpeg to transcode videos using the HEVC codec, you need to use the libx265
implementation. To access all the parameters available in the x265
library, please read the official docs.
Let’s start this quick tutorial by trying out a simple FFmpeg command line and encode a video using HEVC.
./ffmpeg -i input_file -c:v libx265 -preset [preset] -crf [crf] -x265-params [params] -c:a copy output_file
Here’s what each parameter does:
-i input_file
: Specifies the input video file.-c:v libx265
: Specifies that the video codec for encoding is HEVC or H.265.-preset [preset]
: Specifies the preset for the HEVC encoder. The available presets are ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, and placebo. The slower the preset, the higher the compression and the better the quality.-crf [crf]
: Specifies the Constant Rate Factor (CRF) for the HEVC encoder. The CRF ranges from 0-51, with 0 being lossless and 51 being the worst quality possible. A lower CRF value will result in a higher quality and larger file size, while a higher CRF value will result in a lower quality and smaller file size. The default value is 28.-x265-params [params]
: Specifies additional HEVC encoder parameters. This can be used to fine-tune the encoding process.-c:a copy
: Specifies that the audio stream should be copied as-is without any re-encoding.output_file
: Specifies the output file name and location.
By using this commandline and changing the parameters, you can produce HEVC encodes of varying quality and size. I repeat the following –
- I ran these tests using FFmpeg 6.0 on an M1 MacBook Pro (M1 Pro Chip with 8 cores, 16 GB RAM, and 512 GB SSD).
- The test sequence I used is a 1080p version of the Big Buck Bunny downloadable from here (https://test-videos.co.uk/bigbuckbunny/mp4-h264).
Let’s try tests using a CRF value of 20 and varying the presets.
HEVC encoding with the “slow” preset and a CRF value of 20.
./ffmpeg -benchmark -i Big_Buck_Bunny_1080_10s_30MB.mp4 -c:v libx265 -preset slow -crf 20 -c:a copy output_slow_crf20.mp4
This produces a file that’s 12 MB in size and has a PSNR of 43.15 dB, taking 32.62s (9.20 fps).
HEVC encoding with the “medium” preset and a CRF value of 20.
./ffmpeg -benchmark -i Big_Buck_Bunny_1080_10s_30MB.mp4 -c:v libx265 -preset medium -crf 20 -c:a copy output_medium_crf20.mp4
This produces a file that’s 11 MB in size and has a PSNR of 42.20 dB, taking 12.93s (23.20 fps).
HEVC encoding with the “fast” preset and a CRF value of 20.
./ffmpeg -benchmark -i Big_Buck_Bunny_1080_10s_30MB.mp4 -c:v libx265 -preset fast -crf 20 -c:a copy output_fast_crf20.mp4
This produces a file that’s 9.7 MB in size and has a PSNR of 41.53 dB, taking 11.93s (25.14 fps).
HEVC encoding with the “ultrafast” preset and a CRF value of 20.
./ffmpeg -benchmark -i Big_Buck_Bunny_1080_10s_30MB.mp4 -c:v libx265 -preset ultrafast -crf 20 -c:a copy output_ultrafast_crf20.mp4
This produces a file that’s 7.8 MB in size and has a PSNR of 38.68 dB, taking 4.23s (71.00 fps).
As you can see, by changing the preset, you can alter the transcoding process by turning on & off coding tools. This results in a change in the transcoding speed, and consequently, the quality and size of the video.
Preset | Filesize (MB) | PSNR (dB) | Time taken (sec) |
Slow | 12 | 43.15 | 32.62 |
Medium | 11 | 42.20 | 12.93 |
Fast | 9.7 | 41.53 | 11.93 |
Ultrafast | 7.8 | 38.68 | 4.23 |
To understand what tools are enabled in each of the presets, please visit the table on this page.
HEVC (x265)’s Additional Parameters
x265 is a fabulous codec implementation with hundreds of parameters you can use to tune the performance of the codec – both in terms of video quality and performance. For the complete list of parameters, go here – you can use these parameters to control the SAO strength, quantization parameters, motion estimation (half-pel and quarter-pel), frame-level parallelism, and much more.
In this example, we run an encode using and set the quantization parameter (QP) to 23
and set the Adaptive Quantization (AQ) (aq-mode
) to 2
. In AQ, the QP of every block is varied in a tradeoff between quality and bitrate.
./ffmpeg -benchmark -i Big_Buck_Bunny_1080_10s_30MB.mp4 -c:v libx265 -preset medium -crf 23 -x265-params qp=22:aq-mode=2 -c:a copy output.mp4
In this example, we’re using the medium preset with a CRF of 23, and adding the qp
and aq-mode
parameters to further fine-tune the encoding process.
CBR Encoding using HEVC and FFmpeg
In all the examples so far, we used FFmpeg’s CRF mode to encode the videos. In this example, let’s use the CBR encoding mode. If you are new to encoding, go here to learn more about CBR, CRF, and VBR.
To encode with FFmpeg and HEVC using Constant Bitrate (CBR) mode, you can use the following command:
./ffmpeg -benchmark -i input.mp4 -c:v libx265 -b:v [bitrate] -minrate [bitrate] -maxrate [bitrate] -bufsize [buffer size] -preset medium -c:a copy output.mp4
Here’s a breakdown of the command:
- -i input.mp4: Specifies the input video file.
- -c:v libx265: Specifies the video codec to be used for encoding is HEVC or H.265.
- -b:v [bitrate]: Specifies the bitrate for the video stream. The bitrate is specified in bits per second (bps). This value will be the same throughout the video.
- -minrate [bitrate]: Specifies the minimum bitrate for the video stream. This value is used to control the quality of the video in sections with complex content.
- -maxrate [bitrate]: Specifies the maximum bitrate for the video stream. This value is used to control the quality of the video in sections with simple content.
- -bufsize [buffer size]: Specifies the size of the buffer used to store the video data. This value is used to control the amount of data that can be stored in the buffer before it is written to the output file.
- -preset medium: Specifies the medium preset for the HEVC encoder. This preset provides a balance between file size and quality.
- -c:a copy: Copies the audio stream as-is without re-encoding.
- output.mp4: Specifies the output file name and location.
You should replace the [bitrate] and [buffer size] with the desired values.
For example, to encode a 1080p HEVC video with a CBR of 5 Mbps and a buffer size of 10 Mbps, you can use the following command:
ffmpeg -benchmark -i input.mp4 -c:v libx265 -b:v 5M -minrate 5M -maxrate 5M -bufsize 10M -preset medium -c:a copy output.mp4
This command will produce a 1080p HEVC-encoded video with a CBR of 5 Mbps and a buffer size of 10 Mbps, while keeping the audio stream unchanged. Note that using CBR can result in a larger file size compared to CRF, but it provides more consistent quality throughout the video.
Here is an interesting article on CBR vs. VBR if you are interested in learning more.
2-Pass Encoding using HEVC and FFmpeg
It is very straightforward to do 2-pass encoding using HEVC and FFmpeg. While running a 2-pass encode, FFmpeg will analyze the video stream in the first pass to determine the optimal bitrate and other encoding parameters for the second pass. This can result in better compression efficiency and quality compared to a single-pass encoding process.
Word of caution: A 2-pass encode can result in better compression efficiency and quality compared to a single-pass encode, but, it may be excessive in some situations – i.e., not a lot of quality improvement despite spending a lot of time and resources. This is easily observable in simple cartoon content with piecewise-linear regions (e.g., Simpsons).
Okay – let’s get coding. Here are the steps to perform 2-pass encoding using HEVC and FFmpeg:
First Pass
First, run the first pass of the encoding process using the following command
./ffmpeg -benchmark -y -i input.mp4 -c:v libx265 -preset [preset] -b:v [bitrate] -pass 1 -f mp4 /dev/null
In this command,
- -y is used to overwrite the output file if it already exists.
- -i input.mp4 specifies the input H.264 video file. -c:v libx265 specifies the HEVC codec to be used for encoding.
- -b:v [bitrate] sets the target bitrate for the video stream.
- The value of [bitrate] is in bits per second (bps).
- -pass 1 specifies that this is the first pass of the two-pass encoding process. Finally, /dev/null is used as the output file, as the actual output file is not generated in the first pass.
Second Pass
After the first pass is complete, run the second pass of the encoding process using the following command:
./ffmpeg -benchmark -i input.mp4 -c:v libx265 -preset [preset] -b:v [bitrate] -pass 2 -c:a copy output.mp4
In this command, the
- -i input.mp4 option specifies the input H.264 video file.
- -c:v libx265 specifies the HEVC codec to be used for encoding.
- -b:v [bitrate] sets the target bitrate for the video stream. The value of [bitrate] should be the same as in the first pass.
- -pass 2 specifies that this is the second pass of the two-pass encoding process.
- Finally, -c:a copy is used to copy the audio stream from the input file without any re-encoding.
- The output video file is specified with the extension .mp4.
Converting from HEVC to H.264/AVC using FFmpeg
Finally, let’s end this tutorial with the opposite and convert HEVC to H.264/AVC using FFmpeg! Again, it’s very simple and can be done with a simple commandline.
./ffmpeg -benchmark -i input.hevc -c:v libx264 -preset [preset] -crf [crf] -c:a copy output.mp4
Here’s what each parameter does:
- -i input.hevc: Specifies the input HEVC-encoded file.
- -c:v libx264: Specifies the video codec to be used for encoding is H.264.
- -crf [crf]: Specifies the Constant Rate Factor (CRF) for the H.264 encoder. The CRF ranges from 0-51, with 0 being lossless and 51 being the worst quality possible. A lower CRF value will result in a higher quality and larger file size, while a higher CRF value will result in a lower quality and smaller file size.
- -c:a copy: Specifies that the audio stream should be copied as-is without any re-encoding.
- output.mp4: Specifies the output file name and location.
Change 1080p video to 720p video using FFmpeg and HEVC
To convert a 1080p video to a 720p video using FFmpeg and HEVC, you can use the following command:
./ffmpeg -benchmark -i Big_Buck_Bunny_1080_10s_30MB.mp4 -c:v libx265 -preset medium -crf 23 -vf scale=1280x720 -c:a copy output_1080_to_720.mp4
Here’s a breakdown of the command:
- -i input.mp4: Specifies the input video file.
- -c:v libx265: Specifies the video codec to be used for encoding is HEVC or H.265.
- -preset medium: Specifies the medium preset for the HEVC encoder. This preset provides a balance between file size and quality.
- -crf 23: Specifies the Constant Rate Factor (CRF) for the HEVC encoder. The lower the CRF value, the higher the quality and larger the file size.
- -vf scale=1280×720: Rescales the video to 720p by specifying the new resolution of 1280×720 using the scale filter.
- -c:a copy: Copies the audio stream as-is without re-encoding.
- output.mp4: Specifies the output file name and location.
This command will produce a 720p HEVC-encoded video with a medium preset and a CRF of 23, while keeping the audio stream unchanged.
Conclusion
That’s it – we’ve concluded our article on encoding basics using HEVC and FFmpeg. I hope you found it useful and will be able to use some of the ideas and command lines in your workflow. In future articles, we shall explore HDR encoding using FFmpeg. Stay tuned!
Until next time, happy streaming!

Krishna Rao Vijayanagar
Krishna Rao Vijayanagar, Ph.D. is the Editor-in-Chief of OTTVerse, a news portal covering technological and business news in the OTT space. With extensive experience in video compression, ABR streaming, video analytics, monetization, and more, Krishna has held multiple roles in R&D, Engineering, and Product ownership at companies such as Harmonic Inc., MediaMelon, and Airtel Digital. Krishna has published numerous articles and research papers on the latest trends in OTT and frequently speaks at industry events to share his insights and perspectives on the fundamentals and the future of OTT streaming.