This is my current command for resizing videos (1080p) from 2GB to 300MB, but it takes a lot of time:
mkdir newfiles
for %%a in ("*.mp4") do ffmpeg -i "%%a" -c:v libx264 -preset slow -crf 21 -c:a aac -b:a 128k -vf scale=678:-2 "newfiles\%%~na.mp4"
pause
I tried nvenc with my NVIDIA GTX1070:
mkdir newfiles
for %%a in ("*.mp4") do ffmpeg -i "%%a" -c:v h264_nvenc -preset slow -c:a aac -b:a 128k -vf scale=678:-2 "newfiles\%%~na.mp4"
pause
Output size is always 3⨉ or 5⨉ the original size – nvenc does not use -crf
.
So how do I use nvenc with ffmpeg to convert/resize a video with high quality and small size? Should I use the GPU for encoding?
Best Answer
For CRF-based encodes, pass the following arguments in the snippet below to FFmpeg:
Of course, you'll need to adjust for target bit rates and a fixed
cq
value. 19 is the recommended setting as its' visually identical to 0, yet preserves good compression trade off to file size. See this write-up for more on what CRF does.Note that the
-cq
scale is logarithmic, meaning that 0 is essentially lossless and 51 would be the absolute worst.Quality can be further improved upon by adding options such as B-frames (limit this to 3, at most, and this requires the H.264 Main profile and above. Baseline profiles do not support B-frames. To do this, pass
-bf {uint}
to the video encoder, such that-bf:v 4
would result in the encoder using 4 B-frames.The key parts here are the
-cq:v 19
and the-rc:v vbr_hq
arguments, which allow you to tune the encoder with both a preset variable bitrate and a maximum allowable bitrate (-b:v
and-maxrate:v
) while adhering to a CRF value of 19.And now, small notes about NVENC, and tuning it for high quality encodes:
NVENC, like any other hardware-based encoder, has several limitations, and in particular with HEVC, here are the known limitations:
On Pascal:
For HEVC encodes, the following limitations apply:
Turing has all the enhancements available to Pascal, with the addition of B-frame support for HEVC and the ability to use B-frames as a reference. See this answer for an example on this capability.
And on Maxwell Gen 2 (GM200x series GPUs):
HEVC encoding lacks the following features:
The impact here for Maxwell is that motion heavy scenes with HEVC under constrained bitrates may suffer from artifacting (blockiness) due to the missing lookahead functions and adaptive sample offset (SAO) loop filtering capabilities. Pascal has somewhat improved on this capability, but depending on the version of the SDK that the video encoder was built with, not all features may be available.
For instance, weighted prediction mode for H.264 encodes on Pascal requires NVENC SDK 8.0x and above, and this encode mode will also disable B-frame support. Likewise, the combination of hardware-based scalers running off the Nvidia Performance Primitives (NPP) with NVENC may introduce performance improvements with video scaling applications at the cost of scaling artifacting, particularly with upscaled content. The same also impacts the video encode pipeline as NPP's scaling functions run off the CUDA cores on the GPU, and as such, the performance impact introduced by the extra load should be analyzed on a case-by case basis to determine if the performance-quality trade-off is acceptable.
Keep this in mind: A hardware-based encoder will always offer somewhat lesser customization than an equivalent software-based implementation, and as such, your mileage and acceptable output quality will always differ.
And for your reference:
With FFmpeg, you can always refer to an encoder's settings for customization by:
So, for NVENC-based encoders, you can run:
You can also see all the NVENC-based encoders and NPP-based scalers (if built as such) by running:
Sample output on my testbed: