This tutorial deals with video resizing using GPU accelerated libraries supported by FFMPEG in Ubuntu 16.04.

Introduction

FFmpeg is one of the most famous multimedia frameworks which is widely used for processing videos. The popular x264 is the one which is widely used as the encoder; however, it is not super fast! The latest NVIDIA GPUs contain a hardware-based video encoder called NVENC which is much faster than traditional ones. To be able to utilize this GPU-accelerated encoder, FFmpeg must be installed with NVENC support. The full documentation of FFmpeg integrated with NVIDIA can be found at here. Documentation on NVENC can be found here. Moreover, The NVENC programming guide can be found here. The full code for this tutorial is available at this GitHub repository.

In this tutorial, the primary goal is to show how to do resize a video with GPU-accelerated libraries in Linux. In this tutorial, we do not use the terminal commands directly for employing the FFmpeg with NVENC support. Instead, the python interface is being used to run commands in the terminal. This can be done using subprocess python module. This module is employed for execution and dealing external commands, intended to supersede the os.sys module. The trivial method os its usage will be explained in this tutorial. Please refer to this documentation for further details.

This tutorial assumes that the FFmpeg is already installed because it is based on NVENC support. The installation guide can be found in FFMPEG WITH NVIDIA ACCELERATION ON UBUNTU LINUXdocumentation provided by NVIDIA.

Data Indicator

This tutorial is customized for processing multiple videos. The assumption is that the full path of each video is stored in a .txt file in line-by-line format. The example of the “.txt” file is as below:

Linkedin
Figure 1: The format of .txt file.

As guidance if a recursive search for specific files in a directory and its subdirectories with extension “.mov” is desired, the following method in the command line is useful and it saves the output as a “.txt” file:

find /absolute/path/to/directory/to/be/search -type f -name "*.mov" > /absolute/path/to/save/the/output/textfile.txt

Video Resize

From now on the assumption is that the “.txt” file is ready and well-formatted. The python script for processing videos is as below:

import subprocess
import os
import sys
# Pre...
textfile_path = 'videos.txt'
output_dir_base = 'PATH/TO/OUTPUT'
# Read the text file
with open(textfile_path) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
files_list = [x.strip() for x in content]
# Transpose 90 degree & Clockwise
# It already save the video file using the named defined by output_name.
for file_num, file_path_input in enumerate(files_list, start=1):
    # Get the file name without extension
    file_name = os.path.basename(file_path_input)
    ID = file_name.split('_')[1]
    raw_file_name = os.path.basename(file_name).split('.')[0]
    file_dir_input = os.path.dirname(file_path_input)
    file_dir_output = output_dir_base + '/' + ID
    if not os.path.exists(file_dir_output):
        os.makedirs(file_dir_output)
    file_path_output = file_dir_output + '/' + raw_file_name + '.mkv'
    print('processing file: %s' % file_path_input)
    subprocess.call(
        ['ffmpeg', '-y', '-i', file_path_input, '-filter_complex', 
        'nvresize=1:s=540x960:readback=0[out0]', '-map', '[out0]',
         '-acodec', 'copy', '-r', '30', '-vcodec', 'nvenc', '-b:v', '3M', file_path_output])
print('file %s saved' % file_path_output)

I – Overall Code Description

The videos.txt file is saved in the absolute path. Lines 8-12 of the code reads the “.txt” file and stores each line as an item of a list called files_list. The loop starts at line 16 process each file with the subprocess.call command. In each loop, the folder of the input file is found, and the output file will be stored in the same directory but with the different naming convention which is explained by the comments in the code. Each, in the subprocess.call command in the python is correspondent to an empty space in the terminal. As an example the correspondent shell command is as below:

ffmpeg -i file_path -filter:v transpose=-1 -vcodec nvenc -preset slow -b:v 5M -acodec copy output_file_path

II – FFmpeg Encoder

The command executed by FFmpeg needs to be described. Each of the elements started by – are calling specific operations and the command follows by them perform the desired process. For example -vcodec indicator will specify the codec to be used by FFmpeg and nvenc which follows by that point to the codec. More details can be found at FFmpeg Filters Documentation. The following Table, summarize the indicators:

The -vf is the main command which its full documentation is available here and it has the filter options.

Code Execution

In order to run the python file we go to the terminal and execute the following:

python /absolute/path/to/python/file

As a consideration, if we are working on any specific virtual environment it has to be activated at first.

Working in Bash Shell

A similar approach can be employed in the terminal too. Running commands in Terminal can be much faster than Python. So it is useful to have an idea of how to do it. Consider the following commands:

for i in **/*.mov; do
> base={i%.mov}; > ffmpeg -y -i file_path_input -filter_complex nvresize=1:s=540x960:readback=0[out0] -map [out0] -acodec copy -r 30 -vcodec nvenc -b:v 3M base={i%.mkv};
> done

By the assumption that the globstar is enabled (in order to make sure about that, the command of shopt -s globstar can be executed in the terminal.), the above command find all the files with the “.mov” extension in the current directory recursively and after desired processing save them in place with the “.mkv” extension. The advantage of globstar is that it is recursive and robust in cases that there is white space in a file or directory name. The command can be altered arbitrarily to read the data from a text file and do the processing.

Summary

This tutorial demonstrated how to process a video and individually resizing that using FFmpeg and Nvidia GPU accelerated library called NVENC. The advantage of using the Python interface is to parse the .txt file and looping through all files easily. Moreover, it enables the user with options which are more complicated to be directly employed in the terminal environment.


0

Sina Torfi

Currently, as a CS Ph.D. student, I'm a research assistant at Virginia Tech. My research is mainly about Machine Learning & Deep Learning and their applications in Computer Vision and NLP. I'm interested in developing software packages and open-source projects.

Leave a Reply

avatar
  Subscribe  
Notify of
Tweet
Share
Pin
Share