Glorious1
Guru
- Joined
- Nov 23, 2014
- Messages
- 1,211
** 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
Save the file (Esc, Enter, Enter). Read that file in so it takes effect now by typing
# Later times, instead of install using pkg, just update/upgrade:
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:
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]
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.
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
Last edited: