Minimalist dynamic OBS studio build on Ubuntu 16.04 with Nvidia NVENC enabled in a stand-alone FFmpeg binary

Preamble:

Why is this necessary?

First, you may want to build this package without installing it as a system application, such that incase anything breaks, you can simply delete its’ installation directory and restart the build without breaking your running system. Handling dependencies on multi-user systems tends to be quite messy, and this is where the environment-modules system comes in handy: Flexible enough to allow the user to switch between multiple versions of the same application, with explicit control of environment variables and module dependencies loaded on demand, and even switchable on the fly (in TCL mode).

To start off: Build FFmpeg first!

First, prepare for the build and create the workspace directory:

cd ~/
mkdir ~/ffmpeg_sources
sudo apt-get -y update && apt-get dist-upgrade -y
sudo apt-get -y install autoconf automake build-essential libass-dev \
  libtool \
  pkg-config texinfo zlib1g-dev

Install dependencies for NVENC:

sudo apt-get -y install glew-utils libglew-dbg libglew-dev libglew1.13 \
libglewmx-dev libglewmx-dbg freeglut3 freeglut3-dev freeglut3-dbg libghc-glut-dev \
libghc-glut-doc libghc-glut-prof libalut-dev libxmu-dev libxmu-headers libxmu6 \
libxmu6-dbg libxmuu-dev libxmuu1 libxmuu1-dbg 

Now, prepare the target directory where FFmpeg will be installed:

sudo mkdir -p /apps/ffmpeg/dyn

Then take ownership of the target directory:

sudo chown -Rc $USER:$USER /apps/ffmpeg/dyn

Substitute ‘your_username’ with your logon name without the quotes, and when done, move to the next step đŸ˜‰

Build and deploy nasm: Nasm is an assembler for x86 optimizations used by x264 and FFmpeg. Highly recommended or your resulting build may be very slow. Note that we’re using the latest release candidate, and not the stable version as of the time of writing.

cd ~/ffmpeg_sources
wget http://www.nasm.us/pub/nasm/releasebuilds/2.14rc0/nasm-2.14rc0.tar.gz
tar xzvf nasm-2.14rc0.tar.gz
cd nasm-2.14rc0
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin"
make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean

Build and deploy libx264 dynamically: This library provides a H.264 video encoder. See the H.264 Encoding Guide for more information and usage examples. This requires ffmpeg to be configured with –enable-gpl –enable-libx264.

cd ~/ffmpeg_sources
wget http://download.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
tar xjvf last_x264.tar.bz2
cd x264-snapshot*
PATH="/apps/ffmpeg/git/bin:$PATH" ./configure --prefix="/apps/ffmpeg/dyn" --bindir="/apps/ffmpeg/dyn/bin" --enable-dynamic --disable-opencl
PATH="/apps/ffmpeg/dyn/bin:$PATH" make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean

Build and configure libx265: This library provides a H.265/HEVC video encoder. See the H.265 Encoding Guide for more information and usage examples.

sudo apt-get install cmake mercurial
cd ~/ffmpeg_sources
hg clone https://bitbucket.org/multicoreware/x265
cd ~/ffmpeg_sources/x265/build/linux
PATH="/apps/ffmpeg/dyn/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/apps/ffmpeg/dyn" -DENABLE_SHARED:bool=on ../../source
make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean

Build and deploy the libfdk-aac library: This provides an AAC audio encoder. See the AAC Audio Encoding Guide for more information and usage examples. This requires ffmpeg to be configured with –enable-libfdk-aac (and –enable-nonfree if you also included –enable-gpl).

cd ~/ffmpeg_sources
wget -O fdk-aac.tar.gz https://github.com/mstorsjo/fdk-aac/tarball/master
tar xzvf fdk-aac.tar.gz
cd mstorsjo-fdk-aac*
autoreconf -fiv
./configure --prefix="/apps/ffmpeg/dyn" --enable-shared
make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean

Deploy NVENC SDK:

Deploy NVENC SDK:

First, install Nvidia’s drivers:

Activate the proper repo:

sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update

Then install nvidia-367:

apt-get install nvidia-367 nvidia-367-dev -y
apt-get install nvidia-cuda-toolkit --install-recommends -y

At this stage, please reboot the node.

sudo systemctl reboot

Then proceed to download the Nvidia NVENC 7.0 SDK from the Nvidia Developer portal when the host is booted up:

We are using the NVENC 7.0 SDK from here. Sign up with the developer program to access the download page below.

Ensure that the SDK is downloaded to your ~/ffmpeg_sources directory (cd ~/ffmpeg_sources to be sure) so as to maintain the needed directory structure.

Extract and copy the NVENC SDK headers as needed:

Then navigate to the extracted directory:

unzip Video_Codec_SDK_7.0.1.zip
cd Video_Codec_SDK_7.0.1/Samples

From within the SDK directory, do:

