wxPython Plays Audio and Video Files

vegaseat 2 Tallied Votes 4K Views Share

An example showing how to use the wx.media.MediaCtrl() widget to play MIDI, MP3, WAV, AU, AVI and MPG audio and video files. I have only tested it with Windows. If you are very ambitious, you could use a random graphics display with the sound, or tie the slider position to a slide presentation.

# experiment with wxPython's
# wx.media.MediaCtrl(parent, id, pos, size, style, backend)
# the backend (szBackend) is usually figured by the control
# wxMEDIABACKEND_DIRECTSHOW   Windows
# wxMEDIABACKEND_QUICKTIME    Mac OS X
# wxMEDIABACKEND_GSTREAMER    Linux (?)
# plays files with extension .mid .mp3 .wav .au .avi .mpg
# tested with Python24 and wxPython26 on Windows XP   vegaseat  10mar2006

import wx
import wx.media
import os

class Panel1(wx.Panel):
    def __init__(self, parent, id):
        #self.log = log
        wx.Panel.__init__(self, parent, -1, style=wx.TAB_TRAVERSAL|wx.CLIP_CHILDREN)

        # Create some controls
        try:
            self.mc = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER)
        except NotImplementedError:
            self.Destroy()
            raise

        loadButton = wx.Button(self, -1, "Load File")
        self.Bind(wx.EVT_BUTTON, self.onLoadFile, loadButton)
        
        playButton = wx.Button(self, -1, "Play")
        self.Bind(wx.EVT_BUTTON, self.onPlay, playButton)
        
        pauseButton = wx.Button(self, -1, "Pause")
        self.Bind(wx.EVT_BUTTON, self.onPause, pauseButton)
        
        stopButton = wx.Button(self, -1, "Stop")
        self.Bind(wx.EVT_BUTTON, self.onStop, stopButton)

        slider = wx.Slider(self, -1, 0, 0, 0, size=wx.Size(300, -1))
        self.slider = slider
        self.Bind(wx.EVT_SLIDER, self.onSeek, slider)
        
        self.st_file = wx.StaticText(self, -1, ".mid .mp3 .wav .au .avi .mpg", size=(200,-1))
        self.st_size = wx.StaticText(self, -1, size=(100,-1))
        self.st_len  = wx.StaticText(self, -1, size=(100,-1))
        self.st_pos  = wx.StaticText(self, -1, size=(100,-1))
        
        # setup the button/label layout using a sizer
        sizer = wx.GridBagSizer(5,5)
        sizer.Add(loadButton, (1,1))
        sizer.Add(playButton, (2,1))
        sizer.Add(pauseButton, (3,1))
        sizer.Add(stopButton, (4,1))
        sizer.Add(self.st_file, (1, 2))
        sizer.Add(self.st_size, (2, 2))
        sizer.Add(self.st_len,  (3, 2))
        sizer.Add(self.st_pos,  (4, 2))
        sizer.Add(self.mc, (5,1), span=(5,1))  # for .avi .mpg video files
        self.SetSizer(sizer)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer.Start(100)
        
    def onLoadFile(self, evt):
        dlg = wx.FileDialog(self, message="Choose a media file",
                            defaultDir=os.getcwd(), defaultFile="",
                            style=wx.OPEN | wx.CHANGE_DIR )
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.doLoadFile(path)
        dlg.Destroy()
        
    def doLoadFile(self, path):
        if not self.mc.Load(path):
            wx.MessageBox("Unable to load %s: Unsupported format?" % path, "ERROR", wx.ICON_ERROR | wx.OK)
        else:
            folder, filename = os.path.split(path)
            self.st_file.SetLabel('%s' % filename)
            self.mc.SetBestFittingSize()
            self.GetSizer().Layout()
            self.slider.SetRange(0, self.mc.Length())
            self.mc.Play()
        
    def onPlay(self, evt):
        self.mc.Play()
    
    def onPause(self, evt):
        self.mc.Pause()
    
    def onStop(self, evt):
        self.mc.Stop()
    
    def onSeek(self, evt):
        offset = self.slider.GetValue()
        self.mc.Seek(offset)

    def onTimer(self, evt):
        offset = self.mc.Tell()
        self.slider.SetValue(offset)
        self.st_size.SetLabel('size: %s ms' % self.mc.Length())
        self.st_len.SetLabel('( %d seconds )' % (self.mc.Length()/1000))
        self.st_pos.SetLabel('position: %d ms' % offset)


