Compiling mpv for MacOS X

It has been a long time since my last posting and I am still building ffmpeg/mpv for personal use. As I do not clearly explain how to build mpv in a previous blog article Compiling ffmpeg I thought I make a new one just explaining mpv.

I build two different versions of mpv, one without subtitle and on screen display support and one with it. At the time of writing, this script should work with MacOS X 10.11.x.


# use the llvm compiler
export CC="/usr/bin/clang"
export CXX="/usr/bin/clang++"

# set the ramdisk name
export VOLNAME=mpv-master

# and make it 1.5 GB
DISK_ID=$(hdid -nomount ram://4145728)
newfs_hfs -v ${VOLNAME} ${DISK_ID}
diskutil mount ${DISK_ID}

# set up shortcuts
export MCB="/Users/snowy/mediaencoding"
export MES=${MCB}/base/
export TARGET="/Volumes/${VOLNAME}/"
export CMPL="/Volumes/${VOLNAME}/compile"
export PATH=${TARGET}/bin:$PATH

# extend the python modules path
export PYTHONPATH="${TARGET}/lib/python2.7/site-packages/"

# set up the directories
mkdir -p ${CMPL}

# next, yasm
# should work with yasm-1.3.0.tar.gz
cd ${CMPL}
tar xzpf ${MES}/yasm*.tar.gz
cd yasm-*
./configure --prefix=${TARGET} && make -j 8 && make install

# next, pkg-config
# should work with pkg-config-0.29.1.tar.gz
cd ${CMPL}
tar xzpf ${MES}/pkg-config*
cd pkg-config*
export LDFLAGS="-framework Foundation -framework Cocoa"
./configure --prefix=${TARGET} --with-pc-path=${TARGET}/lib/pkgconfig --with-internal-glib && make -j 8 && make install
unset LDFLAGS

# building libressl
# should work with libressl-2.4.2.tar.gz
puts "Building libressl"
cd ${CMPL}
tar xzpf ${MES}/libressl-*tar.gz
cd libressl*
./configure --prefix=${TARGET} --enable-static --disable-shared && make -j 8 && make -s install

# get ffmpeg
# technically, I could simply build a full blown ffmpeg with third party libraries
# but as they are mostly used for encoding and mpv is a media player
# there is no real need to do it. But you could, if you wanted to :-)
cd ${CMPL}
curl -LOs http://www.ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
tar xjpf ffmpeg-snapshot.tar.bz2
cd ffmpeg
./configure --prefix=${TARGET} \
--extra-cflags="-I${TARGET}/include" \
--extra-ldflags="-L${TARGET}/lib" \
--enable-openssl \
--enable-static \
--disable-shared \
--disable-doc && make -j 8 && make install

# check if build was successful
if [ ! -e $TARGET/bin/ffmpeg ]
then
echo "Build failed (ffmpeg). KABOOM"
exit 1
fi

# and build mpv
# clone from git so the version will be set
git clone https://github.com/mpv-player/mpv.git
cd mpv

# And mpv just had to use yet another different build system
# people just have too much time reinventing the wheel....
# This time, it is some python hell called 'was'

./bootstrap.py

# Without this the configure line will(!) fail
export PKG_CONFIG=pkg-config

# something broke finding "ar", this is a crude way to fix it
sed '/ctx.find_program.ar/d' -i wscript

./waf configure --prefix=${TARGET} --disable-libass-osd --disable-libass

./waf build
./waf install

# check if build was successful
if [ ! -e $TARGET/bin/mpv ]
then
echo "Build failed. KABOOM"
exit 1
fi

# debug
# bash

# copy to local directory
cp ${TARGET}/bin/mpv $HOME/.bin/
cp ${TARGET}/share/man/man1/mpv.1 $HOME/.man/man1/

# wipe the compilation tree
cd ${TARGET} && rm -rf include
cd ${TARGET} && rm -rf lib
cd ${TARGET} && rm -rf compile

# create the disk image
hdiutil create -size 300m -volname ${VOLNAME} -srcfolder /Volumes/${VOLNAME} $HOME/Downloads/${VOLNAME}

# eject the ram disk
cd $HOME
diskutil unmount /Volumes/${VOLNAME}

So that gets you a bare mpv binary that you can use from Terminal to play media content.
It just works and you can still use keys to fast forward or rewind.

And now for a mpv binary with OSD and subtitle support. It compiles just like the mpv above but a few more libraries are needed so the OSD and subtitle support is included.


# use the llvm compiler
export CC="/usr/bin/clang"
export CXX="/usr/bin/clang++"

# ramdisk
export VOLNAME=mpv-osd-master
DISK_ID=$(hdid -nomount ram://3145728)
newfs_hfs -v ${VOLNAME} ${DISK_ID}
diskutil mount ${DISK_ID}

# set up shortcuts
export MCB="/Users/snowy/mediaencoding"
export MES=${MCB}/base/
export TARGET="/Volumes/${VOLNAME}/"
export CMPL="/Volumes/${VOLNAME}/compile"
export PATH=${TARGET}/bin:$PATH

# set up the directories
mkdir -p ${CMPL}

# run make with 6 threads
export MKMU="make -j 6"

# no directory, no fun
cd ${CMPL} || exit 1

# next, yasm
cd ${CMPL}
tar xzpf ${MES}/yasm*.tar.gz
cd yasm-*
./configure --prefix=${TARGET} && $MKMU && make install

# next, pkg-config
cd ${CMPL}
tar xzpf ${MES}/pkg-config*
cd pkg-config*
export LDFLAGS="-framework Foundation -framework Cocoa"
./configure --prefix=${TARGET} --with-pc-path=${TARGET}/lib/pkgconfig --with-internal-glib && $MKMU && make install
unset LDFLAGS

# building libressl
# should work with libressl-2.4.2.tar.gz
puts "Building libressl"
cd ${CMPL}
tar xzpf ${MES}/libressl-*tar.gz
cd libressl*
./configure --prefix=${TARGET} --enable-static --disable-shared && $MKMU && make -s install

# next, libpng
# should work with libpng-1.6.23.tar.gz
cd ${CMPL}
tar xzpf ${MES}/libpng*.tar.gz
cd libpng*
./configure --prefix=${TARGET} --disable-shared --enable-static && $MKMU && make install

# next, freetype
# should work with freetype-2.6.5.tar.gz
cd ${CMPL}
tar xzpf ${MES}/freetype*.tar.gz
cd freetype*
./configure --prefix=${TARGET} --disable-shared --enable-static && $MKMU && make install

# next fribidi
# should work with fribidi-0.19.7.tar.bz2
cd ${CMPL}
tar xjpf ${MES}/fribidi*.tar.bz2
cd fribidi*
./configure --prefix=${TARGET} --disable-shared --enable-static && $MKMU && make install

# next, libass
# should work with libass-0.13.2.tar.gz
cd ${CMPL}
tar xzpf ${MES}/libass*.tar.gz
cd libass*
./configure --prefix=${TARGET} --disable-fontconfig --disable-shared --enable-static && $MKMU && make install

# lua
# mpv specifically requires lua 5.1 or 5.2
# althoug current version is 5.3.x
cd ${CMPL}
tar xzpf ${MES}/lua-5.2.4.tar.gz
cd lua-5.2.4
make macosx install INSTALL_TOP=${TARGET}

# create a lua.pc so mpv can find it
cat >${TARGET}/lib/pkgconfig/lua.pc <<EOF
prefix=/Volumes/mpv-osd-master
exec_prefix=\${prefix}
libdir=\${prefix}/lib/
includedir=\${prefix}/include
Name: lua
Description: lua
Requires:
Version: 5.2.4
Libs: -L\${libdir} -llua
Cflags: -I\${includedir}
EOF

# much to my surprise it also requires luaJIT
# so we provide that too
# should work with LuaJIT-2.0.4.tar.gz
cd ${CMPL}
tar xzpf ${MES}/LuaJIT*.tar.gz
cd LuaJIT*
make PREFIX=${TARGET}
make install PREFIX=${TARGET}

# get rid of the dynamically loadable libraries
# to force it to use the static version for compilation
rm -v ${TARGET}/lib/libluajit*dylib

# ffmpeg
# set compiler flags
cd ${CMPL}
curl -LOs http://www.ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
tar xjpf ffmpeg-snapshot.tar.bz2
cd ffmpeg
./configure --prefix=${TARGET} \
--extra-cflags="-I${TARGET}/include" \
--extra-ldflags="-L${TARGET}/lib -lpng -framework CoreText" \
--enable-openssl \
--enable-libass \
--enable-static --disable-shared \
--disable-programs --disable-doc && $MKMU && make install

# and build mpv
cd ${CMPL}
git clone https://github.com/mpv-player/mpv.git
cd mpv

./bootstrap.py
export PKG_CONFIG=pkg-config

# something broke finding "ar", this is a crude way to fix it
sed '/ctx.find_program.ar/d' -i wscript

# configure the damn thing
./waf configure --prefix=${TARGET} --disable-debug-build --disable-manpage-build

# and thanks to the awesome build system mpv uses
# which I am unable to wrap my head around in trying
# to add linking to libpng I had to resort to a very
# crude yet effective workaround
sed "s/'fribidi',/'fribidi', 'png',/g" -i build/c4che/_cache.py

# and, hoorary, this should build
./waf build
./waf install

# check if build was successful
if [ ! -e $TARGET/bin/mpv ]
then
echo "Build failed. KABOOM"
exit
fi

# and copy it
cp $TARGET/bin/mpv $HOME/.bin/mpv-osd

# cleanup
cd ${TARGET} && rm -rf include
cd ${TARGET} && rm -rf lib
cd ${TARGET} && rm -rf compile

# create the disk image
cd $HOME
hdiutil create -size 300m -volname ${VOLNAME} -srcfolder /Volumes/${VOLNAME} $HOME/Downloads/${VOLNAME}

# eject the ram disk
cd $HOME
diskutil unmount /Volumes/${VOLNAME}

So you should have two versions of mpv. The ‘mpv’ and ‘mpv-osd’ binary which both work from Terminal. Compilation usually fails if ffmpeg is in an inconsistent state and the ffmpeg build fails which mpv depends on.

I know you can build mpv as a proper MacOS X application but then again one can simply use VLC if someone wants an ugly GUI program :-)

One more thing: You need to elevate to root and kill the diskimages-helper processes which seem to hang around after mounting the ram disks. That should get you some precious :-) memory back.