Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
FFMpeg's playbook: Advanced encoding options with hardware-accelerated acceleration for both NVIDIA NVENC's and Intel's VAAPI-based hardware encoders in both ffmpeg and libav.

FFmpeg and libav's playbook: Advanced encoding options with hardware-based acceleration, NVIDIA's NVENC and Intel's VAAPI-based encoder.

Hello guys,

Continuing from this guide to building ffmpeg and libav with NVENC and VAAPI enabled, this snippet will cover advanced options that you can use with ffmpeg and libav on both NVENC and VAAPI hardware-based encoders.

For ffmpeg:

As usual, we supply the usual arguments when we want to encode with VAAPi-based encoders:

ffmpeg -loglevel debug -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i input_file -vf 'format=nv12,hwupload' -threads 8 -aspect 16:9 -y -f matroska -acodec copy -vcodec h264_vaapi -qp 19 -bf 2 "output_file"

For libav:

Libav takes its' arguments in a slightly different way. For both ffmpeg and libav, refer to this on what these arguments do. If you're already familiar with both pipelines, carry on.

avconv -v 55 -y -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -i "input_file" -c:a copy -vf 'format=nv12|vaapi,hwupload' -c:v h264_vaapi -bf 2 -b 12500k "output_file"

Trying two-pass with the h264_vaapi encoder:

ffmpeg -loglevel debug -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i "input_file" -vf 'format=nv12,hwupload' -pass 1 -map 0:0 -map 0:1 -threads 8 -aspect 16:9 -y -f matroska -an -c:v h264_vaapi -b 7.5M "/dev/null"

ffmpeg -loglevel debug -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i "input_file" -vf 'format=nv12,hwupload' -pass 2 -map 0:0 -map 0:1 -threads 8 -aspect 16:9 -y -f matroska -acodec copy -c:v h264_vaapi -b 7.5M "output_file"

And with NVENC:

NVENC's h264 and h265_nvenc based encoders natively support two-pass encoding, and this should be pretty straight-forward:

ffmpeg -loglevel debug -hwaccel cuvid -i "input_file" -c:v h264_nvenc -preset llhq -profile:v high -rc ll_2pass_quality -an -b:v 2.4M -pass 1 -2pass -1 "output_file"

ffmpeg -loglevel debug -hwaccel cuvid  -i "input_file" -c:v h264_nvenc -preset llhq -profile:v high -rc ll_2pass_quality -acodec copy -b:v 2.4M -pass 2 -2pass -1 -y "output_file"

Note the syntax order:

(a). The first will always be ffmpeg (the binary name in the system path or absolute path to ffmpeg depending on your deployment).

(b). The second should be an option passed directly to ffmpeg, such as a debug value (if needed).

(c). -i: Here is your input file's absolute path. If you are already in the path relative to the file's position, then use that relative path. The same applies to the output video too.

(d). -c:v : Use this to select the encoder. In the example above, we have selected h264_nvenc.

(e). -preset: Some video and audio encoders will support the preset argument. In the case where both the video and the audio codec support the same argument, such as this, then wrap this argument with a declaration, as shown: -preset:v would apply for the video encoder whereas -preset:a would apply for the audio encoder.

(f). Here, pass absolute options to the video encoder. In the example above, we are passing -rc (the rate control factor) recognized by the h264_nvenc encoder, and selecting the low-latency, 2-pass quality rate control factor as we are doing a two-pass high quality encode. You will also notice that we have passed the -profile:v option to the video encoder (h264_nvenc) to select the high quality preset.

(g). -acodec: Use this to select the audio encoder to use. In our case, we are copying the audio as is and we don't re-encode.

(h). -b:v: This selects a video bitrate. In our example, we have selected a 2.4 MB/s variable bitrate by default, as the nvenc_h264 encoder uses variable rate encoding unless its' explicitly disabled (via the -cbr option that enforces constant-rate encoding). (i). -hwaccel: Here, you can select the hardware acceleration decode method you wish to use. If you compiled ffmpeg with NPP (Nvidia Performance Primitives) enabled under the NVIDIA Video SDK directive, you can select cuvid here.

Optional arguments:

(a).-c:a copy copies the audio stream

(b).-f: Selects the container format to use. This can be MP4, Matroska, etc. Select whatever suits you, and take note of container restrictions.

Formats (muxers and demuxers):

List all supported formats in your ffmpeg build:

ffmpeg -formats

Display options specific to, and information about, a particular muxer:

ffmpeg -h muxer=matroska

Display options specific to, and information about, a particular demuxer:

ffmpeg -h demuxer=matroska

Codecs (encoders and decoders):

List all supported codecs in your ffmpeg build:

ffmpeg -codecs

List all supported encoders in your ffmpeg build:

ffmpeg -encoders

List all available decoders in your ffmpeg build:

ffmpeg -decoders

Display options specific to, and information about, a particular encoder:

ffmpeg -h encoder=mpeg4

Display options specific to, and information about, a particular decoder:

ffmpeg -h decoder=aac

Display information about all hardware acceleration(s) supported by your current ffmpeg build:

ffmpeg -hwaccels

Reading the results

There is a key near the top of the output that describes each letter that precedes the name of the format, encoder, decoder, or codec:

$ ffmpeg -encoders
 V..... = Video
 A..... = Audio
 S..... = Subtitle
 .F.... = Frame-level multithreading
 ..S... = Slice-level multithreading
 ...X.. = Codec is experimental
 ....B. = Supports draw_horiz_band
 .....D = Supports direct rendering method 1
 V.S... mpeg4                MPEG-4 part 2

In this example V.S... indicates that the encoder mpeg4 is a Video encoder and supports Slice-level multithreading.


See advanced nvenc encoder options in ffmpeg:

ffmpeg -h encoder=nvenc_h264

Encoder nvenc_h264 [NVIDIA NVENC H.264 encoder]:
    General capabilities: delay 
    Threading capabilities: none
    Supported pixel formats: yuv420p nv12 yuv444p
nvenc_h264 AVOptions:
  -preset            <int>        E..V.... Set the encoding preset (from 0 to 11) (default medium)
     default                      E..V.... 
     slow                         E..V.... hq 2 passes
     medium                       E..V.... hq 1 pass
     fast                         E..V.... hp 1 pass
     hp                           E..V.... 
     hq                           E..V.... 
     bd                           E..V.... 
     ll                           E..V.... low latency
     llhq                         E..V.... low latency hq
     llhp                         E..V.... low latency hp
     lossless                     E..V....
     losslesshp                   E..V....
  -profile           <int>        E..V.... Set the encoding profile (from 0 to 3) (default main)
     baseline                     E..V.... 
     main                         E..V.... 
     high                         E..V.... 
     high444p                     E..V.... 
  -level             <int>        E..V.... Set the encoding level restriction (from 0 to 51) (default auto)
     auto                         E..V.... 
     1                            E..V.... 
     1.0                          E..V.... 
     1b                           E..V.... 
     1.0b                         E..V.... 
     1.1                          E..V.... 
     1.2                          E..V.... 
     1.3                          E..V.... 
     2                            E..V.... 
     2.0                          E..V.... 
     2.1                          E..V.... 
     2.2                          E..V.... 
     3                            E..V.... 
     3.0                          E..V.... 
     3.1                          E..V.... 
     3.2                          E..V.... 
     4                            E..V.... 
     4.0                          E..V.... 
     4.1                          E..V.... 
     4.2                          E..V.... 
     5                            E..V.... 
     5.0                          E..V.... 
     5.1                          E..V.... 
  -rc                <int>        E..V.... Override the preset rate-control (from -1 to INT_MAX) (default -1)
     constqp                      E..V.... Constant QP mode
     vbr                          E..V.... Variable bitrate mode
     cbr                          E..V.... Constant bitrate mode
     vbr_minqp                    E..V.... Variable bitrate mode with MinQP
     ll_2pass_quality              E..V.... Multi-pass optimized for image quality (only for low-latency presets)
     ll_2pass_size                E..V.... Multi-pass optimized for constant frame size (only for low-latency presets)
     vbr_2pass                    E..V.... Multi-pass variable bitrate mode
  -surfaces          <int>        E..V.... Number of concurrent surfaces (from 0 to INT_MAX) (default 32)
  -cbr               <boolean>    E..V.... Use cbr encoding mode (default false)
  -2pass             <boolean>    E..V.... Use 2pass encoding mode (default auto)
  -gpu               <int>        E..V.... Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on. (from -2 to INT_MAX) (default any)
     any                          E..V.... Pick the first device available
     list                         E..V.... List the available devices
  -delay             <int>        E..V.... Delay frame output by the given amount of frames (from 0 to INT_MAX) (default INT_MAX)

See advanced h264_vaapi options:

ffmpeg -h encoder=h264_vaapi

Encoder h264_vaapi [H.264/AVC (VAAPI)]:
    General capabilities: delay 
    Threading capabilities: none
    Supported pixel formats: vaapi_vld
h264_vaapi AVOptions:
  -qp                <int>        E..V.... Constant QP (for P-frames; scaled by qfactor/qoffset for I/B) (from 0 to 52) (default 20)
  -quality           <int>        E..V.... Set encode quality (trades off against speed, higher is faster) (from 0 to 8) (default 0)
  -low_power         <int>        E..V.... Use low-power encoding mode (experimental: only supported on some platforms, does not support all features) (from 0 to 1) (default 0)
Copy link

Foxtrod89 commented Apr 4, 2018

Thx a lot, what is difference btw cuda and cuvid encoders?

Copy link

naikrovek commented May 9, 2018

Based on my limited knowledge of CUDA, it might perform a bit better for encoders that support threading, since the CPU is a CUDA device as well as the GPU. The nvenc (formerly cuvid) and nvdec acceleration are GPU-only and NVidia-only. CUDA will work on AMD or NVidia GPUs and any modern CPU, I believe.

Copy link

tnraro commented May 20, 2018

Specified rc mode is deprecated.

ll_2pass_quality -> cbr_ld_hq
ll_2pass_size -> cbr_hq
vbr_2pass -> vbr_hq
vbr_minqp -> (no replacement)

Copy link

Brainiarc7 commented Jun 8, 2018


The current valid modes are vbr_hq and the llhq presets.

Copy link

Limingxing00 commented Nov 15, 2018

Hello, I recently use ffmpeg's hevc_nvenc , the parameter in “ffmpeg -h encoder=hevc_nvenc” is similar to “ffmpeg -h encoder=nvenc_h264”.
These parameters make me feel very distressed. Does it have an official introduction? Or what other learning pathways?

Copy link

aphex3k commented Dec 7, 2018

How do I ensure that my output pixel format is yuv420p and not cuda, nv12 or yuv444p?

looking at my log it says cuda where I expect it to say yuv420p...

Stream #0:0: Video: h264 (h264_nvenc) (High) (avc1 / 0x31637661), cuda, 1920x1080 [SAR 1:1 DAR 16:9], q=18-23, 2000 kb/s, 29.97 fps, 30k tbn, 29.97 tbc

Update: I figured it out... My filter chain needs to convert to yuv420p before encoding the frame

I will leave this here in case anyone else stumbles across this: In my example I transcode a TV recording in mpeg2ts format to h.264 using the entire cuda pipeline along the way (for decoding, filtering and encoding).

ffmpeg  -hwaccel cuvid -c:v mpeg2_cuvid -i "${inFile}" -c:v h264_nvenc -vf yadif_cuda=0:-1:1,scale_npp=format=yuv420p,hwdownload,format=yuv420p -preset hq -profile:v high -level 4.2 -map 0:0 -map 0:a -c:a copy -map 0:s? -c:s copy -movflags +faststart  -qmin 18 -qmax 23 "${outFile}" 

Copy link

Brainiarc7 commented Dec 21, 2018


Please see this answer. It explains NVENC's internals across various GPU generations, and also why these options (for both the H264/AVC and HEVC encoders) are identical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment