Login
This website uses Launchpad for user authentication.
If you don't have an account there, you will be invited to create one on your first login here.
If you registered on this site before the installation of the Launchpad integration, you will have to log in manually and add the https://login.launchpad.net OpenID identities to your account.
Languages
How to write a wxPython video player with Gstreamer
wxPython ships by default with the wx.MediaCtrl for very basic playback of music or videos. As I would like to do more advanced video manipulation, I was curious if I could use Gstreamer directly in wxPython to create my own pipelines. It was surprisingly easy.
For those who don't know Gstreamer, I quote the website (http://www.gstreamer.org):
GStreamer is a library that allows the construction of graphs of media-handling components, ranging from simple playback to complex audio (mixing) and video (non-linear editing) processing. Applications can take advantage of advances in codec and filter technology transparently.
There are python bindings for it, of which the documentation can be found on http://pygstdocs.berlios.de
I would also suggest to read these introductions to gstreamer & python:
- Introducing Gstreamer
- Getting started with GStreamer with Python
- Using Gnonlin with GStreamer and Python
I translated the video player example 2.2 of the tutorial from pyGtk to wxPython:
http://pygstdocs.berlios.de/pygst-tutorial/playbin.html
It should be straightforward to use this as a base for implementing your own pipelines. I work on Ubuntu, where I could install everything straight from the standard repositories.
Here is the source code:
#!/usr/bin/env python
#Example 2.2 http://pygstdocs.berlios.de/pygst-tutorial/playbin.html
import sys, os
import wx
import pygst
pygst.require("0.10")
import gst
import gobject
gobject.threads_init()
class WX_Main(wx.App):
def OnInit(self):
window = wx.Frame(None)
window.SetTitle("Video-Player")
window.SetSize((500, 400))
window.Bind(wx.EVT_CLOSE,self.destroy)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.entry = wx.TextCtrl(window)
hbox.Add(self.entry, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
self.button = wx.Button(window,label="Start")
hbox.Add(self.button, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
self.button.Bind(wx.EVT_BUTTON, self.start_stop)
vbox.Add(hbox, 0, wx.EXPAND, 0)
self.movie_window = wx.Panel(window)
vbox.Add(self.movie_window,1,wx.ALL|wx.EXPAND,4)
window.SetSizer(vbox)
window.Layout()
window.Show()
self.SetTopWindow(window)
self.player = gst.element_factory_make("playbin", "player")
bus = self.player.get_bus()
bus.add_signal_watch()
bus.enable_sync_message_emission()
bus.connect('message', self.on_message)
bus.connect('sync-message::element', self.on_sync_message)
return True
def start_stop(self, event):
if self.button.GetLabel() == "Start":
filepath = self.entry.GetValue()
if os.path.exists(filepath):
self.button.SetLabel("Stop")
self.player.set_property('uri',"file://" + filepath)
self.player.set_state(gst.STATE_PLAYING)
else:
self.player.set_state(gst.STATE_NULL)
self.button.SetLabel("Start")
def on_message(self, bus, message):
t = message.type
if t == gst.MESSAGE_EOS:
self.player.set_state(gst.STATE_NULL)
self.button.SetLabel("Start")
elif t == gst.MESSAGE_ERROR:
self.player.set_state(gst.STATE_NULL)
self.button.SetLabel("Start")
def on_sync_message(self, bus, message):
if message.structure is None:
return
message_name = message.structure.get_name()
if message_name == 'prepare-xwindow-id':
imagesink = message.src
imagesink.set_property('force-aspect-ratio', True)
imagesink.set_xwindow_id(self.movie_window.GetHandle())
def destroy(self,event):
#Stop the player pipeline to prevent a X Window System error
self.player.set_state(gst.STATE_NULL)
event.Skip()
app = WX_Main()
app.MainLoop()