https://www.streaming-servers.com/

Script Transcoding Script H264 --> H265 / Retranscode H265 / Watermark

MwVTW

New Member
Member
Joined
Mar 26, 2020
Messages
15
Likes
8
Points
14
Hello everybody,

I would like to share with you my script for transcoding H264 content to H265 / HVEC and how to add watermarks. In addition, I will also show you how to re-transcode H265 content to add a watermark, for example.

The retranscoding of 4K material in particular took me tens of hours of testing to create a working script with the filters.

The complete tutorial including the code comes from me and was posted by me on the DEB.

I hope it will help one or the other!

The requirements:
- at least a Core i5 processor, comparatively AMD
- at least 8 GB of RAM
- An HDD with enough capacity
- an NVIDIA GPU: GTX 1060 3GB / 6GB, GTX 1070, 1080, Quadro P2000 etc. I wouldn't start with that.
- Installation of Ubuntu Server 18.04 as the basic system is required.

Step 1:
After installing the basic system and installing the latest updates, we install the CUDA Toolkit and the necessary requirements.
Code:
apt update
apt install autoconf automake build-essential cmake pkg-config texinfo wget yasm zlib1g-dev nasm
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.1.1/local_installers/cuda-repo-ubuntu1804-11-1-local_11.1.1-455.32.00-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1804-11-1-local_11.1.1-455.32.00-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu1804-11-1-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda

Step 2:
After the installation of CUDA took a few minutes, we build FFMPEG.
Code:
 #First of all we install a few requirements:
apt install libx264-dev libx265-dev libnuma-dev libfdk-aac-dev
cd / opt
git clone https://git.ffmpeg.org/ffmpeg.git
git clone https://github.com/FFmpeg/nv-codec-headers
cd nv-codec-headers && make install && cd ..
cd ffmpeg

#Now we're building the actual FFMPEG binary with libfdk_aac, cuda, h264 and h265 support

./configure --enable-cuda-sdk --enable-cuda --enable-cuvid --enable-nvenc --enable-gpl --enable-nonfree --enable-libx264 --enable-libfreetype --enable-libfdk -aac --enable-cuda-nvcc --enable-libnpp --extra-cflags = -I /usr/local/cuda/include --extra-ldflags = -L /usr/local/cuda/lib64
make -j4
make install

Now check your ffmpeg version:
Code:
 ffmpeg -version
#Output:
ffmpeg version N-98403-g04e06beb0a Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 7 (Ubuntu 7.5.0-3ubuntu1 ~ 18.04)
configuration: --enable-cuda-sdk --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --enable-gpl --enable-libx264 --enable-libfreetype --enable-libfdk- aac --enable-cuda-nvcc --enable-libnpp --extra-cflags = -I /usr/local/cuda /include --extra-ldflags = -L /usr/local/cuda/lib64

libavutil 56. 55.100 / 56. 55.100
libavcodec 58.94.100 / 58.94.100
libavformat 58.48.100 / 58.48.100
libavdevice 58.11.101 / 58.11.101
libavfilter 7. 86.100 / 7. 86.100
libswscale 5,800 / 5,800
libswresample 3. 8,100 / 3. 8,100
libpostproc 55.8.100 / 55.8.100
Now that the basic framework for transcoding is in place, you can start transcoding a film from MKV to MP4, for example.
With the variable $ f I define the file which is transcoded and with $ name the output. In the next step, CUDA is initiated and the input file is read.
This is where the actual transcoding begins. The hwdownload loads the frames into the GPU RAM, changes the pixel format to nv12 and uploaded frames
for further processing. Here the video stream 0 is selected with -c: v: 0 and codec H264 (for example) with the profile Main and the speed Slow with medium
Quality qmin to qmax transcoded into the YUV420P format. At the same time, the audio streams in German are selected and converted into the LIBFDK_AAC codec. It should be noted here that the audio stream 0 is converted to stereo at 48kbit/s and the audio stream 1 to 5.1 at 384kbit/s.