app = wx.PySimpleApp()
# create a window/frame, no parent, -1 is default ID
frame = wx.Frame(None, -1, "play audio and video files", size = (320, 350))
# call the derived class
Panel1(frame, -1)
frame.Show(1)
app.MainLoop()
ananthram90 0 Newbie Poster

The slider doesnt work, any idea how to make the slider work?

wise_stam 0 Newbie Poster

heya, this is a reli good piece of work, but im having a bit of a problem.. the actual video doesn't appear when i pressed play, only the sound was playing, but if I resize the window (like dragging the edge to stretch the window), the video displays straight away... did this happen to anyone else? Is this possibly a bug with the new python 2.6? Any suggestions/advices on how to fix this?
Thanks ever so much :)

sarosh 0 Newbie Poster

ya the play problem is with me too
were u able to fix it? if yes how?
may b some problem with size i guess

n about slider

slider = wx.Slider(self, -1, 0,0.0001,3000, pos=(120,680), style = wx.SL_HORIZONTAL | wx.SL_LABELS, size = (400, -1))

is working well, just dont write 0,0,0 as 3rd , fourth n fifth aurgument.. and 5th onle shud b long enuf till length of ur video!

vnasery 0 Newbie Poster

The player seems to be working fine for me in Ubuntu 12.04 but the video looks upside down!

sneekula 969 Nearly a Posting Maven

wxMediaCtrl uses native backends to render media,
for example on Windows there is a ActiveMovie/DirectShow backend,
and on Macintosh there is a QuickTime backend

backend options:.

wx.MEDIABACKEND_GSTREAMER    for linux/unix
wx.MEDIABACKEND_QUICKTIME       for Mac 
viggie 0 Newbie Poster

Hi,

I used this code for my project at the university but I am unable to play some videos even though they are .avi format!

Is there any bug that i should resolve for this ?

bunkus 0 Newbie Poster

if you want to play video files this code should work:

from __future__ import print_function
import wx
import wx.media
import os

#----------------------------------------------------------------------

class StaticText(wx.StaticText):
    """
    A StaticText that only updates the label if it has changed, to
    help reduce potential flicker since these controls would be
    updated very frequently otherwise.
    """
    def SetLabel(self, label):

        if label <> self.GetLabel():
            wx.StaticText.SetLabel(self, label)

#----------------------------------------------------------------------

