How to Use scale_npp Filter in FFmpeg for NVIDIA GPUs

The scale_npp filter in FFmpeg provides hardware-accelerated video scaling by leveraging the NVIDIA Performance Primitives (NPP) library directly on NVIDIA GPUs. This guide explains how to properly configure and use the scale_npp filter within an end-to-end GPU processing pipeline—incorporating hardware decoding (NVDEC) and hardware encoding (NVENC)—to achieve maximum throughput without CPU-GPU memory transfer bottlenecks.

Prerequisites

To use scale_npp, your FFmpeg build must be compiled with the following flags enabled:

  • --enable-cuda-nvcc (or --enable-cuda-llvm)
  • --enable-libnpp
  • --enable-nvenc
  • --enable-nvdec

You must also have compatible NVIDIA drivers and the CUDA toolkit installed.

Basic End-to-End Hardware Pipeline

To maximize performance, you should keep the decoded video frames entirely within GPU memory (VRAM). This requires using -hwaccel cuda along with -hwaccel_output_format cuda before the input file.

Here is the standard command for scaling a video to 1080p:

ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 \
-vf "scale_npp=1920:1080" \
-c:v h264_nvenc -c:a copy output.mp4

In this command:

  • -hwaccel cuda -hwaccel_output_format cuda: Decodes the input video using NVDEC and keeps the uncompressed frames in CUDA surface memory.
  • -vf "scale_npp=1920:1080": Scales the CUDA frames to 1920x1080 resolution on the GPU.
  • -c:v h264_nvenc: Encodes the scaled frames directly using NVENC without copying them back to system RAM.

Choosing an Interpolation Algorithm

The scale_npp filter supports multiple scaling algorithms via the interp_algo parameter. Depending on whether you are upscaling or downscaling, you can choose an algorithm that balances speed and visual quality:

  • nn: Nearest neighbor (fastest, lowest quality)
  • linear: Bilinear
  • cubic: Bicubic
  • lanczos: Lanczos (ideal for high-quality upscaling)
  • super: Super-sampling (recommended specifically for downscaling)

Example using Lanczos scaling:

ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 \
-vf "scale_npp=1280:720:interp_algo=lanczos" \
-c:v h264_nvenc -c:a copy output.mp4

Example using Super-sampling for downscaling to 480p:

ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 \
-vf "scale_npp=854:480:interp_algo=super" \
-c:v h264_nvenc -c:a copy output.mp4

Preserving Aspect Ratio

To maintain the input video's aspect ratio, set one dimension explicitly and use -1 (or -2 to ensure dimensions remain divisible by 2 for the encoder) for the other dimension:

ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 \
-vf "scale_npp=1920:-2" \
-c:v h264_nvenc -c:a copy output.mp4

Scaling from a CPU Decoded Source

If your input codec is not supported by NVDEC, you can decode the stream using the CPU, upload the raw frames to GPU memory with hwupload_cuda, and then apply scale_npp:

ffmpeg -i input.mkv \
-vf "hwupload_cuda,scale_npp=1280:720" \
-c:v hevc_nvenc -c:a copy output.mp4

While this method is slower than a full hardware pipeline due to the PCIe bus transfer overhead from system RAM to VRAM, it still offloads the computationally expensive scaling and encoding stages to the GPU.