You can save the following script as transcode in /usr/local/bin.
Please do not forget to give the script the appropriate rights to execute it, such as chmod 777 /usr/local/bin/transcode
Code:
#!/bin/bash
f = "$ 1" # all args
name = "$ 2"
ffmpeg -y -loglevel verbose \
           -init_hw_device cuda = cuda \
           -hwaccel cuda \
           -filter_hw_device cuda \
           -hwaccel_output_format cuda \
           -i "$ f" \
          -flags -global_header \
          -filter_complex "[0: v] hwdownload, format = nv12, hwupload_cuda" \
          -c: v: 0 hevc_nvenc \
          -profile: v main \
          -preset slow \
          -qmin 28 \
          -qmax 30 \
          -format yuv420p \
          -map 0: m: language: ger -map 0: m: language: ger \
          -c: a: 0 libfdk_aac -ar: a 48000 \
          -channel_layout: a 5.1 -ab: a 640k
          -c: a: 1 libfdk_aac -ab: a 384k -ar 48000 \
          -sn "$ name" .mp4
Embodiment:
We have our film Avatar.264.DEB.mkv under /mnt/share/
This film is about 10GB in size.
Code:
cd /mnt/ share
transcode "Avatar.264.DEB.mkv" "Avatar.HVENC.Peters.Release"
The transcoding is completed after about 10-15 minutes.
Now you can use ls- l --block-size = m to check the size of the output file Avatar.HVENC.Peters.Release.mp4.
You will find that in the end the output will only be 2 ... a maximum of 3.5 GB without losing the quality of the image material.
You are welcome to experiment a little with the qmin and qmax. For me, however, these are very good values measured by the quality of the input file. For qmin and qmax:
The lower the value, the higher the bit rate -> the higher the bit rate, the better the picture -> the better the picture -> the larger the file. So in the extreme case it can end up being 30GB instead of originally 10GB ... only you don't win anything.

To add a little spice to everything here, I put my UHD script on top.
I've had really strong successes here for myself. I transcoded a good old classic with 49GB MKV to just under 8.9GB. And to be honest ... if I'm not sitting in front of the television with a magnifying glass, I don't see any difference.

The difference here is the pixel format yuv420p10le and the color space color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc.
If the settings are not available, the color tones are lost and are replaced by white. In this script, the metadata is set as to how the audio streams are named.
Code:
#!/bin/ bash
f = "$ 1" # all args
name = "$ 2"
        ffmpeg -y -loglevel verbose \
         -init_hw_device cuda = cuda \
         -hwaccel cuda \
         -filter_hw_device cuda \
         -hwaccel_output_format cuda -i "$ f" \
         -flags -global_header -filter_complex \
         "[0: v] hwdownload, format = p010le, hwupload_cuda" \
         -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc \
         -c: v hevc_nvenc -profile: v main10 -preset slow -qp 25 -format yuv420p10le \
         -map 0: m: language: ger -map 0: m: language: ger -map 0: m: language: ger -map 0: m: language: ger \
         -c: a: 1 copy -metadata: s: a: 0 title = "Original Audio" \
         -c: a: 2 libfdk_aac -ar: a 48000 -channel_layout: a 5.1 -ab: a 640k -metadata: s: a: 1 title = "AAC 5.1" \
         -c: a: 3 libfdk_aac -ab: a 384k -ar 48000 -metadata: s: a: 2 title = "AAC Stereo" \
         -c: a: 4 ac3 -ac 6 -ab 640k -metadata: s: a: 3 title = "AC3 5.1" \
         -sn "$ name" .mp4
A little info at the end:
With a few minor adjustments, ts streams can also be created and live streaming.
 

doc

Advance Member
Member
Joined
Dec 27, 2019
Messages
130
Likes
562
Points
104
Hello everybody,

I would like to share with you my script for transcoding H264 content to H265 / HVEC and how to add watermarks. In addition, I will also show you how to re-transcode H265 content to add a watermark, for example.

The retranscoding of 4K material in particular took me tens of hours of testing to create a working script with the filters.

The complete tutorial including the code comes from me and was posted by me on the DEB.

I hope it will help one or the other!

The requirements:
- at least a Core i5 processor, comparatively AMD
- at least 8 GB of RAM
- An HDD with enough capacity
- an NVIDIA GPU: GTX 1060 3GB / 6GB, GTX 1070, 1080, Quadro P2000 etc. I wouldn't start with that.
- Installation of Ubuntu Server 18.04 as the basic system is required.

Step 1:
After installing the basic system and installing the latest updates, we install the CUDA Toolkit and the necessary requirements.
[SPOILER = "CUDA Toolkit Installation"]

Bash:
apt update
apt install autoconf automake build-essential cmake pkg-config texinfo wget yasm zlib1g-dev nasm
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.1.1/local_installers/cuda-repo-ubuntu1804-11-1-local_11.1.1-455.32.00-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1804-11-1-local_11.1.1-455.32.00-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu1804-11-1-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda
[/SPOILER]

Step 2:
After the installation of CUDA took a few minutes, we build FFMPEG.
[SPOILER = "FFMPEG Repository Build"]
Bash:
 #First of all we install a few requirements:
apt install libx264-dev libx265-dev libnuma-dev libfdk-aac-dev
cd / opt
git clone https://git.ffmpeg.org/ffmpeg.git
git clone https://github.com/FFmpeg/nv-codec-headers
cd nv-codec-headers && make install && cd ..
cd ffmpeg

#Now we're building the actual FFMPEG binary with libfdk_aac, cuda, h264 and h265 support

./configure --enable-cuda-sdk --enable-cuda --enable-cuvid --enable-nvenc --enable-gpl --enable-nonfree --enable-libx264 --enable-libfreetype --enable-libfdk -aac --enable-cuda-nvcc --enable-libnpp --extra-cflags = -I /usr/local/cuda/include --extra-ldflags = -L /usr/local/cuda/lib64
make -j4
make install
[/SPOILER]

Now check your ffmpeg version:
Code:
 ffmpeg -version
#Output:
ffmpeg version N-98403-g04e06beb0a Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 7 (Ubuntu 7.5.0-3ubuntu1 ~ 18.04)
configuration: --enable-cuda-sdk --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --enable-gpl --enable-libx264 --enable-libfreetype --enable-libfdk- aac --enable-cuda-nvcc --enable-libnpp --extra-cflags = -I /usr/local/cuda /include --extra-ldflags = -L /usr/local/cuda/lib64

libavutil 56. 55.100 / 56. 55.100
libavcodec 58.94.100 / 58.94.100
libavformat 58.48.100 / 58.48.100
libavdevice 58.11.101 / 58.11.101
libavfilter 7. 86.100 / 7. 86.100
libswscale 5,800 / 5,800
libswresample 3. 8,100 / 3. 8,100
libpostproc 55.8.100 / 55.8.100
Now that the basic framework for transcoding is in place, you can start transcoding a film from MKV to MP4, for example.
With the variable $ f I define the file which is transcoded and with $ name the output. In the next step, CUDA is initiated and the input file is read.
This is where the actual transcoding begins. The hwdownload loads the frames into the GPU RAM, changes the pixel format to nv12 and uploaded frames
for further processing. Here the video stream 0 is selected with -c: v: 0 and codec H264 (for example) with the profile Main and the speed Slow with medium
Quality qmin to qmax transcoded into the YUV420P format. At the same time, the audio streams in German are selected and converted into the LIBFDK_AAC codec. It should be noted here that the audio stream 0 is converted to stereo at 48kbit/s and the audio stream 1 to 5.1 at 384kbit/s.

