Carlos Dieste
Carlos Dieste

Reputation: 21

Converting H265 to MP4 Using FFMPEG and GPU

I am trying to convert a video ouput from a camera to MP4 but it is using too much CPU (However we can not limit the program as we need this to be done fast) so we thought using some GPU might be an option.

At the moment we were using this so far:

ffmpeg.exe -i "old.mkv" "new.mp4"

Tried using:

ffmpeg.exe -hwaccel cuvid  -i "old.mkv" "new.mp4"

However it throws an error:

"Pixel format 'yuvj420p' is not supported"

There is nothing I can do with the video input but I am looking for alternatives to reduce CPU use.

The video encode is HEVC.

I thought GPU might be a good idea but this seems to be incompatible with the video input.

Any ideas of how to make ffmpeg run on GPU or alternatives for lowering the CPU usage?

Upvotes: 1

Views: 16063

Answers (3)

Hirusha Adikari
Hirusha Adikari

Reputation: 149

This is what worked for me: (NVIDIA GTX 1650 SUPER)

ffmpeg -hwaccel_device 0 -hwaccel cuda -i "input.mkv" -c:v h264_nvenc -preset slow "output.mp4"

device is set to 0 because that is the first GPU in your computer. if you have more than one graphics card, you can change the number. (starting with 0)

(yes, you can do both decoding and encoding with your nvidia graphics card)

NVENC and NVDEC are NVIDIA's hardware-accelerated encoding and decoding APIs. They used to be called CUVID. They can be used for encoding and decoding on Windows and Linux. FFmpeg refers to NVENC/NVDEC as CUDA.

NVENC

NVENC can be used for H.264 and HEVC encoding. FFmpeg supports NVENC through the h264_nvenc and hevc_nvenc encoders. In order to enable it in FFmpeg you need:

  1. A ​supported GPU

  2. Supported drivers for your operating system

​3. The NVIDIA Codec SDK or compiling FFmpeg with --enable-cuda-llvm ffmpeg configured with --enable-nvenc (default if the drivers are detected while configuring)

Note: FFmpeg uses its own slightly modified runtime-loader for NVIDIA's CUDA/NVENC/NVDEC-related libraries. If you get an error from configure complaining about missing ffnvcodec, ​this project is what you need. It has a working Makefile with an install target: make install PREFIX=/usr. FFmpeg will look for its pkg-config file, called ffnvcodec.pc. Make sure it is in your PKG_CONFIG_PATH.

This means that running the following before compiling ffmpeg should suffice:

git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
make
sudo make install
After compilation, you can use NVENC.

Usage example:

ffmpeg -i input -c:v h264_nvenc -profile high444p -pixel_format yuv444p -preset default output.mp4

You can see available presets, other options, and encoder info with ffmpeg -h encoder=h264_nvenc or ffmpeg -h encoder=hevc_nvenc.

Note: If you get the No NVENC capable devices found error make sure you're encoding to a supported pixel format. See encoder info as shown above.

NVDEC/CUVID NVDEC offers decoders for H.264, HEVC, MJPEG, MPEG-1/2/4, VP8/VP9, VC-1. Codec support varies by hardware (see the ​GPU compatibility table).

Note that FFmpeg offers both NVDEC and CUVID hwaccels. They differ in how frames are decoded and forwarded in memory.

The full set of codecs being available only on Pascal hardware, which adds VP9 and 10 bit support. The note about missing ffnvcodec from NVENC applies for NVDEC as well.

Sample decode using CUDA:

ffmpeg -hwaccel cuda -i input output

Sample decode using CUVID:

ffmpeg -c:v h264_cuvid -i input output

Full hardware transcode with NVDEC and NVENC:

ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input -c:v h264_nvenc -preset slow output

If ffmpeg was compiled with support for libnpp, it can be used to insert a GPU based scaler into the chain:

ffmpeg -hwaccel_device 0 -hwaccel cuda -i input -vf scale_npp=-1:720 -c:v h264_nvenc -preset slow output.mkv

The -hwaccel_device option can be used to specify the GPU to be used by the hwaccel in ffmpeg.

More info: https://trac.ffmpeg.org/wiki/HWAccelIntro#CUDANVENCNVDEC

Upvotes: 3

Stef
Stef

Reputation: 85

This bash script should work for Nvidia GPUs. I have tested this with a 1050 Ti which from the nvidia-gpu-support-matrix seems like the first generation that had a NVDEC chip for accelerated decoding a NVENC chip for accelerated encoding.

#! /usr/bin/sh
# requires a properly compiled ffmpeg; CUDA and a supported GPU from Nvidia https://developer.nvidia.com/video-encode-decode-gpu-support-matrix

# Take in some inputs, this will not check the validity
# there are many more rendering options available.

printf "input file: "
read INPUT
printf "output file: "
read OUTPUT
printf "choose audio [codec ac3, aac, etc]: "
read AUDIO
printf "video resolution [1920x1080, 1024x720, etc]: "
read RESOLUTION
printf "video bitrate [1200~48000]: "
read V_BITRATE

ffmpeg -hide_banner -hwaccel cuvid -c:v hevc_cuvid -resize $RESOLUTION -autorotate 0 -i $INPUT -c:a $AUDIO -c:v h264_nvenc -preset slow -b:v $V_BITRATE $OUTPUT

Upvotes: 0

szatmary
szatmary

Reputation: 31110

There is really no such thing as GPU encoding. SOME GPU come with a video encoding chip on board, some don't. You need to know what one is in your system and if ffmpeg is compiled to support it. Look into NVENC (if Nvidia GPU) VCE (if AMD) or quicksync (if Intel). -hwaccel cuvid if for accelerated decoding (not encoding).

Upvotes: 0

Related Questions