class TestPanel(wx.Panel):

    def __init__(self, parent):

        wx.Panel.__init__(self, parent, -1,
                          style=wx.TAB_TRAVERSAL|wx.CLIP_CHILDREN)
        # Create some controls
        try:
            self.mc = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER,
                                         szBackend=wx.media.MEDIABACKEND_DIRECTSHOW
                                         #szBackend=wx.media.MEDIABACKEND_QUICKTIME
                                         #szBackend=wx.media.MEDIABACKEND_WMP10

                                         )
        except NotImplementedError:
            self.Destroy()
            raise
        # print(dir(self.mc))
        self.video_size = parent.GetSize()
        self.Bind(wx.media.EVT_MEDIA_LOADED, self.OnMediaLoaded)
        loadButton = wx.Button(self, -1, "Load File")
        self.Bind(wx.EVT_BUTTON, self.OnLoadFile, loadButton)
        playButton = wx.Button(self, -1, "Play")
        self.Bind(wx.EVT_BUTTON, self.OnPlay, playButton)
        self.playBtn = playButton
        pauseButton = wx.Button(self, -1, "Pause")
        self.Bind(wx.EVT_BUTTON, self.OnPause, pauseButton)
        stopButton = wx.Button(self, -1, "Stop")
        self.Bind(wx.EVT_BUTTON, self.OnStop, stopButton)
        self.slider = wx.Slider(self, -1, 0, 0, 0)
        self.slider.SetMinSize((self.video_size[0]-15, -1))
        self.Bind(wx.EVT_SLIDER, self.OnSeek, self.slider)
        self.st_size = StaticText(self, -1, size=(100,-1))
        self.st_len  = StaticText(self, -1, size=(100,-1))
        self.st_pos  = StaticText(self, -1, size=(100,-1))
        self.st_file = StaticText(self, -1, ".mid .mp3 .wav .au .avi .mpg", size=(200,-1))
        Bsizer = wx.BoxSizer(wx.VERTICAL)
        Lsizer = wx.BoxSizer(wx.HORIZONTAL)
        Lsizer.Add(loadButton, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
        Lsizer.Add(self.st_file, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
        Bsizer.Add(Lsizer)
        Bsizer.Add(self.mc, 1, wx.ALL, 5) # for .avi .mpg video files
        Bsizer.Add(self.slider)
        bsizer = wx.BoxSizer(wx.HORIZONTAL)
        bsizer.Add(playButton, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
        bsizer.Add(pauseButton, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
        bsizer.Add(stopButton, 0, wx.ALL|wx.ALIGN_RIGHT, 5)
        Bsizer.Add(bsizer)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.st_size, 0, wx.ALL|wx.ALIGN_RIGHT, 7)
        sizer.Add(self.st_len, 0, wx.ALL|wx.ALIGN_RIGHT, 7)
        sizer.Add(self.st_pos, 0, wx.ALL|wx.ALIGN_RIGHT, 7)
        Bsizer.Add(sizer)
        self.SetSizer(Bsizer)
        filename = "data/toy.mp4"
        if os.path.isfile(filename):
            wx.CallAfter(self.DoLoadFile, os.path.abspath(filename))
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.timer.Start(100)

    def OnLoadFile(self, evt):
        dlg = wx.FileDialog(self, message="Choose a media file",
                            defaultDir=os.getcwd(), defaultFile="",
                            style=wx.OPEN | wx.CHANGE_DIR )
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.DoLoadFile(path)
        dlg.Destroy()

    def DoLoadFile(self, path):
        #self.playBtn.Disable()
        if not self.mc.Load(path):
            wx.MessageBox("Unable to load %s: Unsupported format?" % path,
                          "ERROR",
                          wx.ICON_ERROR | wx.OK)
        else:
            folder, filename = os.path.split(path)
            self.st_file.SetLabel('%s' % filename)
            self.mc.SetInitialSize(self.video_size)
            self.GetSizer().Layout()
            self.slider.SetRange(0, self.mc.Length())

    def OnMediaLoaded(self, evt):
        self.playBtn.Enable()

    def OnPlay(self, evt):
        if not self.mc.Play():
            wx.MessageBox("Unable to Play media : Unsupported format?",
                          "ERROR",
                          wx.ICON_ERROR | wx.OK)
        else:
            self.mc.SetInitialSize(self.video_size)
            self.GetSizer().Layout()
            self.slider.SetRange(0, self.mc.Length())

    def OnPause(self, evt):
        self.mc.Pause()

    def OnStop(self, evt):
        self.mc.Stop()

    def OnSeek(self, evt):
        offset = self.slider.GetValue()
        self.mc.Seek(offset)

    def OnTimer(self, evt):
        offset = self.mc.Tell()
        self.slider.SetValue(offset)
        self.st_size.SetLabel('size: %s' % self.mc.Length())
        self.st_len.SetLabel('length: %d seconds' % (self.mc.Length()/1000))
        self.st_pos.SetLabel('position: %d' % offset)

    def ShutdownDemo(self):
        self.timer.Stop()
        del self.timer

app = wx.App(0)
frame = wx.Frame(None, size=(640, 480))
panel = TestPanel(frame)
frame.Show()
app.MainLoop()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.