Note: These intstructions may not cover everything 100% since i had to write some from memory.
I also recently added more details and the section on compiling a current version of perl with threads which is required.
This post covers:
* Installing basic requirements to transcode and stream (ffmpeg and lame). This is needed to transcode audio files to different bitrates and stream videos.
* Getting advances streaming to work. This is only needed if you are not satisfied with the video quality or the CPU power of your NAS does not suffice for better video encoding. For instance with ffmpeg it is not possible to stream 720p h264 videos in real time. With the advanced mplayer2 solution this will be possible if you have a dual-core Atom NAS (or better).
1) Installing lame:
* install lame with the command "ipkg install lame"
* if it does not exist yet, creat the transcode directory where all transcoding applications of subsonic are found: mkdir /var/subsonic/transcode
* link to lame so subsonic finds it: ln -s /opt/bin/lame /var/subsonic/transcode/lame
2) Installing ffmpeg
* Install ffmpeg: "ipkg install ffmpeg"
* link to it: ln -s /opt/bin/ffmpeg /var/subsonic/transcode/ffmpeg
3) getting, compiling and configuring mplayer2.
Basic info: Why this modified mplayer2 and not just use ffmpeg or mplayer/mencoder?
Well, ffmpeg has a feature you need: encode to flash video (or mp4), but ffmpeg lacks really good multi-threaded video decoding (it never worked for me, even with the pthreads option enabled), which you will need to be able to decode 720p h264 files in real time.
On the other hand, mencoder does support proper fast multithreaded decoding, but cannot output to flv (or mp4) properly. I tried and it either dos not work or causes mencoder to crash.
mplayer2 with encoding extension added can do both!
Since this is somthing thing that is not official yet, you cannot get pre-built binarys yet, so you have to get the sources and compile it.
Basics on mplayer2:
http://www.mplayer2.org/ (in short: mplayer2 is a new improved version of mplayer which allows playing and converting of media files. mplayer2 is not yet very common, but with encoding support provided by divVerent it is a much better option compared to ffmpeg)
* Prepare your system for compiling:
First you have to install all the packages needed so you can compile, all of which are available as packages. Here is a list of the commands I used (I got the basics here but extended them:
http://forum.qnap.com/viewtopic.php?f=177&t=32731):
- Code: Select all
ipkg install make bash svn automake autoconf mktemp grep bzip2 yasm coreutils glib libtool libcurl libgsm libogg libtheora libvorbis libmatroska libmpeg2 perl ncurses pkgconfig freetype fontconfig tar optware-devel nano
Note, you may want/nedd to execute "rm /bin/mktemp" temporarily after this
also, if you want aac audio decoding, do this:
ipkg install faad2
(you can get the sources and compile the latest version if you want, alternatively:
http://www.audiocoding.com/downloads.html)
* get, compile and install pre-requisites for mplayer2Since mplayer2 (and for that matter also ffmpeg and mplayer) depend on libraries that do the decoding and encoding, we need to compile some of the important ones ourselves, since either packages are not available or outdated.
you will want x264 (for h.264 avc video encofding), faac (aac audio encoding) and if you want, xvid for mpeg-4 encoding.
We will do all the downloading and then compiling in /opt/etc:
You may want to tell the comiler to optimize compilation :
- Code: Select all
export CFLAGS="-O3 -march=i686 -mtune=i686"
export CXXFLAGS="${CFLAGS}"
x264:
------
I did not manage to get the current version to work.
It will crash some time into the encoding process (depending on source).
This is not an issue of x264 itself, but of the available gcc compiler being
outdated and buggy.
I found that one of the latest snapsots of x264 that work correctly is
the first of 2011. So:
- Code: Select all
cd /opt/etc/
wget http://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-20110101-2245.tar.bz2
tar -xvf x264-snapshot-20110101-2245.tar.bz2
cd x264-snapshot-20110101-2245
./configure --prefix=/opt
make
make install
Please note to always add --prefix=/opt for configuring, since that is where you want to have all your software installed instead of the default location.
faac (if you want to comile faad2, that looks almost identical):
-----
- Code: Select all
cd /opt/etc/
wget http://switch.dl.sourceforge.net/sourceforge/faac/faac-1.28.tar.gz
tar -xvf faac-1.28.tar.gz
cd /opt/etc/faac-1.28
./configure --prefix=/opt
make
make install
optional: xvid
---------------
- Code: Select all
cd /opt/etc/
wget http://downloads.xvid.org/downloads/xvidcore-1.2.2.tar.gz
tar -xvf xvidcore-1.2.2.tar.gz
cd /opt/etc/xvidcore/build/generic/
./configure --prefix=/opt
make
make install
Please note that the latest version of xvid is currently 1.3.1, however for that to compile (actually configure, i think) correctly, you will need some updated software.
I'm not sure which anymore, but possibly gawk or perl, or maybe sed.
If you want the latest version, replace the version in the code above, and first try with
ipkg install gawk
ipkg install sed
It may be that xvid 1.3.1 also needs a current perl, I am not sure.
* Compile a current version of perl that supports threadsUnfortunately some components of mplayer2 require a current version of perl that supports threading,
which is not the case with the version of perl that can be installed using ipgk.
Here the steps to compile and install perl:
- Code: Select all
# download sources
cd /opt/etc/
wget http://www.cpan.org/src/5.0/perl-5.12.3.tar.gz
tar -xvf perl-5.12.3.tar.gz
cd /opt/etc/perl-5.12.3
# perl searches for errno.h only at a few predefined places where we do not have it.
# Fix this by replacing these lines
my $linux_errno_h = -e '/usr/include/errno.h' ?
'/usr/include/errno.h' : '/usr/local/include/errno.h';
with this:
my $linux_errno_h = -e '/usr/include/errno.h' ?
'/usr/include/errno.h' : -e '/usr/local/include/errno.h' ? '/usr/local/include/errno.h' : '/opt/include/errno.h';
in file ext/Errno/Errno_pm.PL in the perl sources directory
# configure perl: (-de: not to enter each question manually, -Dcc=gcc: to tell we use the gcc compiler, prefix that we want to intall to opt, and -Dusethreads that thread support is to be addedd)
./Configure -de -Dcc=gcc -Dprefix=/opt -Dusethreads
# compile and install:
make
make install
* get "git"Git is a version control system. Mplayer2 sources are available through git.
You need the git client to check out the sources.
Normally it should be enough to install git with
ipkg install git
However while I did my second install (after loosing some data because of accidentally deleting it),
git was not avaailable in the ipkg repository, so I had to compile git myself, using these commands:
- Code: Select all
# prerequisites
ipkg install tcl python libcurl-dev openssl openssl-dev sed gawk
ln -s /opt/bin/perl /usr/bin/perl
ln -s /opt/bin/python /usr/bin/python
# get sources
cd /opt/etc/
wget http://kernel.org/pub/software/scm/git/git-1.7.5.tar.bz2
cd /opt/etc/git-1.7.5
# configure, compile and install
./configure --prefix=/opt
make
make install
* get, compile and install mplayer2Now we got all the prerequisites, we go on to the main point, mplayer2 enhanced with divVerent's encoding features:
https://github.com/divVerent/mplayer/wi ... au-vo-lavcIf you have trouble along the way, log in to IRC server irc.freenode.net and join channel #mplayer2. I recommend the MIRC client for that.
Also, some more information on my own problems and progress is documented here:
http://forum.qnap.com/viewtopic.php?f=4 ... 41#p192041Now, for mplayer2:
- Code: Select all
git clone git://git.mplayer2.org/mplayer2-build.git
cd mplayer2-build
./init
Then you will want to configure the features with which you want mplayer2 and ffmpeg (which is used by mplayer2) compiled.
Just add the line "--prefix=/opt) to mplayer_options (use nano).
And I recommend those for ffmpeg_options (no --prefix=/opt here because it shall be installed locally only):
- Code: Select all
--enable-static
--disable-shared
--enable-pthreads
--enable-nonfree
--enable-libmp3lame
--enable-libx264
--enable-libfaac
--enable-libxvid
--enable-libvorbis
--enable-libtheora
--enable-decoder=aac
(do not add --enable-libx264 if you did not compile xvid before)
then continue with getting divVerents encoding modifications and start the compile and finally install:
- Code: Select all
cd mplayer
git remote add -f divVerent git://github.com/divVerent/mplayer.git
git checkout -t -b divVerent/mplayer-uau-vo-lavc divVerent/divVerent/mplayer-uau-vo-lavc
cd ..
make
make install
If you only want to compile or re-compile portions of mplayer2, there a list of commands for each component:
Note: if leave out --prefix=/opt of the ffmpeg configuration unless you want to install this ffmpeg in your system.
- Code: Select all
mkdir ffmpeg_build
cd ffmpeg_build
../ffmpeg-mt/configure --prefix=/opt --enable-gpl --disable-debug --enable-pthreads --disable-shared --enable-static --enable-postproc --enable-nonfree --enable-libmp3lame --enable-libx264 --enable-libxvid --enable-libfaac --enable-decoder=aac
make
make install
cd ..
cd libass
./autogen.sh --prefix=/opt
make
make install
cd ..
cd mplayer
./configure --prefix=/opt
make
make install
* configure use of mplayer2Now, I hope you did not run into troubles with compilation anywhere. If you did, please report this to me, so I can ajust this documentation so it instructs accordingly so all runs well).
Now that we have mplayer2, we can almost start using it.
I have spend many hours tweaking settings for mplayer2, so it gets the best quality at certain bitrates and is still fast enough.
You can take a short-cut here and use my shell script:
- Code: Select all
#!/bin/sh
# $1=offset in seconds
# $2=source file
# $3 bitrate in kbit/s
# $4 width in pixels (optional, currently ignored and derived from height and aspect ratio)
# $5 hight in pixels (optional, currently ignored and derived from bitrate)
# $6 output: if provided output file name, if not provided output is sdtout
offset=$1; source=$2; bitrate=$3; width=$4; height=$5; output=$6;
VIDEO_METADATA=$(/var/subsonic/transcode/mplayer -vo null -ao null -frames 0 -identify "$source" 2>/dev/null | /opt/bin/sed -ne '/^ID_/ { s/[]()|&;<>`'"'"'\\!$" []/\\&/g;p }')
VIDEO_FPS=$(echo "$VIDEO_METADATA" | /opt/bin/sed -n 's/^ID_VIDEO_FPS=//p' | /opt/bin/sed 's/\.//g')
VIDEO_WIDTH=$(echo "$VIDEO_METADATA" | /opt/bin/sed -n 's/^ID_VIDEO_WIDTH=//p')
VIDEO_HEIGHT=$(echo "$VIDEO_METADATA" | /opt/bin/sed -n 's/^ID_VIDEO_HEIGHT=//p')
#echo VIDEO_FPS=$VIDEO_FPS
#echo VIDEO_WIDTH=$VIDEO_WIDTH
#echo VIDEO_WIDTH=$VIDEO_WIDTH
if [ $VIDEO_HEIGHT -gt 480 ]; then
FASTDECODING="-lavdopts threads=4:fast:skiploopfilter=all"
else
FASTDECODING="-lavdopts threads=4:fast"
fi
if [ $VIDEO_FPS -ge 100000 ]; then
FPS_OPTION="-ofps 24000/1001";
else
FPS_OPTION="-oautofps";
fi
SRATE=44100
if [ $bitrate -le 200 ]; then
MAXRATE=100k; CRF=23; AUDIORATE=64k; VERT_RES=160; SRATE=22050
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@fast; else SPEEED=@slow; fi
elif [ $bitrate -le 300 ]; then
MAXRATE=300k; CRF=22; AUDIORATE=64k; VERT_RES=192; SRATE=22050
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@faster; else SPEEED=@medium; fi
elif [ $bitrate -le 400 ]; then
MAXRATE=400k; CRF=22; AUDIORATE=80k; VERT_RES=240;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@superfast; else SPEEED=@faster; fi
elif [ $bitrate -le 500 ]; then
MAXRATE=500k; CRF=22; AUDIORATE=96k; VERT_RES=288;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@superfast; else SPEEED=@faster; fi
elif [ $bitrate -le 700 ]; then
MAXRATE=700k; CRF=22; AUDIORATE=96k; VERT_RES=320;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@superfast; else SPEEED=@faster; fi
elif [ $bitrate -le 1000 ]; then
MAXRATE=1000k; CRF=21; AUDIORATE=112k; VERT_RES=384;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@ultrafast; else SPEEED=@veryfast; fi
elif [ $bitrate -le 1200 ]; then
MAXRATE=1200k; CRF=21; AUDIORATE=128k; VERT_RES=408;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@ultrafast; else SPEEED=@superfast; fi
elif [ $bitrate -le 1500 ]; then
MAXRATE=1500k; CRF=21; AUDIORATE=144k; VERT_RES=432; FASTDECODE=@fastdecode,;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@ultrafast; else SPEEED=@superfast; fi
elif [ $bitrate -le 2000 ]; then
MAXRATE=2000k; CRF=21; AUDIORATE=160k; VERT_RES=448; FASTDECODE=@fastdecode,;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@ultrafast; else SPEEED=@superfast; fi
else
MAXRATE=3000k; CRF=20; AUDIORATE=160k; VERT_RES=448; FASTDECODE=@fastdecode,;
if [ $VIDEO_HEIGHT -gt 480 ]; then SPEEED=@ultrafast; else SPEEED=@superfast; fi
fi
ASPECT=$(($VIDEO_WIDTH / $(($VIDEO_HEIGHT / 10))))
if [ $ASPECT -lt 15 ]; then
HOR_RES=$(($(($VERT_RES * 15)) / 10))
SCALE="-aspect $HOR_RES/$VERT_RES -vf scale=$HOR_RES:$VERT_RES"
elif [ $ASPECT -gt 18 ]; then
HOR_RES=$(($(($VERT_RES * 18)) / 10))
SCALE="-aspect $HOR_RES/$VERT_RES -vf scale=$HOR_RES:$VERT_RES"
else
SCALE="-vf scale=-2:$VERT_RES"
fi
INPUT_OPTIONS="$FASTDECODING -af volnorm -channels 2 -srate $SRATE"
AUDIO_ENCODING="-oac aac -oacopts b=$AUDIORATE"
VIDEO_ENCODING="-ovc libx264 -ovcopts $SPEEED,@film,${FASTDECODE}@baseline,level=30,threads=4,maxrate=$MAXRATE,bufsize=10000k,rc_init_occupancy=9800k,crf=$CRF"
#VIDEO_ENCODING="-ovc flv -ovcopts b=${bitrate}k"
OUTPUT_OPTIONS="$SCALE -sws 0 $FPS_OPTION -of flv"
# if we did not want different loggin options depending on streaming or not, we may be able to use use -o "${6-/dev/fd/3}"
if [ -z "$output" ]; then
echo "/opt/bin/mplayer -ss $offset \"$source\" $INPUT_OPTIONS $AUDIO_ENCODING $VIDEO_ENCODING $OUTPUT_OPTIONS -o /dev/fd/3 3>&1 1>>/var/subsonic/transcode/logs.log 2>>/var/subsonic/transcode/errors.log" >>/var/subsonic/transcode/logs.log
/opt/bin/mplayer -ss $offset "$source" $INPUT_OPTIONS $AUDIO_ENCODING $VIDEO_ENCODING $OUTPUT_OPTIONS -o /dev/fd/3 3>&1 1>>/var/subsonic/transcode/logs.log 2>>/var/subsonic/transcode/errors.log
else
echo "/opt/bin/mplayer -ss $offset \"$source\" $INPUT_OPTIONS $AUDIO_ENCODING $VIDEO_ENCODING $OUTPUT_OPTIONS -o \"$output\""
/opt/bin/mplayer -ss $offset "$source" $INPUT_OPTIONS $AUDIO_ENCODING $VIDEO_ENCODING $OUTPUT_OPTIONS -o "$output"
fi
Create a file /var/subsonic/transcode/streamflv and put the above code into it.
then make it executable with chmod 775 /var/subsonic/transcode/streamflv
You may want to test it first on command line. Try a command like this:
/var/subsonic/transcode/streamflv 0 <your source file> 1000 - - <your destination file.flv>
The first parameter is the offset into the video in seconds where to start encoding, the second the source file (provide double-quotes around it if the file name has spaces), the third paramter is the bitrate (will ajust encoding details in steps: 200, 300, 400, 500, 700, 1000, 1200, 1500, 2000 and above). The forth and fifth option are height and width, but those are ignored in this script currently and unless you need to provide the 6th parameter you can leave them out). The 6th parameter is the optional output file.
It should transcode and show you log output on the transcoding process. When you call it without the last parameter like you will do in subsonic, it will output the encoded video to standard out so subsonic can stream it on to the flash player.
If it works, you can configure the transcoding settings of subsonic:
Anywhere where it is about video encoding (where "Convert to" is "flv") you replace the existing content of "Step 1" with "streamflv %o %s %b %w %h".
Now, if streaming does not work, try restarting tomcat like this:
/etc/init.d/tomcat.sh restart
If it still does not work, first check the conents of
/var/subsonic/transcode/logs.log
and then
/var/subsonic/transcode/errors.log
For hints on what went wrong.
Please provide feedback if the instructions worked for you!
I wrote part of this right from the head and may have forgotten details.
Cheers!