Skip to content

Instantly share code, notes, and snippets.

@obradovic
Last active March 24, 2021 13:36
Show Gist options
  • Save obradovic/dd428538b72b5e8281cb619ba47f3c82 to your computer and use it in GitHub Desktop.
Save obradovic/dd428538b72b5e8281cb619ba47f3c82 to your computer and use it in GitHub Desktop.
compile ffmpeg on apple silicon
#!/bin/bash
set -exuo pipefail
#
# MODIFIED FROM: https://github.com/ssut/ffmpeg-on-apple-silicon
#
# WILL NEED THE USER TO ENTER ROOT PW
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
# SET UP DIRECTORIES
WORKDIR="$(pwd)"
DEST_DIR="$WORKDIR/dest"
SRC_DIR="$WORKDIR/src"
if [[ -e "${SRC_DIR}" ]]; then
rm -rf "${SRC_DIR}"
fi
mkdir -p ${DEST_DIR}
mkdir -p ${SRC_DIR}
# SET UP ENV VARS
export PATH=${DEST_DIR}/bin:$PATH
export CC=clang && export PKG_CONFIG_PATH="${DEST_DIR}/lib/pkgconfig"
export MACOSX_DEPLOYMENT_TARGET=11.0
export LDFLAGS=${LDFLAGS:-}
export CFLAGS=${CFLAGS:-}
export NUM_PARALLEL_BUILDS=$(sysctl -n hw.ncpu)
export MAKE_INSTALL="make -j $NUM_PARALLEL_BUILDS && make install"
export ARCH=x86_64
if [[ "$(uname -m)" == "arm64" ]]; then
export ARCH=arm64
fi
# INSTALL BREW PACKAGES
function ensure_package () {
if [[ "$ARCH" == "arm64" ]]; then
if [[ ! -e "/opt/homebrew/opt/$1" ]]; then
echo "Installing $1 using Homebrew"
brew install "$1"
export LDFLAGS="-L/opt/homebrew/opt/$1/lib ${LDFLAGS}"
export CFLAGS="-I/opt/homebrew/opt/$1/include ${CFLAGS}"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/opt/homebrew/opt/$1/lib/pkgconfig"
fi
else
if [[ ! -e "/usr/local/opt/$1" ]]; then
echo "Installing $1 using Homebrew"
brew install "$1"
export LDFLAGS="-L/usr/local/opt/$1/lib ${LDFLAGS}"
export CFLAGS="-I/usr/local/opt/$1/include ${CFLAGS}"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/$1/lib/pkgconfig"
fi
fi
}
ensure_package pkgconfig
ensure_package libtool
ensure_package glib
if ! command -v autoreconf &> /dev/null; then
brew install autoconf
fi
if ! command -v automake &> /dev/null; then
brew install automake
fi
if ! command -v cmake &> /dev/null; then
brew install cmake
fi
if ! command -v handbrake &> /dev/null; then
echo "Skipping handbrake for now"
# brew install --build-from-source handbrake
fi
# CLONE GIT REPOS
echo "Cloning required git repositories"
git clone --depth 1 -b master https://code.videolan.org/videolan/x264.git $SRC_DIR/x264 &
git clone --depth 1 -b origin https://github.com/rbrito/lame.git $SRC_DIR/lame &
git clone --depth 1 -b master https://github.com/webmproject/libvpx $SRC_DIR/libvpx &
git clone --depth 1 -b master https://github.com/FFmpeg/FFmpeg $SRC_DIR/ffmpeg &
git clone --depth 1 -b v2.0.1 https://aomedia.googlesource.com/aom.git $SRC_DIR/aom &
wait
# statically linking glibc is discouraged. Dont do this.
# echo "Downloading: glib (2.66.2)"
# curl -Ls -o - https://download.gnome.org/sources/glib/2.66/glib-2.66.2.tar.xz | tar Jxf - -C $SRC_DIR/
# curl -o "$SRC_DIR/glib-2.66.2/hardcoded-patchs.diff" https://raw.githubusercontent.com/Homebrew/formula-patches/6164294a75541c278f3863b111791376caa3ad26/glib/hardcoded-paths.diff
#
# HERE IS A CRAPTON OF FUNCTIONS TO DOWNLOAD/INSTALL REQUIRED PACKAGES
#
function download_src_gz {
url=$1
echo "♻️ Downloading: $url"
{(curl -Ls -o - $url | tar zxf - -C $SRC_DIR/ )};
}
function download_src_xz {
url=$1
echo "♻️ Downloading: $url"
{(curl -Ls -o - $url | tar Jxf - -C $SRC_DIR/) };
}
function download_src_bz {
url=$1
echo "♻️ Downloading: $url"
{(curl -Ls -o - $url | tar xf - -C $SRC_DIR/) };
}
function build_fribidi () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/fribidi.pc" ]]; then
local VERSION=1.0.10
local NAME=fribidi-$VERSION
download_src_xz https://github.com/fribidi/fribidi/releases/download/v$VERSION/$NAME.tar.xz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-debug --disable-dependency-tracking --disable-silent-rules --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_yasm () {
if [[ ! -e "${DEST_DIR}/lib/libyasm.a" ]]; then
local VERSION=1.3.0
local NAME=yasm-$VERSION
download_src_gz http://www.tortall.net/projects/yasm/releases/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR}
$MAKE_INSTALL
fi
}
function build_aom () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/aom.pc" ]]; then
echo '♻️ ' Start compiling AOM
cd ${SRC_DIR}
cd aom
mkdir aom_build
cd aom_build
AOM_CMAKE_PARAMS="-DENABLE_DOCS=off -DENABLE_EXAMPLES=off -DENABLE_TESTDATA=off -DENABLE_TESTS=off -DENABLE_TOOLS=off -DCMAKE_INSTALL_PREFIX:PATH=${DEST_DIR} -DLIBTYPE=STATIC"
if [[ "$ARCH" == "arm64" ]]; then
AOM_CMAKE_PARAMS="$AOM_CMAKE_PARAMS -DCONFIG_RUNTIME_CPU_DETECT=0"
fi
cmake ${SRC_DIR}/aom $AOM_CMAKE_PARAMS
$MAKE_INSTALL
fi
}
function build_nasm () {
if [[ ! -e "${DEST_DIR}/bin/nasm" ]]; then
local VERSION=2.15.05
local NAME=nasm-$VERSION
download_src_gz https://www.nasm.us/pub/nasm/releasebuilds/$VERSION/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
cd nasm-$VERSION
./configure --prefix=${DEST_DIR}
$MAKE_INSTALL
fi
}
function build_pkgconfig () {
if [[ ! -e "${DEST_DIR}/bin/pkg-config" ]]; then
local VERSION=0.29.2
local NAME=pkg-config-$VERSION
download_src_gz https://pkg-config.freedesktop.org/releases/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
export LDFLAGS="-framework Foundation -framework Cocoa"
./configure --prefix=${DEST_DIR} --with-pc-path=${DEST_DIR}/lib/pkgconfig --with-internal-glib --disable-shared --enable-static
$MAKE_INSTALL
unset LDFLAGS
fi
}
function build_zlib () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/zlib.pc" ]]; then
local VERSION=1.2.11
local NAME=zlib-$VERSION
download_src_gz https://zlib.net/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR}
$MAKE_INSTALL
rm ${DEST_DIR}/lib/libz.so* || true
rm ${DEST_DIR}/lib/libz.* || true
fi
}
function build_lame () {
if [[ ! -e "${DEST_DIR}/lib/libmp3lame.a" ]]; then
cd ${SRC_DIR}
cd lame
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_x264 () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/x264.pc" ]]; then
echo '♻️ ' Start compiling X264
cd ${SRC_DIR}
cd x264
./configure --prefix=${DEST_DIR} --disable-shared --enable-static --enable-pic
$MAKE_INSTALL
make install-lib-static
fi
}
function build_x265 () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/x265.pc" ]]; then
local VERSION=3.3
local NAME=x265_$VERSION
download_src_gz https://bitbucket.org/multicoreware/x265_git/downloads/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
rm -f ${DEST_DIR}/include/x265*.h 2>/dev/null
rm -f ${DEST_DIR}/lib/libx265.a 2>/dev/null
echo '♻️ ' X265 12bit
cd ${SRC_DIR}
cd $NAME/source
cmake -DCMAKE_INSTALL_PREFIX:PATH=${DEST_DIR} -DHIGH_BIT_DEPTH=ON -DMAIN12=ON -DENABLE_SHARED=NO -DEXPORT_C_API=NO -DENABLE_CLI=OFF .
make -j ${NUM_PARALLEL_BUILDS}
mv libx265.a libx265_main12.a
make clean-generated
rm CMakeCache.txt
echo '♻️ ' X265 10bit
cd ${SRC_DIR}
cd $NAME/source
cmake -DCMAKE_INSTALL_PREFIX:PATH=${DEST_DIR} -DMAIN10=ON -DHIGH_BIT_DEPTH=ON -DENABLE_SHARED=NO -DEXPORT_C_API=NO -DENABLE_CLI=OFF .
make clean
make -j ${NUM_PARALLEL_BUILDS}
mv libx265.a libx265_main10.a
make clean-generated && rm CMakeCache.txt
echo '♻️ ' X265 full
cd ${SRC_DIR}
cd $NAME/source
cmake -DCMAKE_INSTALL_PREFIX:PATH=${DEST_DIR} -DEXTRA_LIB="x265_main10.a;x265_main12.a" -DEXTRA_LINK_FLAGS=-L. -DLINKED_12BIT=ON -DLINKED_10BIT=ON -DENABLE_SHARED=OFF -DENABLE_CLI=OFF .
make clean
make -j ${NUM_PARALLEL_BUILDS}
mv libx265.a libx265_main.a
libtool -static -o libx265.a libx265_main.a libx265_main10.a libx265_main12.a 2>/dev/null
make install
fi
}
function build_vpx () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/vpx.pc" ]]; then
echo '♻️ ' Start compiling VPX
cd ${SRC_DIR}
cd libvpx
./configure --prefix=${DEST_DIR} --enable-vp8 --enable-postproc --enable-vp9-postproc --enable-vp9-highbitdepth --disable-examples --disable-docs --enable-multi-res-encoding --disable-unit-tests --enable-pic --disable-shared
$MAKE_INSTALL
fi
}
function build_expat () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/expat.pc" ]]; then
local VERSION=2.2.10
local NAME=expat-$VERSION
download_src_gz https://github.com/libexpat/libexpat/releases/download/R_`echo $VERSION | tr "." "_"`/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_libiconv () {
if [[ ! -e "${DEST_DIR}/lib/libiconv.a" ]]; then
local VERSION=1.16
local NAME=libiconv-$VERSION
download_src_gz https://ftp.gnu.org/pub/gnu/libiconv/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_enca () {
if [[ ! -d "${DEST_DIR}/libexec/enca" ]]; then
local VERSION=1.19
local NAME=enca-$VERSION
download_src_gz https://dl.cihar.com/enca/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-dependency-tracking --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_freetype () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/freetype2.pc" ]]; then
local VERSION=2.10.4
local NAME=freetype-$VERSION
download_src_gz https://download.savannah.gnu.org/releases/freetype/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_gettext () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/gettext.pc" ]]; then
local VERSION=0.21
local NAME=gettext-$VERSION
download_src_xz https://ftp.gnu.org/gnu/gettext/$NAME.tar.xz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-dependency-tracking --disable-silent-rules --disable-debug --disable-shared --enable-static \
--with-included-gettext --with-included-glib --with-includedlibcroco --with-included-libunistring --with-emacs \
--disable-java --disable-csharp --without-git --without-cvs --without-xz
$MAKE_INSTALL
fi
}
function build_fontconfig () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/fontconfig.pc" ]]; then
local VERSION=2.13.93
local NAME=fontconfig-$VERSION
download_src_gz https://www.freedesktop.org/software/fontconfig/release/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --enable-iconv --disable-libxml2 --disable-shared --enable-static --disable-docs
$MAKE_INSTALL
fi
}
function build_harfbuzz () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/harfbuzz.pc" ]]; then
local VERSION=2.7.2
local NAME=harfbuzz-$VERSION
download_src_xz https://github.com/harfbuzz/harfbuzz/releases/download/$VERSION/$NAME.tar.xz
echo '♻️ ' Start compiling harfbuzz
cd $SRC_DIR/harfbuzz-$NAME
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_ass () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/libass.pc" ]]; then
local VERSION=0.15.0
local NAME=libass-$VERSION
download_src_gz https://github.com/libass/libass/releases/download/$VERSION/$NAME.tar.gz
cd $SRC_DIR/$NAME
autoreconf -i
./configure --prefix=${DEST_DIR} --disable-dependency-tracking --disable-shread --enable-static
$MAKE_INSTALL
fi
}
function build_opus () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/opus.pc" ]]; then
local VERSION=1.3.1
local NAME=opus-$VERSION
download_src_gz https://archive.mozilla.org/pub/opus/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_ogg () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/ogg.pc" ]]; then
local VERSION=1.3.4
local NAME=libogg-$VERSION
download_src_gz https://downloads.xiph.org/releases/ogg/$NAME.tar.gz
curl -s -o "$SRC_DIR/$NAME/fix_unsigned_typedefs.patch" "https://github.com/xiph/ogg/commit/c8fca6b4a02d695b1ceea39b330d4406001c03ed.patch?full_index=1"
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
patch -p1 < ./fix_unsigned_typedefs.patch
./configure --prefix=${DEST_DIR} --disable-shared --enable-static
$MAKE_INSTALL
fi
}
function build_vorbis () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/vorbis.pc" ]]; then
local VERSION=1.3.7
local NAME=libvorbis-$VERSION
download_src_gz https://downloads.xiph.org/releases/vorbis/$NAME.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --with-ogg-libraries=${DEST_DIR}/lib --with-ogg-includes=${DEST_DIR}/include/ --enable-static --disable-shared --build=x86_64
$MAKE_INSTALL
fi
}
function build_theora () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/theora.pc" ]]; then
local VERSION=1.1.1
local NAME=libtheora-$VERSION
download_src_bz http://downloads.xiph.org/releases/theora/$NAME.tar.bz2
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR} --disable-asm --with-ogg-libraries=${DEST_DIR}/lib --with-ogg-includes=${DEST_DIR}/include/ --with-vorbis-libraries=${DEST_DIR}/lib --with-vorbis-includes=${DEST_DIR}/include/ --enable-static --disable-shared
$MAKE_INSTALL
fi
}
function build_vidstab () {
if [[ ! -e "${DEST_DIR}/lib/pkgconfig/vidstab.pc" ]]; then
local VERSION=1.1.0
local NAME=vid.stab-$VERSION
download_src_gz https://github.com/georgmartius/vid.stab/archive/v$VERSION.tar.gz
curl -s -o "$SRC_DIR/$NAME/fix_cmake_quoting.patch" https://raw.githubusercontent.com/Homebrew/formula-patches/5bf1a0e0cfe666ee410305cece9c9c755641bfdf/libvidstab/fix_cmake_quoting.patch
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
patch -p1 < fix_cmake_quoting.patch
cmake . -DCMAKE_INSTALL_PREFIX:PATH=${DEST_DIR} -DLIBTYPE=STATIC -DBUILD_SHARED_LIBS=OFF -DUSE_OMP=OFF -DENABLE_SHARED=off
$MAKE_INSTALL
fi
}
function build_snappy () {
if [[ ! -e "${DEST_DIR}/lib/libsnappy.a" ]]; then
local VERSION=1.1.8
local NAME=snappy-$VERSION
download_src_gz https://github.com/google/snappy/archive/$VERSION.tar.gz
echo '♻️ ' Start compiling $NAME
cd $SRC_DIR/$NAME
cmake . -DCMAKE_INSTALL_PREFIX:PATH=${DEST_DIR} -DLIBTYPE=STATIC -DENABLE_SHARED=off
$MAKE_INSTALL
fi
}
function build_libpng {
if [[ ! -e "${DEST_DIR}/lib/libpng.a" ]]; then
# local VERSION=1.6.37 $ libtheora borks with this version cause it cant find png_sizeof
local VERSION=1.2.59 # This is the last version that has png_sizeof. Was deprecated as of 1.4
local NAME=libpng-$VERSION
download_src_gz https://sourceforge.net/projects/libpng/files/libpng`echo $VERSION | cut -d'.' -f1,2 | tr -d '.'`/$VERSION/$NAME.tar.gz/download
cd $SRC_DIR/$NAME
./configure --prefix=${DEST_DIR}
$MAKE_INSTALL
# NOTE: ALSO install in the global dir cause somehow we cant configure libfontconfig to find it anywhere else
./configure
make -j ${NUM_PARALLEL_BUILDS}
sudo make install
fi
}
function build_ffmpeg () {
echo '♻️ ' Start compiling FFMPEG
cd $SRC_DIR/ffmpeg
export LDFLAGS="-L${DEST_DIR}/lib ${LDFLAGS:-}"
export CFLAGS="-I${DEST_DIR}/include ${CFLAGS:-}"
export LDFLAGS="$LDFLAGS -lexpat -lenca -lfribidi -liconv -lstdc++ -lfreetype -framework CoreText -framework VideoToolbox"
./configure --prefix=${DEST_DIR} --extra-cflags="-fno-stack-check" --arch=${ARCH} --cc=/usr/bin/clang \
--enable-fontconfig --enable-gpl --enable-libopus --enable-libtheora --enable-libvorbis \
--enable-libmp3lame --enable-libass --enable-libfreetype --enable-libx264 --enable-libx265 --enable-libvpx \
--enable-libaom --enable-libvidstab --enable-libsnappy --enable-version3 --pkg-config-flags=--static \
--disable-ffplay --enable-postproc --enable-nonfree --enable-runtime-cpudetect
echo "build start"
start_time="$(date -u +%s)"
$MAKE_INSTALL
end_time="$(date -u +%s)"
elapsed="$(($end_time-$start_time))"
echo "[FFmpeg] $elapsed seconds elapsed for build"
}
#
# INSTALL THE REQUIRED PACKAGES, IN ROUGH ORDER
#
build_fribidi
build_yasm
build_aom
build_nasm
build_pkgconfig
build_zlib
build_lame
build_x264
build_x265
build_vpx
build_expat
build_libiconv
build_enca
build_freetype
if [[ "$ARCH" == "arm64" ]]; then
build_gettext
fi
build_libpng
build_fontconfig
build_harfbuzz
build_ass
build_opus
build_ogg
build_vorbis
build_theora
build_vidstab
build_snappy
build_ffmpeg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment