我正在制作一个简单的 youtube 播放器和下载器应用程序,供盲人使用屏幕阅读器访问,但也可供有视力的人使用。 我选择 wxpython 是因为它具有有史以来最好的可访问性。 如何在 wx 窗口中播放 youtube 视频?我是否需要使用
wx.media.MediaCtrl
以及如何正确使用它?
我可以在不直接在 wxpython 窗口中下载的情况下播放 youtube 视频吗?
我尝试使用
wx.media.MediaCtrl
,但我从youtube下载了视频,然后让它显示了视频。
更新:
媒体控制不播放任何内容。我使用了我自己的 pafy 修改版本,它使用 yt_dlp 库,它完美地给了我一个有效的视频流 url,但是当我将它插入 wx 媒体时,它不播放。
import wx
import wx.media
import pafy
from webbrowser import open as wopen
from youtubesearchpython import VideosSearch
from accessible_output2.outputs import auto
class YoutubePlayer(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Youtube Player", size=(640, 480))
self.panel = wx.Panel(self)
self.edit_box = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER, pos=(10, 10), size=(200, 20))
self.list_box = wx.ListBox(self.panel, pos=(10, 40), size=(200, 400))
self.media_player = wx.media.MediaCtrl(self.panel)
self.media_player.Bind(wx.media.EVT_MEDIA_LOADED, self.on_media_loaded)
self.edit_box.Bind(wx.EVT_TEXT_ENTER, self.on_search)
self.output = auto.Auto()
self.results={}
def on_search(self, event):
query = self.edit_box.GetValue()
self.output.output("Searching for " + query)
search = VideosSearch(query, limit=10)
items = search.result()["result"]
video_ids = [item["id"] for item in items]
video_titles = [item["title"] for item in items]
self.list_box.SetItems(video_titles)
self.media_player.Stop()
self.results={k: v for k, v in zip(video_titles, video_ids)}
def on_media_loaded(self, event):
print("loaded")
self.output.output("Playing")
self.media_player.Play()
def play_video(self, video_id):
url = f"https://www.youtube.com/watch?v={video_id}"
video = pafy.new(url)
best = video.getbest()
play_url = best.url
# wopen(play_url)
self.media_player.LoadURI(play_url)
def on_list_select(self, event):
self.output.output("loading")
video_id = self.results[event.GetString()]
self.play_video(video_id)
def on_list_double_click(self, event):
self.on_list_select(event)
def bind_list_events(self):
#self.list_box.Bind(wx.EVT_LISTBOX, self.on_list_select)
self.list_box.Bind(wx.EVT_LISTBOX_DCLICK, self.on_list_double_click)
if __name__ == "__main__":
app = wx.App()
player = YoutubePlayer()
player.bind_list_events()
player.Show()
app.MainLoop()
wx.media
将直接从 URL 播放,虽然我不知道它是否可以直接访问 YouTube url(我不是粉丝)。
这是一个非常简单的播放器,它访问一个 url 而不是一个文件。
我建议您测试媒体链接,看看它是一个 url 还是一个文件,然后根据结果使用
LoadURI
或 Load
import wx
import wx.media
class TestPanel(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title='Media Player')
panel = wx.Panel(self, -1, size=(500, 700))
self.player = wx.media.MediaCtrl(panel, style=wx.SIMPLE_BORDER)
self.stop = wx.Button(panel, -1, "Stop")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.player, 1, flag=wx.ALL, border=5)
sizer.Add(self.stop, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.media = 'http://clips.vorwaerts-gmbh.de/VfE_html5.mp4'
self.player.Bind(wx.media.EVT_MEDIA_LOADED, self.play)
self.player.Bind(wx.media.EVT_MEDIA_FINISHED, self.quit)
self.Bind(wx.media.EVT_MEDIA_STOP, self.quit)
self.Bind(wx.EVT_BUTTON, self.quit, self.stop)
self.Bind(wx.EVT_CLOSE, self.quit)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self.timer.Start(250)
if self.player.LoadURI(self.media):
pass
else:
print("Media not found")
self.quit(None)
self.Show()
def OnTimer(self, event):
if self.player.GetState() == wx.media.MEDIASTATE_PLAYING:
print("Progress:",self.player.Tell())
def play(self, event):
self.player.Play()
def quit(self, event):
self.timer.Stop()
if self.player.GetState() == wx.media.MEDIASTATE_PLAYING:
self.player.Stop()
self.Destroy()
if __name__ == '__main__':
app = wx.App()
Frame = TestPanel()
app.MainLoop()
值得注意的是,您可能必须通过
szBackend
参数选择您的后端播放器。
可用的选项是:
如果你想要比
wx.media
更复杂的东西,你将不得不自己动手。
Gstreamer
和 Vlc
在 Linux 上都运行良好,在其他操作系统上,我不知道。
编辑:
如果您必须直接从 youtube 流式传输,请使用
pafy
之类的东西来隔离 url。
对于上面的代码:
添加
import pafy
而不是指定 url
self.media
replace
self.media = 'http://clips.vorwaerts-gmbh.de/VfE_html5.mp4'
具有以下内容:
# youtube url via pafy
url = "https://www.youtube.com/watch?v=iL-jC7XyLeo"
video = pafy.new(url)
best = video.getbest()
playurl = best.url
self.media = playurl
然后继续如上