Python and libcheese, the simple way of dealing with camera devices

GStreamer does assembling advanced video application quite easy, in fact so easy that even I can write such an application in Python :) What I have had a lot more issues with is understanding how to deal with things like USB cameras and such. Well luckily the developers of Cheese realized this and created libcheese to help. libcheese is today used by Cheese itself of course, but also by Empathy for its camera handling.

Since I been thinking about adding some kind of video recording support in Transmageddon I wanted to test libcheese from Python. Unfortunately there was no Python examples available anywhere online, so I had write my own example :)
With some pointers from David King I managed to put the following python code together.

import sys
from gi.repository import Gtk
from gi.repository import Cheese
from gi.repository import Clutter
from gi.repository import Gst
Gst.init(None)
Clutter.init(sys.argv)

class VideoBox():
   def __init__(self):
    self.stage = Clutter.Stage()
    self.stage.set_size(400, 400)
    self.layout_manager = Clutter.BoxLayout()
    self.textures_box = Clutter.Actor(layout_manager=self.layout_manager)
    self.stage.add_actor(self.textures_box)

    self.video_texture = Clutter.Texture.new()

    self.video_texture.set_keep_aspect_ratio(True)
    self.video_texture.set_size(400,400)
    self.layout_manager.pack(self.video_texture, expand=False, x_fill=False, y_fill=False, x_align=Clutter.BoxAlignment.CENTER, y_align=Clutter.BoxAlignment.CENTER)

    self.camera = Cheese.Camera.new(self.video_texture, None, 100, 100)
    Cheese.Camera.setup(self.camera, None)
    Cheese.Camera.play(self.camera)

    def added(signal, data):
        uuid=data.get_uuid()
        node=data.get_device_node()
        print "uuid is " +str(uuid)
        print "node is " +str(node)
        self.camera.set_device_by_device_node(node)
        self.camera.switch_camera_device()

    device_monitor=Cheese.CameraDeviceMonitor.new()
    device_monitor.connect("added", added)
    device_monitor.coldplug()

    self.stage.show()
    Clutter.main()
if __name__ == "__main__":
    app = VideoBox()

The application creates a simple clutter window to host the stream from the webcam. So when you run the application it should display the video from the system webcam. Then if you plug a second webcam into a USB port it will switch the video feed to that stream. Not a very useful application in itself, but hopefully enough to get you started on using libcheese from Python. You can find the libcheese API docs here, they are for C, but Python API from Gobject Introspection follows it so close that you should be able to find the right calls. And remember for figuring out exact API names ipython is your friend :)

P.S. You need Cheese 3.6 installed to be able to use libcheese with Python, this version which will be in Fedora starting with Fedora 18.

4 thoughts on “Python and libcheese, the simple way of dealing with camera devices”

  1. you should not use Clutter.Box – it’s deprecated since Clutter 1.10. you can use Clutter.Actor directly, as it’s not an abstract class any more, and any actor can use a delegate LayoutManager to lay out children. just do:

    self.textures_box = Clutter.Actor(layout_manager=self.layout_manager)

    also, don’t use the Clutter.BoxLayout.pack() method if you have Clutter 1.12 installed (it comes with GNOME 3.6). Clutter.Actor has expand and alignment properties, like GtkWidget in gtk+ 3.x, so you just need to set them on the actor and call add_child().

    finally, Clutter.Texture has been deprecated in 1.12, but that will require new API in libcheese; there is some work to move the video capture API in Clutter-GStreamer directly as well.

    1. Thanks Emmanuele, tried updating the code above with some of your suggestions. The clutter code was just something I found online and just hammered on until I got something showing on screen, so very little thought went into it :)

Comments are closed.