Register for the iXsystems Community to get an ad-free experience and exclusive discounts in our eBay Store.

[How-to] Install ffmpeg in a jail

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
** Updated 2020 May with FreeNAS 11.3 and latest libraries **

I wanted to install a custom build of ffmpeg on my FreeNAS to do long transcoding tasks and not tie up my laptop for days at a time. It took three days to figure it out as there were a lot of hurdles to overcome (and some peculiarities of FreeBSD), so I thought I would share the process for the one or two other people in the world who want to do this ;). I've written it assuming knowledge of basic FreeNAS tasks like accessing by SSH, but for someone who has never used a jail. I'm really starting to appreciate jails because, when I screwed things up (many times), I just deleted the jail and started over. No harm to the main FreeNAS or other jails.

FFmpeg is a powerful, versatile media editing program, used in products like Plex, Kodi, and VLC. It is often used in servers for on-the-fly transcoding to serve videos, but the use intended here is remuxing/transcoding to produce high-quality, smaller files with desired container format and codecs. This installation process is set up to build it with few very good encoders (fdk_aac for audio and x264 and x265 for video), but you can build it with almost anything. It builds the current master source of ffmpeg, which is needed to get support for the most part.

Newer applications and libraries seem to always add new build tools, dependencies and methods. This is completely updated and uses only the built-in compiler clang. To make it simpler and easier to maintain, I dropped libass as part of the build. In all the years I have been building ffmpeg with libass, I have never once used it, but it is a royal pain with all the endless dependencies. However, I am keeping the libraries freetype, fontconfig, and fribidi, because they allow full use of the drawtext filter, which is handy if you want to put timestamps or any other text on the video.

