The methods described on this page are based on a blog entry by Daniel Tietze, who uses Django and FFmpeg to play Video files on his web pages.
PassThru or OS_Process
Handling video files as outlined in this document can only be done through the use of command line applications. These were accessed by installing and using Steffan Clines PassThru tag for older versions of Lasso, or alternatively by using OS_Process in Lasso version 8.5 and newer.
Installing LAME encoder
This section on the installation of the LAME MP3 encoder has been reproduced with kind permission by Stephen Jungels from his article on FFmpeg on Mac OS X How-to.
Although it's not documented anywhere, FFmpeg will silently ignore audio streams when converting to Flash Video, if you do not have the LAME MP3 encoder installed. Other codecs, like mp2, just don't work. I don't know if this is a limitation of FFmpeg or of Flash Video, but it is easy enough to fix by installing LAME. In this case FFmpeg is going to need include files, so it is not enough to install a prebuilt binary.
Start by creating a working directory:
mkdir ~/lame cd ~/lame
On a good day you can get the latest source code release of LAME from Sourceforge. The file you want will be named lame-3.97.tar.gz or something similar. If you download the tar file, you need to unpack it as follows:
tar xvzf lame-3.97.tar.gz
After downloading and unpacking the source, change to the main directory and do the usual install procedure:
cd lame-3.97
./configure
make
sudo make install
Install faad encoder
Quicktime movies, such as the ones produced by iMovie, may cause problems with ffmpeg reporting errors about "negative ctts". As it happens, the "negative ctts" is not actually a problem - the real error lies in the codec ffmpeg is trying to use. Having previously compiled ffmpeg with the LAME mp3 libraries, it turns out that we need another library to deal with these Quicktime files. Thanks to Rich Fortnum for pointing this out!
This problem is addressed by installing the faad libraries, which are available from http://packages.debian.org/unstable/sound/faad. Personally, I simply downloaded the package "faad2_2.6.orig.tar.gz" and unpacked it. Once you've done that, cd into the resulting directory and perform the usual install procedure from the Terminal:
./configure
make
sudo make install
That should be it, libfaad is ready to be included in your ffmpeg build.
Building FFmpeg
As of July 24, 2006, the latest version of FFmpeg from the Subversion repository builds and runs on OS X 10.4 as well as OS X 10.3 (tested by yours truly). However, I recently (November 2007) found that building on OSX 10.3 Server reported several errors, notably an error about "ffmpeg-doc.html". Fortunately, this did not stop the build from being successful, so I decided to ignore the errors, which appear to relate to the installation of the docs. Who reads them, anyway?
In January 2008, while trying to build on OS X Server 10.5 on my new Intel Xserve, the build failed miserably. Chris Waltham on the Apple macosx-server List supplied the solution - we need to add the --disable-mmx flag to ./configure in order to, you guessed it, disable MMX support.
FFmpeg is available from http://ffmpeg.mplayerhq.hu/download.html. I prefer to fetch the source with Subversion. First create a working directory:
mkdir ~/ffmpeg cd ~/ffmpeg
Use Subversion to retrieve the source and cd into the main directory:
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg cd ffmpeg
It is of course possible that an earlier version of FFmpeg is already installed on your system. This may well cause problems, such as unsupported codec errors. The solution is to perform a clean recompile to ensure that FFmpeg will work with LAME and faad. The --enable-gpl parameter is there to keep the faad libraries happy.
./configure --enable-libmp3lame --enable-static --disable-vhook --enable-libfaad --enable-gpl --disable-mmx make clean make sudo make install
Note that various instructions online refer to --enable-mp3lame but this no longer works - make sure to use --enable-libmp3lame instead.
It is outside the scope of these instructions to explain how to upload files to your server. Let's just assume that you have a Quicktime movie, MPEG or even .wmv file somewhere on your server.
Using PassThru, FFmpeg and a bit of RegExp, we can retrieve some useful information from such a file:
[PassThru('/usr/local/bin/ffmpeg -i "/path/to/myfile.mov"')]
This will return something like the following:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/path/to/myfile.mov': Duration: 00:00:24.4, start: 0.000000, bitrate: 991 kb/s Stream #0.0(eng): Video: mpeg4, yuv420p, 320x240, 23.95 fps(r) Stream #0.1(eng): Audio: pcm_mulaw, 8000 Hz, mono, 64 kb/s Must supply at least one output file
Note the reference to the video file's frame rate, indicated in the example above as 23.95 fps(r), in other words, 24-ish Frames per Second. In newer versions of ffmpeg, this framerate is referred to less intuitively as 23.95 tb(r).
[ //Establish if the file is Video, Audio, or Unsupported: if((string_findregexp:#movie_info, -find='Video') -> size > 0); local('filetype'='Video'); else((string_findregexp:#movie_info, -find='Audio') -> size > 0); local('filetype'='Audio'); else; local('filetype'='Unknown'); /if; //Declare variables for Video-Specific details local('dimensions' = string); local('width' = string); local('height' = string); local('fps' = string); if:(#filetype [h1] 'Video'); local:'dimensions_temp' = (string_findregexp: #movie_info, -find='Video: [^x]*x[^,]*'); local:'fps_temp' = (string_findregexp: #movie_info, -find='Video:[^t]* tb\\(r\\)|Video:[^f]* fps'); #fps = (#fps_temp -> get:1 -> split:' '); local:'fps_x'=(#fps -> size); #fps = (#fps -> get:(#fps_x - 1)); local:'dimensions_array' = (array); if:(#dimensions_temp -> size > 0); #dimensions_array = (string_findregexp:(#dimensions_temp -> get:1), -find='(\\d+)x(\\d+)'); /if; if:(#dimensions_array -> size [h1] 3); #dimensions = (#dimensions_array -> get: 1); #width = (#dimensions_array -> get: 2); #height = (#dimensions_array -> get: 3); /if; /if; //Declare variables for general audio/video details local:'duration_temp' = (string_findregexp: #movie_info, -find='Duration: [^ ,]*'); local:'duration_display' = string; local:'duration' = decimal; local:'seconds' = decimal; local:'halftime' = duration; if:(#duration_temp -> size > 0); #duration_display = (string_removeleading:(#duration_temp -> get:1), -pattern='Duration: '); #seconds = #duration_display -> split:':' -> last; #duration_display=(duration:#duration_display); //calculate duration in seconds with decimal value to accurately grab frame interval rate #duration = (#duration_display->second); #duration = (#duration - (integer:#seconds)); #duration = (decimal:#duration) + (decimal:#seconds); #halftime = (duration(integer(#duration / 2))); /if; ] Using the example, the above code will give us the following locals: #filetype: Video #duration: 24.4 #duration_display: 00:00:24 #seconds: 24.4 #halftime: 00:00:12 #dimensions: 320x240 #width: 320 #height: 240 #fps: 23.95
NOTE: Instead of using PassThru, I have started using OS_Process for some of my cli stuff - but unfortunately OS_Process causes problems when trying to call ffmpeg, in that OS_Process should be explicitly told to retrieve the error, rather than the output, from the ffmpeg command.
The next big requirement will be to display the video in a browser and to that end, we convert it to Flash video format, FLV. Again, PassThru and FFmpeg come to the rescue. Note that we re-use some of the locals from the above example. Also, the .flv file does not exist yet, and you will obviously use vars or locals to set the name of the file.
local('passthrucommand' = ('/usr/local/bin/ffmpeg -i /path/to/myfile.mov ')); #passthrucommand += (' -ar 22050 -ab 32 -f flv -s '+#width+'x'+#height); #passthrucommand += (/path/to/myfile.flv'); passthru(#passthrucommand);
NOTE: ffmpeg will choke on frame sizes that are not a multiple of 2, so make sure to cast the width and height values (if different from the original) to the nearest even number! You could achive this as follows:
[ #width % 2 > 0 ? #width += 1; #height % 2 > 0 ? #height += 1; ]
FFmpeg can extract single frames from a video stream, storing them in still image format. In our example we calculated a "half-time" value for the video file, and we now use this local to grab a frame from the middle of the clip and turn it into a thumbnail:
Local('PassThruCommand2' = ('/usr/local/bin/ffmpeg -y -i /path/to/myfile.mov ')); #PassThruCommand2 += ('-vframes 1 -ss '+(duration(#halftime))); #PassThruCommand2 += (' -an -vcodec png -f rawvideo '); #PassThruCommand2 += (' -s '+#width+'x'+#height+' /path/to/myfile.png'); PassThru(#PassThruCommand2);
Make sure to read the note on frame sizes above...!
Last but not least, we want to play our video file on a web page similar to YouTube and Google Video. For this, we need to embed a Flash Video player in the webpage. I use FlowPlayer, which is available from http://flowplayer.sourceforge.net/. That page provides ample documentation on how to implement and customise FlowPlayer, all I need to say is that its simplicity itself. The most basic implementation requires no more than the presence of the flowplayer.swf file where it can be accessed by the relevant webpage, plus a chunk of code to embed the object and tell the flowplayer.swf file where to get its video file from:
<object type="application/x-shockwave-flash" data="/path/to/FlowPlayer.swf" width="[#width]" height="[#height]" id="FlowPlayer"> <param name="allowScriptAccess" value="sameDomain" /> <param name="movie" value="/path/to/FlowPlayer.swf" /> <param name="quality" value="high" /> <param name="scale" value="noScale" /> <param name="wmode" value="transparent" /> <param name="flashvars" value="config={ videoFile: '/webroot/path/to/myfile.flv', loop: false, autoPlay: false }" /> </object>
Author: Pier Kuipers
Created: 1 Mar 2007
Last Modified: 16 Mar 2011
Please note that periodically LassoSoft will go through the notes and may incorporate information from them into the documentation. Any submission here gives LassoSoft a non-exclusive license and will be made available in various formats to the Lasso community.
©LassoSoft Inc 2015 | Web Development by Treefrog Inc | Privacy | Legal terms and Shipping | Contact LassoSoft