You can save the following script as transcode in /usr/local/bin.
Please do not forget to give the script the appropriate rights to execute it, such as chmod 777 /usr/local/bin/transcode
[SPOILER = "Transcoding"]
Bash:
#!/bin/bash
f = "$ 1" # all args
name = "$ 2"
ffmpeg -y -loglevel verbose \
           -init_hw_device cuda = cuda \
           -hwaccel cuda \
           -filter_hw_device cuda \
           -hwaccel_output_format cuda \
           -i "$ f" \
          -flags -global_header \
          -filter_complex "[0: v] hwdownload, format = nv12, hwupload_cuda" \
          -c: v: 0 hevc_nvenc \
          -profile: v main \
          -preset slow \
          -qmin 28 \
          -qmax 30 \
          -format yuv420p \
          -map 0: m: language: ger -map 0: m: language: ger \
          -c: a: 0 libfdk_aac -ar: a 48000 \
          -channel_layout: a 5.1 -ab: a 640k
          -c: a: 1 libfdk_aac -ab: a 384k -ar 48000 \
          -sn "$ name" .mp4
[/SPOILER]
Embodiment:
We have our film Avatar.264.DEB.mkv under /mnt/share/
This film is about 10GB in size.
[SPOILER = "Transcode example"]
Code:
cd /mnt/ share
transcode "Avatar.264.DEB.mkv" "Avatar.HVENC.Peters.Release"
[/ CODE]
[/ SPOILER]
The transcoding is completed after about 10-15 minutes.
Now you can use ls- l --block-size = m to check the size of the output file Avatar.HVENC.Peters.Release.mp4.
You will find that in the end the output will only be 2 ... a maximum of 3.5 GB without losing the quality of the image material.
You are welcome to experiment a little with the qmin and qmax. For me, however, these are very good values measured by the quality of the input file. For qmin and qmax:
The lower the value, the higher the bit rate -> the higher the bit rate, the better the picture -> the better the picture -> the larger the file. So in the extreme case it can end up being 30GB instead of originally 10GB ... only you don't win anything.

To add a little spice to everything here, I put my UHD script on top.
I've had really strong successes here for myself. I transcoded a good old classic with 49GB MKV to just under 8.9GB. And to be honest ... if I'm not sitting in front of the television with a magnifying glass, I don't see any difference.

The difference here is the pixel format yuv420p10le and the color space color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc.
If the settings are not available, the color tones are lost and are replaced by white. In this script, the metadata is set as to how the audio streams are named.
[SPOILER = "2160p Script"]
[CODE=bash]
#!/bin/ bash
f = "$ 1" # all args
name = "$ 2"
        ffmpeg -y -loglevel verbose \
         -init_hw_device cuda = cuda \
         -hwaccel cuda \
         -filter_hw_device cuda \
         -hwaccel_output_format cuda -i "$ f" \
         -flags -global_header -filter_complex \
         "[0: v] hwdownload, format = p010le, hwupload_cuda" \
         -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc \
         -c: v hevc_nvenc -profile: v main10 -preset slow -qp 25 -format yuv420p10le \
         -map 0: m: language: ger -map 0: m: language: ger -map 0: m: language: ger -map 0: m: language: ger \
         -c: a: 1 copy -metadata: s: a: 0 title = "Original Audio" \
         -c: a: 2 libfdk_aac -ar: a 48000 -channel_layout: a 5.1 -ab: a 640k -metadata: s: a: 1 title = "AAC 5.1" \
         -c: a: 3 libfdk_aac -ab: a 384k -ar 48000 -metadata: s: a: 2 title = "AAC Stereo" \
         -c: a: 4 ac3 -ac 6 -ab 640k -metadata: s: a: 3 title = "AC3 5.1" \
         -sn "$ name" .mp4
[/ CODE]
[/ SPOILER]
A little info at the end:
With a few minor adjustments, ts streams can also be created and live streaming.
No need to instal CUDA, just regular driver is enough.
replace
Bash:
make -j4
with
Bash:
make -j$(nproc)
some people have more then 4 cores
 
Last edited:

MwVTW

New Member
Member
Joined
Mar 26, 2020
Messages
15
Likes
8
Points
14
You indeed need CUDA for GPU Transcoding and using filter_graph.
Yes of course, thanks for your correction about the cores.
 
Place your Business Ad here !
Top