The instructions below differentiate between the
  • first build (# First time) and
  • subsequent updates (# Later times). Don't get them mixed up.
First, in the webGUI, make a jail without a plugin (Jails > Add Jail); call it ffmpeg. Then SSH into FreeNAS and enter the jail:
Code:
sudo iocage console ffmpeg

############################
# FIRST TIME ONLY
############################
# freetype2 gets installed with fontconfig
pkg install curl git mercurial yasm nasm bash cmake gmake autoconf autotools fontconfig fribidi rsync
bash  # enter the bash shell
#  Make bash the default shell:
chsh
#  This invokes the vi editor to make the change. If you don't use it
#  regularly, read elsewhere how to use vi. Beside 'Shell:' enter '/usr/local/bin/bash' and save.
# Make a link to bash in /bin so shell scripts can find it:
ln -s /usr/local/bin/bash /bin/bash
# Set some stuff that gets read whenever you login.  Type 'ee root/.profile' and add in these lines:
# This gives you an alias 'll' for a full long directory listing
alias ll='ls -lahp'
# These set clang as default compiler for most things.
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
# This lets your system find the new man pages
export PATH=$PATH:/usr/local/share
# This allows ffmpeg ./configure to find things through pkg-config
export PKG_CONFIG_PATH=/usr/local/lib:/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig

Save the file (Esc, Enter, Enter). Read that file in so it takes effect now by typing source .bashrc (All first time only)

# Later times, instead of install using pkg, just update/upgrade:
pkg update # updates pkg list
pkg upgrade # updates all installed pkgs


Now we're ready to download source files and start building them. We'll
use three directories: PAKS for the source files, BUILD, to do the building
and make a mess, and TARGET to put the resulting files. Then you can
choose to actually install only ffmpeg. Every time:
Code:
PAKS=/usr/local/ffmpeg/packages
BUILD=/usr/local/ffmpeg/build
TARGET=/usr/local/ffmpeg/target
export PATH=$PATH:${TARGET}/bin

# Some earlier libraries interfere (if present) so nuke them
rm /usr/local/lib/libavcodec* /usr/local/lib/libx2*

# First time only:
mkdir ${PAKS}
# First time, or every time if you choose to delete these directories after building:
mkdir ${BUILD} ${TARGET}

##############################
#  Update libraries and ffmpeg
#  The git/hg line pulls into the appropriate directory, or (||),
#  if error (like directory doesn't exist), clone a new one.
#  Using rsync to copy to BUILD  with archive mode
#  (recursive, copy symlinks, preserve permissions, preserve mod. times,
#  preserve owner/group) and deleting other files on receiving side.
##############################

cd $PAKS
git -C fdk-aac pull 2> /dev/null || git clone --depth 1 https://github.com/mstorsjo/fdk-aac
rsync -a --delete $PAKS/fdk-aac/ $BUILD/fdk-aac/

git -C pkg-config pull 2> /dev/null || git clone https://anongit.freedesktop.org/git/pkg-config
rsync -a --delete $PAKS/pkg-config/ $BUILD/pkg-config/

git -C x264 pull 2> /dev/null || git clone http://git.videolan.org/git/x264.git
rsync -a --delete $PAKS/x264/ $BUILD/x264/

hg pull --update x265 --repository x265 || hg clone http://hg.videolan.org/x265 x265
rsync -a --delete $PAKS/x265/ $BUILD/x265/

git -C ffmpeg pull 2> /dev/null || git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
rsync -a --delete $PAKS/ffmpeg/ $BUILD/ffmpeg/

############################
# Build/compile.  As you pull above, note which ones
# have updates.  Only need to build those unless you
have deleted BUILD and TARGET
############################

#  FDK-AAC
cd $BUILD/fdk-aac
# There is no configure file anymore so have to make it with autoreconf
autoreconf -fiv && \
./configure --prefix="$TARGET" --disable-shared && \
make && \
make install

#  PKG-CONFIG
# No need to rebuild this each time
cd $BUILD/pkg-config
./autogen.sh --with-internal-glib --prefix="$TARGET" --exec-prefix="$TARGET"
make install clean

# Help pkg config find the files it needs in our weird spot
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$TARGET/lib/pkgconfig

#  X264
cd $BUILD/x264
./configure --prefix=$TARGET --enable-static --enable-pic
gmake
gmake install clean

#  X265
cd $BUILD/x265/build/linux

    #######################
    #  x265: Editing multilib.sh
    #######################
#  multilib.sh is a script that will build x265 with 8-, 10-, and 12-bit capability.
#  We have to specify the clang compiler; this process pays no attention to the
#  variables we set before.  Also set the install prefix and change the libtool option.
#  The only way I know how is to edit the script.
#  See https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
#  So:
ee multilib.sh

#  Under 'cd 12bit', after 'cmake', insert with no line breaks:
-D CMAKE_C_COMPILER=/usr/bin/clang -D CMAKE_CXX_COMPILER=/usr/bin/clang++

# Under 'cd ../8bit', after 'cmake', insert
-DCMAKE_INSTALL_PREFIX=/usr/local/ffmpeg/target/

# on same line, after ../../../source, add
-DENABLE_SHARED=OFF

# Optional: Add '-j <cores>' to all the make commands,
# replacing <cores> with the number of cores in your processor

# Near end of the script is an if/then/else.
# It results in using libtool, but the libtool we have doesn't work as expected.
# The alternative, GNU ar, does work.  So either edit out the if/then/else, or
# make the first 'if' have an OR to recognize Linux OR FreeBSD.
# That would look like this:
if [ "$uname" = "Linux" ] | [ "$uname" = "FreeBSD" ]

# Save the edited script in case $BUILD or $BUILD/x265 are deleted
mv multilib.sh multilib_edited.sh
cp -iv multilib_edited.sh $PAKS/x265/build/linux/

    #######################
    #  x265: Continue
    #######################
# To re-use a previously saved, edited script:
cp -iv $PAKS/x265/build/linux/multilib_edited.sh $BUILD/x265/build/linux/

# Then release the dogs.  This one takes quite a while.  Smoke 'em if you got 'em. ;-)
./multilib_edited.sh
cd 8bit  # the complete build gets put here
make install

# Also so pkg-config can easily find the library in future if you rebuild ffmpeg but x265 hasn't changed.
cp -v ${TARGET}/lib/libx265* /usr/local/lib

#  FFMPEG

cd $BUILD/ffmpeg

export  CFLAGS="-I${TARGET}/include -I/usr/local/include -I/usr/include"
export  LDFLAGS="-L${TARGET}/lib -L/usr/local/lib -L/usr/lib"
export PKG_CONFIG_PATH=${TARGET}/lib:$TARGET/lib/pkgconfig:${PKG_CONFIG_PATH}

./configure prefix=$TARGET --cc=/usr/bin/clang --extra-cflags="-I$TARGET/include" \
--extra-ldflags="-L$TARGET/lib" --extra-libs=-lpthread \
--pkg-config-flags="--static" --enable-static --disable-shared \
--enable-libfdk-aac --enable-libx264 --enable-libx265 \
--enable-libfreetype --enable-libfontconfig --enable-libfribidi \
--enable-nonfree --enable-gpl --enable-version3 --enable-hardcoded-tables \
--enable-avfilter --enable-filters --disable-outdevs --disable-network 


# Optional: Add '-j <cores>' to the first gmake command,
# replacing <cores> with the number of cores in your processor
gmake
gmake install

# REAL INSTALL (don't need the man3 docs)
cp -v ${TARGET}/bin/* /usr/local/bin
cp -v ${TARGET}/share/man/man1/* /usr/local/share/man/man1


You can establish storage for ffmpeg (a folder for ffmpeg to do it's work). I call my storage folder FFstor outside the jail, ffstor inside. First create the folder outside the jail the usual way.
Then, in Jails, in the ffmpeg options menu, select 'Mountpoints';
Source: mnt/<Pool>/<Dataset>/FFstor.
Destination: /media/ffstor (inside the jail).
Select the boxes to create the directory in the jail and mount it.

Actually using ffmpeg is a much bigger learning process, and involves learning a lot about video, but here's a command to get you started. It takes a big old movie file called "in.wmv" using crappy old codecs. It converts the video to x265 (the latest and most efficient codec, though not in terms of encoding time or decoding horsepower required) at a bit rate of 2750 kB/second (enough for 1080p), converts the audio to fdk-aac (the best and most versatile aac encoder) at 256 kB/second (plenty for stereo; you might want to double it for surround sound), and outputs it in a mp4 container. It uses 2-pass encoding for the video, giving better quality than a single pass, and uses the default medium (speed) preset. For a 2-hour 1080p movie, this takes about a day and a half on my low-powered processor. Your mileage will probably be better.
Code:
cd /media/ffstor
ffmpeg -i in.wmv -an -sn -c:v libx265 -preset slow -b:v 3000k -x265-params pass=1 -f m4v -y /dev/null && \
ffmpeg -i in.wmv -c:a copy -c:s copy -c:v libx265 -preset slow -b:v 3000k -x265-params pass=2 -y out2.m4v 
[/CODE]
 
Last edited:

Joshua Parker Ruehlig

Wizened Sage
Joined
Dec 5, 2011
Messages
5,949
Why couldn't you just do the following to compile ffmpeg from ports?
Code:
cd /usr/ports/multimedia/ffmpeg
make install clean
 

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
You could, and honestly it's not a bad option. The ports installation begins with a dialogue that allows you to choose the libraries/codecs you want to build it with, and the codecs I suggested are all there to be chosen. It requires significantly less command-line input.

The advantages of building it yourself are:
  • It is faster. The instructions I gave above can be done in about an hour, most of it wait time. I started the ports process over 4 hours ago as an experiment and it is still cranking. You have to babysit it to hit enter to the dialogues every time it wants to install something else. There are literally dozens of packages, most installed from source.
  • There is less stuff installed. I don't recognize most of the things the ports process installs. The jail ends up 5-6 times larger than when you build it yourself.
  • You get the current ffmpeg. As mentioned in the post, if you want help from ffmpeg-users, they want you to be using the current git master, not a release. It is actively developed. To be fair, ports does install the latest release and really seems to keep up with them, so that is probably not much of an issue.
  • You can be sure to get the latest versions of the libraries. Here are the latest ones with do-it-yourself vs. the ports process. Ports is up-to-date on some and not far behind on others.
    • yasm 1.3 vs. 1.2
    • fdk-aac 0.1.4 for both (nice!)
    • x264 0.148 vs. o.144
    • x265 1.8 for both (that's nice!)
  • You get that do-it-yourself satisfaction!
For beginners who want to use the ports option, you have to first get the ports set up, and when you go to the ffmpeg directory as Joshua noted to run it for ffmpeg, it will tell you you need to update pkg. Here's how to do those two things.
Code:
portsnap fetch install
pkg install pkg
 

Joshua Parker Ruehlig

Wizened Sage
Joined
Dec 5, 2011
Messages
5,949
Ok, no reasons I would need, =D

If you want to go through all the configs right away just..
Code:
make config-recursive


And to save building run dependencies you could do the following
Code:
pkg install ffmpeg
pkg delete ffmpeg

Then when you build ffmpeg from ports it will just need to compile the build dependencies
 

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
If you want to go through all the configs right away just..
Code:
make config-recursive
OK, does that allow you to run through all the dialogs at once? At what point would you enter that?
And to save building run dependencies you could do the following
Code:
pkg install ffmpeg
pkg delete ffmpeg

Then when you build ffmpeg from ports it will just need to compile the build dependencies
If I understand correctly, that would force more things to be installed from the pkg binaries as opposed to from source? Nice trick!
 

Joshua Parker Ruehlig

Wizened Sage
Joined
Dec 5, 2011
Messages
5,949
OK, does that allow you to run through all the dialogs at once? At what point would you enter that?

If I understand correctly, that would force more things to be installed from the pkg binaries as opposed to from source? Nice trick!
Yup, it figures out what dependencies (and their dependencies and so on) that you would need. You would just run is before, or during the make install command
make config-recursive install

It would install all the run dependencies, at least with the default configuration. It wouldn't grab build dependencies though like gmake/gcc5/etc.
 

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
I started attempting the ports install again this morning, choosing a minimum number of supporting libraries. After 3.5 hours, it failed for reasons I can't fathom:
Code:
Installing /usr/ports/converters/p5-Unicode-Map8/work/stage/usr/local/bin/umap
/usr/bin/strip /usr/ports/converters/p5-Unicode-Map8/work/stage/usr/local/lib/perl5/site_perl/mach/5.18/auto/Unicode/Map8/Map8.so
====> Compressing man pages (compress-man)
===>  Installing for p5-Unicode-Map8-0.13_1
===>  Checking if p5-Unicode-Map8 already installed
===>   Registering installation for p5-Unicode-Map8-0.13_1 as automatic
pkg-static: Unable to access file /usr/ports/converters/p5-Unicode-Map8/work/stage/usr/local/share/man/man1/umap.1.gz: No such file or directory
*** [fake-pkg] Error code 74

Stop in /usr/ports/converters/p5-Unicode-Map8.
*** [build-depends] Error code 1

Stop in /usr/ports/converters/enca.
*** [install] Error code 1

Stop in /usr/ports/converters/enca.
*** [lib-depends] Error code 1

Stop in /usr/ports/multimedia/libass.
*** [install] Error code 1

Stop in /usr/ports/multimedia/libass.
*** [lib-depends] Error code 1

Stop in /usr/ports/multimedia/ffmpeg.
*** [install] Error code 1

Stop in /usr/ports/multimedia/ffmpeg.
root@temp:/usr/ports/multimedia/ffmpeg # 
 

Joshua Parker Ruehlig

Wizened Sage
Joined
Dec 5, 2011
Messages
5,949
wow, your system compiles slow. 3.5 hous for ffmpeg seems like a long time.

Code:
pkg install libass

Then compile ffmpeg again.
 

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
As mentioned, it's a lot faster when I compile it myself. The ports process seems to compile ALL the dependencies, whether I selected it or not. Most of the time is not spent on ffmpeg compilation.
Anyway, I deleted that jail and am not going down that road again.
 

Joshua Parker Ruehlig

Wizened Sage
Joined
Dec 5, 2011
Messages
5,949
As mentioned, it's a lot faster when I compile it myself. The ports process seems to compile ALL the dependencies, whether I selected it or not. Most of the time is not spent on ffmpeg compilation.
Anyway, I deleted that jail and am not going down that road again.
lol, k. There's probably a way to list the dependencies you need to build, then just pkg install them.

It shouldn't grab all the dependencies. It basically depends on a library if it's selected, and doesn't check for it otherwise.
https://github.com/freebsd/freebsd-ports/blob/master/multimedia/ffmpeg/Makefile
 

n3mmr

Member
Joined
Jan 7, 2015
Messages
81
I actually does compile all deps regardless.
And doesnt handle all configs in make config-recursive, misses like 5 or so.
 

n3mmr

Member
Joined
Jan 7, 2015
Messages
81
I suppose the ports ffmpeg depends on later versions of things than the internal pkg-ng package does...
 

n3mmr

Member
Joined
Jan 7, 2015
Messages
81
And I suppose noone really thinks anyone silly enough to use FreeBSD is too busy to sit patiently at the keyboard for 12 hours. I mean, what could possibly be more important.


Irony, NOTE, IRONY.

If the Unix derivative crowd would consider making recompiles/addons/whatever be config-all-at-the-start-and-do-whatever-you-like-for-the-rest Unix derivs might have a chance.
 

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
Could you already compile ffmpeg 3.0.2 ?
I have not tried. I always compile the latest git head, which the developers recommend. 3.0.2 is a fixed release for the package people.
 

Stubb

Member
Joined
Apr 11, 2015
Messages
27
Is it possible to install ffmpeg via pkg along with fdk-aac, x265, etc. and be able to use these codecs from the command line?
 

Joshua Parker Ruehlig

Wizened Sage
Joined
Dec 5, 2011
Messages
5,949

Dakai

Newbie
Joined
Oct 11, 2016
Messages
1
Hi, Glorious1, thank you very much for the detail instructions, I followed it and found that there were some updates on the guide:

Fisrt, compiling the pkg-config will output error: "GNU libiconv not in use but included iconv.h is from libiconv"
I tried this and it worked:
Code:
./configure --with-internal-glib --with-libiconv


Secondly, compiling ffmpeg outputs:‘x265 not found using pkg-config’, even with x265 installed, after some googling, I found this would work: add to ffmpeg configure one option, which is:
Code:
./configure --cc=/usr/local/bin/gcc5 --pkg-config-flags="--static" --enable-nonfree --enable-gpl --enable-hardcoded-tables --enable-version3 --enable-libx264 --enable-libx265 --enable-avfilter --enable-filters --enable-libfdk-aac --disable-indevs --disable-outdevs --disable-ffserver --disable-network --extra-libs=-lpthread


right now I am waiting for the ffmpeg to be built, thanks again for this very detailed instructions on FreeBSD!

 
Last edited:

Glorious1

Neophyte Sage
Joined
Nov 23, 2014
Messages
1,018
Thanks @Dakai. Yes, I had to make quite a few changes to my process too, and neglected to update this post. When I get around to it, I will compare what I'm currently doing to your suggestions.
 

vinchi007

Neophyte
Joined
Mar 3, 2016
Messages
9
Hi, Glorious1, thank you very much for the detail instructions, I followed it and found that there were some updates on the guide:

Fisrt, compiling the pkg-config will output error: "GNU libiconv not in use but included iconv.h is from libiconv"
I tried this and it worked:
Code:
./configure --with-internal-glib --with-libiconv


Secondly, compiling ffmpeg outputs:‘x265 not found using pkg-config’, even with x265 installed, after some googling, I found this would work: add to ffmpeg configure one option, which is:
Code:
./configure --cc=/usr/local/bin/gcc5 --pkg-config-flags="--static" --enable-nonfree --enable-gpl --enable-hardcoded-tables --enable-version3 --enable-libx264 --enable-libx265 --enable-avfilter --enable-filters --enable-libfdk-aac --disable-indevs --disable-outdevs --disable-ffserver --disable-network --extra-libs=-lpthread


right now I am waiting for the ffmpeg to be built, thanks again for this very detailed instructions on FreeBSD!

I've compiled pkg-config with --with-libiconv like you suggested which resolved my problem.
However, I'm still getting an error when compiling ffmpeg

Code:
[root@compiler /usr/local/build/ffmpeg]# ./configure --cc=/usr/local/bin/gcc5 --pkg-config-flags="--static" --enable-nonfree --enable-gpl --enable-hardcoded-tables --enable-version3 --enable-libx264 --enable-libx265 --enable-avfilter --enable-filters --enable-libfdk-aac --disable-indevs --disable-outdevs --disable-ffserver --disable-network --extra-libs=-lpthread
ERROR: x265 not found using pkg-config

If you think configure made a mistake, make sure you are using the latest
version from Git.  If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "ffbuild/config.log" produced by configure as this will help
solve the problem.



Here are details from config.log

Code:
require_pkg_config libx265 x265 x265.h x265_api_get
check_pkg_config libx265 x265 x265.h x265_api_get
test_pkg_config libx265 x265 x265.h x265_api_get
pkg-config --exists --print-errors x265
check_func_headers x265.h x265_api_get -I/usr/local/include -L/usr/local/lib -lx265 -lstdc++ -lm -lgcc_s -lgcc -lgcc_s -lgcc -lrt
check_ld cc -I/usr/local/include -L/usr/local/lib -lx265 -lstdc++ -lm -lgcc_s -lgcc -lgcc_s -lgcc -lrt
check_cc -I/usr/local/include -L/usr/local/lib
BEGIN /tmp/ffconf.oEHGEiJe/test.c
	1   #include <x265.h>
	2   #include <stdint.h>
	3   long check_x265_api_get(void) { return (long) x265_api_get; }
	4   int main(void) { int ret = 0;
	5	ret |= ((intptr_t)check_x265_api_get) & 0xFFFF;
	6   return ret; }
END /tmp/ffconf.oEHGEiJe/test.c
/usr/local/bin/gcc5 -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -std=c11 -fomit-frame-pointer -pthread -I/usr/local/include -I/usr/local/include -I/usr/local/include -L/usr/local/lib -c -o /tmp/ffconf.oEH
GEiJe/test.o /tmp/ffconf.oEHGEiJe/test.c
/usr/local/bin/gcc5 -Wl,--as-needed -Wl,-z,noexecstack -I/usr/local/include -L/usr/local/lib -o /tmp/ffconf.oEHGEiJe/test /tmp/ffconf.oEHGEiJe/test.o -lx265 -lstdc++ -lm -lgcc_s -lgcc -lgcc_s -lgcc -lrt -lpthread
/tmp/ffconf.oEHGEiJe/test.o: In function `check_x265_api_get':
test.c:(.text+0x1): undefined reference to `x265_api_get_68'
collect2: error: ld returned 1 exit status
ERROR: x265 not found using pkg-config

 
Last edited:
Top