[theora] python bindings to libtheora

Ondrej Certik ondrej at certik.cz
Sun Jun 14 03:05:09 PDT 2009


Hi,

in the past two days I wrote Python bindings to libtheora:

http://github.com/certik/python-theora

Currently it can read any ogv file (that seems to work quite well) and
also encode to ogv (this mostly works, but there are some subtle
issues to be fixed, I suspect I still have some bug in the way I half
the dimensions of the Cb and Cr planes, so when you read ogv and write
ogv, the resulting image is not exactly pixelwise exact).

Here is an example how to read bbb_theora_325kbit.ogv, seek to 10s and
convert the next 10s to a new a.ogv:

--------------------
from theora import Theora, TheoraEncoder

a = Theora("bbb_theora_325kbit.ogv")
b = TheoraEncoder("a.ogv", a.width, a.height, quality=63)
a.seek(time=10)
while a.read_frame() and a.time < 20:
    A = a.get_frame_array()
    b.write_frame(A)
-----------------------

And here is another example that shows an interactive usage in
ipython, that reads tw.ogv, reads 2 frames, then gets the image data
as a numpy array (this is the YCbCr colors), then ask to return it as
a PIL (python imaging library) image and saves it to disk as png.

---------------
    In [1]: from theora import Theora

    In [2]: t = Theora("tw.ogv")

    In [3]: t
    Out[3]: <theora.Theora object at 0x23484c0>

    In [4]: print t
    ------> print(t)
    <Ogg logical stream 5ba555da is Theora 320x240 29.97 fps video,
encoded frame
    content is 320x240 with 0x0 offset, aspect is 0:0>

    In [5]: t.read_frame()
    Out[5]: True

    In [6]: t.read_frame()
    Out[6]: True

    In [7]: t.get_frame_data()
    Out[7]:
    [array([[17, 17, 17, ..., 17, 17, 17],
           [17, 17, 17, ..., 17, 17, 17],
           [17, 17, 17, ..., 17, 17, 17],
           ...,
           [17, 17, 17, ..., 17, 17, 17],
           [17, 17, 17, ..., 17, 17, 17],
           [17, 17, 17, ..., 17, 17, 17]], dtype=uint8),
     array([[128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128],
           ...,
           [128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128]], dtype=uint8),
     array([[128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128],
           ...,
           [128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128],
           [128, 128, 128, ..., 128, 128, 128]], dtype=uint8)]

    In [8]: img = t.get_frame_image()

    In [9]: img.save("b.png")
-----------------

There are also utilities for converting between YCbCr and RGB, etc.
See also the docstrings of the methods.

I am sending it here in case someone would like to help out, or test
it already. My next plan is to incorporate sound in there, I guess
Vorbis, I am not sure yet how tricky this will be, but once I have it
working, it will be possible to write my video editing pipeline as a
simple python script, e.g. it is now trivial to add some text or do
anything with the images, see for example:

http://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html

Also here is a script to show the image in matplotlib:

In [1]: from theora import Theora

In [2]: a = Theora("bbb_theora_325kbit.ogv")

In [3]: a.seek(10)

In [4]: A = a.get_frame_array()

In [5]: import pylab

In [6]: pylab.imshow(a.YCbCr2RGB(A))
Out[6]: <matplotlib.image.AxesImage object at 0x44e3510>

In [7]: pylab.show()

[and a window pops up with the image]

So as you can see, it's very trivial to open the ogv file and then
interactively play with it in Python, retreive the data as an arary
and then do all kinds of things with that. For example if you want to
join more files, simply open several Theora() instances, read the
frames in the order you want, and then feed them to the
TheoraEncoder() instance.

I would be interested in any comments with regards to the interface.
For example, it seems to me the standard YCbCr plane that
get_frame_array() returns is not so useful, I almost always
immediatelly call the conversion method YCbCr2RGB() right after it, so
that I can display the image.

Btw, here is the motivation why I need that:

http://groups.google.com/group/sympy/browse_thread/thread/dce8359b92eef874

I simply wanted to create a video tutorial, but I didn't manage to
simply join audio + video together, without loosing quality etc.
Neither could others btw., as you can see from the posts (the best
thing we can do is something that only works with some players and it
doesn't work on my ubuntu...). So I realized I need firm control of
what is happening, and theora so far is giving me this control and it
just works. The only remaning part is sound, I'll work on this soon.

Ondrej


More information about the theora mailing list