sudo cp -vr common/inc/GL/* /usr/include/GL/
sudo cp -vr common/inc/*.h /usr/include/

When done,do:

cd ~/ffmpeg_sources
mv Video_Codec_SDK_7.0.1 nv_sdk

That will allow us to statically link to the SDK with ease, below.

Note that there may be a newer version of the SDK available at the time, please adjust as appropriate.

Building a static ffmpeg binary with the required options:

cd ~/ffmpeg_sources
git clone https://github.com/FFmpeg/FFmpeg -b master
cd FFmpeg
PATH="/apps/ffmpeg/dyn/bin:$PATH" PKG_CONFIG_PATH="/apps/ffmpeg/dyn/lib/pkgconfig" ./configure \
  --prefix="/apps/ffmpeg/dyn" \
  --enable-shared \
  --extra-cflags="-I/apps/ffmpeg/dyn/include" \
  --extra-ldflags="-L/apps/ffmpeg/dyn/lib" \
  --bindir="/apps/ffmpeg/dyn/bin" \
  --enable-cuda \
  --enable-cuvid \
  --enable-libnpp \
  --extra-cflags=-I../nv_sdk \
  --extra-ldflags=-L../nv_sdk \
  --enable-vaapi \
  --enable-gpl \
  --cpu=native \
  --enable-opengl \
  --enable-libspeex \
  --enable-openssl \
  --enable-libfdk-aac \
  --enable-libx264 \
  --extra-libs=libpthread \
  --enable-libx265 \
  --enable-nvenc \
  --enable-nonfree 
PATH="/apps/ffmpeg/dyn/bin:$PATH" make -j$(nproc) 
make -j$(nproc) install 
make -j$(nproc) distclean 
hash -r

If ~/bin is already in your path, you can call up ffmpeg directly.

Now that we’re done deploying FFmpeg, let us revert the build directory back to the root user:

sudo chown -Rc root:root /apps/ffmpeg/dyn

Now, generate a module file for ffmpeg:

module avail ffmpeg

------------------------ /usr/share/modules/modulefiles ------------------------
ffmpeg/dyn ffmpeg/git

Inspect the module file:

module show ffmpeg/dyn
-------------------------------------------------------------------
/usr/share/modules/modulefiles/ffmpeg/dyn:

conflict     ffmpeg/prod 
prepend-path     PATH /apps/ffmpeg/dyn/bin 
prepend-path     LD_LIBRARY_PATH /apps/ffmpeg/dyn/lib 
-------------------------------------------------------------------

Modulefile content:

#%Module1.0#####################################################################
##
## ffmpeg media transcoder modulefile
## By Dennis Mungai <dmngaie@gmail.com>
## February, 2018
##

# for Tcl script use only
set     appname         ffmpeg
set     version         dyn
set     prefix          /apps/${appname}/${version}
set     exec_prefix     ${prefix}/bin

conflict        ffmpeg/git

prepend-path    PATH            ${exec_prefix}
prepend-path    LD_LIBRARY_PATH ${prefix}/lib

Now, fetch the sources for obs-studio:

cd ~/source.build
git clone --recursive https://github.com/jp9000/obs-studio.git

Since we deployed FFmpeg as shown above, let us carry on with the build below:

Now, navigate to the downloaded sources:

cd obs-studio

Create a separate build directory:

mkdir build

And cd into it:

cd build

Load ffmpeg/dyn module (note that this was built dynamically, static builds will not work!)

module load ffmpeg/dyn

Now, configure your build:

cmake .. -DBUILD_CAPTIONS=1 -DCMAKE_COLOR_PROFILE=1 -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_INSTALL_PREFIX=/apps/obs-studio/git -DCMAKE_VERBOSE_MAKEFILE=ON -DUNIX_STRUCTURE=1 -DUSE_SSL=1 -DUSE_XDG=1

Then run make to build it:

time make -j$(nproc) VERBOSE=1

At this stage, create the target directory for its’ deployment (in my case, its under /apps , set it according to your selected Cmake installation prefix).

sudo mkdir -p /apps/obs-studio/git

Then make install to install it:

sudo make install -j$(nproc)

Generate a module file for the binary:

module avail obs-studio

------------------------ /usr/share/modules/modulefiles ------------------------
obs-studio/git

Modulefile contents:

#%Module1.0#####################################################################
##
## obs-studio screen recorder modulefile
## By Dennis Mungai <dmngaie@gmail.com>
## December, 2018
##

# for Tcl script use only
set     appname         obs-studio
set     version         git
set     prefix          /apps/${appname}/${version}
set     exec_prefix     ${prefix}/bin

# Make sure ffmpeg/dyn is loaded
# obs-studio needs ffmpeg/dyn as a dependency!
if { ![is-loaded ffmpeg/dyn] } {
    module load ffmpeg/dyn
}


prepend-path    PATH            ${exec_prefix}
prepend-path    LD_LIBRARY_PATH ${prefix}/lib

Note that in this module file, we declare ffmpeg/dyn as a dependency to this module because it was built based on this version.

Now, load the module by running:

module load obs-studio/git

And run the binary from the terminal by running:

obs

And the application will launch.

When done using the application, simply run:

module unload obs-studio/git

And it will be unloaded from your environment neatly.

Reasons for running a verbose build:

Useful for debugging, if any step of the build fails, you’ll identify the error and the step at which it stops at.

Why the environment-modules system?

It allows for neat separation of dependencies and multiple versions of the same application configured with different options, as the need may be. For instance, on the host machine, I have two ffmpeg versions. Without the environment modules system, it would not have been as trivial to deploy.

Categories Linux, Video Encoding articlesTags , , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this:
search previous next tag category expand menu location phone mail time cart zoom edit close