Phoenix
Phoenix copied to clipboard
wx.MediaCtrl hangs for several seconds before it starts playing on Linux
Operating system: Linux Mint 21 (based on Ubuntu 22.04) wxPython version & source: 4.2.0 from https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-22.04 Python version & source: 3.10.4 from Mint distribution
Description of the problem: When I run the MediaCtrl example from the wxPython demo there is a delay of several seconds from pressing the Play button until the video actually starts playing. On my 10 year old PC it takes about 6 seconds to start, on my more powerful 1 year old PC it takes 3 - 4 seconds.
If I wait several seconds after a video has loaded and then press Play, it sometimes plays a few frames from the video and then freezes for the usual delay period, before playing normally.
If I let the video run through to the end and press Play again, the delay happens again. However, if I stop or pause the video part way through and then press Play, the delay doesn't happen.
I have tested this with several different video files and a delay happens with all of them
Code Example (click to expand)
The following code was copied from wxPython demo and modified to run standalone. It also disables the Play button until an EVT_MEDIA_LOADED event has been triggered. However, this doesn't prevent the delay from occurring.
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:
backend = "" # let MediaCtrl choose default backend
#backend=wx.media.MEDIABACKEND_DIRECTSHOW
#backend=wx.media.MEDIABACKEND_WMP10
#backend = wx.media.MEDIABACKEND_GSTREAMER
self.mc = wx.media.MediaCtrl()
ok = self.mc.Create(self, style=wx.SIMPLE_BORDER,
szBackend=backend)
if not ok:
raise NotImplementedError
except NotImplementedError:
self.Destroy()
raise
# the following event is not sent with the Windows default backend
# MEDIABACKEND_DIRECTSHOW
# choose above e.g. MEDIABACKEND_WMP10 if this is a problem for you
self.Bind(wx.media.EVT_MEDIA_LOADED, self.OnMediaLoaded)
btn1 = wx.Button(self, -1, "Load File")
self.Bind(wx.EVT_BUTTON, self.OnLoadFile, btn1)
btn2 = wx.Button(self, -1, "Play")
self.Bind(wx.EVT_BUTTON, self.OnPlay, btn2)
self.playBtn = btn2
btn3 = wx.Button(self, -1, "Pause")
self.Bind(wx.EVT_BUTTON, self.OnPause, btn3)
btn4 = wx.Button(self, -1, "Stop")
self.Bind(wx.EVT_BUTTON, self.OnStop, btn4)
slider = wx.Slider(self, -1, 0, 0, 10)
self.slider = slider
slider.SetMinSize((150, -1))
self.Bind(wx.EVT_SLIDER, self.OnSeek, 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))
# setup the layout
sizer = wx.GridBagSizer(5,5)
sizer.Add(self.mc, (1,1), span=(5,1))#, flag=wx.EXPAND)
sizer.Add(btn1, (1,3))
sizer.Add(btn2, (2,3))
sizer.Add(btn3, (3,3))
sizer.Add(btn4, (4,3))
sizer.Add(slider, (6,1), flag=wx.EXPAND)
sizer.Add(self.st_size, (1, 5))
sizer.Add(self.st_len, (2, 5))
sizer.Add(self.st_pos, (3, 5))
self.SetSizer(sizer)
self.playBtn.Disable()
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.FD_OPEN | wx.FD_CHANGE_DIR )
if dlg.ShowModal() == wx.ID_OK:
self.playBtn.Disable()
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:
self.mc.SetInitialSize()
self.GetSizer().Layout()
self.slider.SetRange(0, self.mc.Length())
self.playBtn.Enable()
def OnMediaLoaded(self, evt):
print("OnMediaLoaded")
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.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.GetBestSize())
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
#----------------------------------------------------------------------
class TestFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1)
p = TestPanel(self)
self.SetMinSize((1100, 650))
def runTest():
app = wx.App()
frame = TestFrame(None)
frame.Show()
app.MainLoop()
#----------------------------------------------------------------------
if __name__ == '__main__':
runTest()
This issue has been mentioned on Discuss wxPython. There might be relevant details there:
https://discuss.wxpython.org/t/video-playback-influenced-by-amount-of-time-webpage-is-open/36902/2
+1 Just commenting here as the issue described by reticulatus could be related to my problem that I posted on Discuss wxPython, that RobinD42 linked to. Hopefully someone has the time and inclination to look into this.