thefoundationhttp://www.thefoundation.de2010-07-01T22:53:07Z(c) 2012 Michael Kurze, Aachen, GermanyQuickTime Reference Movies in Python2010-07-01T22:53:07ZDavid Murmannhttp://www.thefoundation.de/about/davidquicktime-reference-movies-python<p>HTML5 video is on its way, and Apple likes to use reference movies to
send different versions of movies to different clients. So, how do
you generate these if you don't have OSX handy (for example on a
server)?
</p><p>This is pretty much the premise of a little tool I wrote to generate
QuickTime reference movies. It is written in Python, because it is to
be used in a Django app that handles video uploads and encodes. Well,
that and because I <em>love</em> Python! There isn't much else to say, so here
is the code if you are interested:</p>
<p><code class="block">hg clone http://bitbucket.org/dmurmann/root pyqtref</code></p>
<p class="annotation notice center">This is very much alpha software, it may fail horribly for you!</p>
<p>The simplest possible example, generating a reference movie to 'content.mov' looks like this:</p>
<p><code class="block">from pyqtref import *
ref_mov = Movie(ReferenceMovie(Descriptor(
DataReference('content.mov')))).to_bytes()</code></p>
<p>The boilerplate is necessary, because the API is pretty close to the <a href="http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25756">Quicktime File Format Specification</a>.</p>
Here comes the Zoom2009-01-13T01:04:10ZDavid Murmannhttp://www.thefoundation.de/about/davidhere-comes-zoom<p>PFTrack does Blender... or does it? The Blender Python script export feature of PFTrack is missing a vital component.</p><p>Usually I am very impressed with the quality and speed of PFTrack's implementation. The more it shocked me to find out that even in the latest version I tested, the Blender export is broken: It does not contain any camera zoom data, i.e. if your shot does not have a fixed focal length you effectivly cannot use Blender to continue your work. This bugged me so much that I circumvented the problem a different way. Instead of directly exporting as a Blender script, I exported the data in PFTrack's Human Readable ASCII format, which contains the wanted camera lens data, and wrote a Blender import script for this format. This works really well and fits even better into Blender, because the steps of loading the script into the Blender text editor and executing it there are replaced by a simple import (if you install the importer in your .blender/scripts folder).</p>
<p>You can find the script in <a href="http://blenderartists.org/forum/showthread.php?t=102510">this post</a> on blenderartists.org.</p>
Using ffmpeg in Python2008-09-11T16:18:32ZDavid Murmannhttp://www.thefoundation.de/about/davidusing-ffmpeg-python<p>Or: how to effectively use other peoples work...
</p><p>First some background: A while ago I wrote a simple Python script that
processed a sequence of images in some specific way. I used the <a
href="http://effbot.org/zone/pil-index.htm">PIL</a> to open the
images, then do the transformation and write a sequence of images
again. It quickly became apparent that there was significant overhead
involved in dealing with larger sequences (>10000 files), especially
for some OS/filesystem combinations. The slowest of these was probably
the OSX Finder trying to access such a directory over SMB, switching
to AFP helped a lot there.</p>
<p>To get rid of the need to use (at least one of) these image sequences at all,
I decided to redo the reading part of the script to use ffmpeg to read
the frames from a quicktime file. As it stands there are some attempts
to wrap ffmpeg in Python (see <a
href="http://pymedia.org/">PyMedia</a>, <a
href="http://code.google.com/p/pyffmpeg/">PyFFmpeg</a>), but they
seemed to be outdated or weren't compiling on my 64bit machine. So, I
went ahead to try a ctypes-based approach on my own, which, as it
turns out, is really easy. I don't want to bore you with the details
of what I tried, here just comes the summary of what worked well:</p>
<p>First some prerequisites that you might not have:
<code class="block">sudo apt-get install gccxml libavcodec-dev \
libavformat-dev libswscale-dev libavfilter-dev \
libavdevice-dev libpostproc-dev</code>
Next is the tool that makes everything incredibly simple: ctypeslib.
<code class="block">svn co http://svn.python.org/projects/ctypes/trunk/ctypeslib</code>
Note that the trunk version of ctypeslib only works well with older versions
of gccxml (like 0.7), if you have a newer version, get the following branch:
<code class="block">svn co http://svn.python.org/projects/ctypes/branches/ctypeslib-gccxml-0.9</code>
After that a simple
<code class="block">sudo ./setup.py install</code>
should give you a working h2xml.py and xml2py.py. With these you can
generate ctypes wrappers:
<code class="block">h2xml.py -c -I/usr/include/ffmpeg libavcodec/avcodec.h \
libavformat/avformat.h libswscale/swscale.h \
libavdevice/avdevice.h libavfilter/avfilter.h \
libpostproc/postprocess.h -o av.xml
xml2py.py av.xml -o av.py -l libavcodec.so -l libavformat.so \
-l libswscale.so -l libavdevice.so -l libavfilter.so \
-l libpostproc.so
</code>
If that worked you can use ffmpeg in Python like this:
<code class="block">from av import *
av_register_all()
pFormatCtx = POINTER(AVFormatContext)()
if av_open_input_file(pFormatCtx, filename, None, 0, None):
handle_error("could not open file")
... (insert your usual ffmpeg code, examples <a
href="http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html">here</a> and <a href="http://www.inb.uni-luebeck.de/~boehme/libavcodec_update.html">here</a>) ...
</code></p>
<p>Up to now I only found two things that I needed that weren't converted
correctly by ctypeslib. The first were some defines, which could
probably be done right but I didn't need many so I just added them by
hand. The second was this inline function
<code class="block">static inline void av_free_packet(AVPacket *pkt)
{
if (pkt && pkt->destruct) {
pkt->destruct(pkt);
}
}
</code>
which I replaced by this definition (to be called with an AVPacket
object instead of a pointer to one):
<code class="block">def av_free_packet(pkt):
if pkt and pkt.destruct:
pkt.destruct(byref(pkt))
</code>
With a little bit of scripting to convert the ffmpeg decoded frame to
a PIL image the script can now read anything ffmpeg can read. All
thats left to do is encode the output with ffmpeg, once that is done I
might post this as a module that encapsules the conversion from
ffmpeg to PIL image sequence and back.</p>
<p><em>Last update on: Thursday, 9th October, 2008</em></p>