我关闭了 vlc 媒体,但在这个音频仍然存在之后我无法使用 gui
I close vlc media, but after this audio remains and i can't use gui
当我用叉号关闭视频时,音频仍然存在。我使用 pafy 和 vlc。我也无法在关闭视频后关闭 PyQt 应用程序。
我用的是python3.8.
import sys
import pafy
import vlc
from PyQt5.QtWidgets import QApplication, QDialog, QLabel, QHBoxLayout, QPushButton
class GoodYoutubeGUI(QDialog):
def __init__(self):
super().__init__()
self.setFixedSize(800, 800)
self.setWindowTitle("Good Youtube")
self.buttons = []
self.generate_content()
def generate_buttons_info(self):
buttons_info = {}
for _ in range(5):
button = QPushButton('Открыть видео', self)
buttons_info[button] = "https://www.youtube.com/watch?v=zPA2Een1EQA"
return buttons_info
def generate_content(self):
pos_y = 0
for button, link in self.generate_buttons_info().items():
button.clicked.connect(lambda: self.open_video(link))
button.move(100, pos_y * 100)
pos_y += 1
def open_video(self, url):
video = pafy.new("https://www.youtube.com/watch?v=zPA2Een1EQA")
best = video.getbest()
media = vlc.MediaPlayer(best.url)
media.play()
while media.get_state() != vlc.State.Ended:
continue
media.stop()
if __name__ == '__main__':
app = QApplication(sys.argv)
dlg_main = GoodYoutubeGUI()
dlg_main.show()
sys.exit(app.exec_())
您遇到以下问题:
你不应该在 Qt 事件循环中使用耗时的任务,因为它会阻止它导致 GUI 冻结,例如 while.loop 和 pafy 的 getbest 函数,第一个应该使用回调以了解视频何时完成重现,第二个必须在辅助线程中执行。
您还必须在 lambda 中传递参数,否则您将遇到范围问题。
要检测 window 何时关闭,一个可能的解决方案是将视频播放器嵌入 QWidget,然后使用事件过滤器了解 window 何时关闭然后停止玩家。
from functools import cached_property
import sys
import threading
import pafy
import vlc
from PyQt5.QtCore import pyqtSignal, QEvent, QObject
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QWidget
class PlayerManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.window = QWidget()
if sys.platform.startswith("linux"): # for Linux using the X Server
self.player.set_xwindow(self.window.winId())
elif sys.platform == "win32": # for Windows
self.player.set_hwnd(self.window.winId())
elif sys.platform == "darwin": # for MacOS
self.player.set_nsobject(self.window.winId())
self.window.installEventFilter(self)
@cached_property
def player(self):
player = vlc.MediaPlayer()
player.event_manager().event_attach(
vlc.EventType.MediaPlayerEndReached, self._handle_finished
)
return player
def _handle_finished(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
self.player.stop()
def play(self):
self.player.play()
self.window.show()
def set_media(self, url):
media = vlc.Media(url)
self.player.set_media(media)
def eventFilter(self, obj, event):
if obj is self.window and event.type() == QEvent.Close:
self.player.stop()
return super().eventFilter(obj, event)
class UrlProvider(QObject):
finished = pyqtSignal(str)
def find_url(self, url):
threading.Thread(target=self._find_url, args=(url,), daemon=True).start()
def _find_url(self, url):
video = pafy.new(url)
best = video.getbest()
self.finished.emit(best.url)
class GoodYoutubeGUI(QDialog):
def __init__(self):
super().__init__()
self.setFixedSize(800, 800)
self.setWindowTitle("Good Youtube")
self.buttons = []
self.url_provider.finished.connect(self.handle_url_finished)
self.generate_content()
@cached_property
def player_manager(self):
return PlayerManager()
@cached_property
def url_provider(self):
return UrlProvider()
def generate_buttons_info(self):
buttons_info = {}
for _ in range(5):
button = QPushButton("Открыть видео", self)
buttons_info[button] = "https://www.youtube.com/watch?v=zPA2Een1EQA"
return buttons_info
def generate_content(self):
pos_y = 0
for button, link in self.generate_buttons_info().items():
button.clicked.connect(lambda checked, link=link: self.open_video(link))
button.move(100, pos_y * 100)
pos_y += 1
def open_video(self, url):
self.url_provider.find_url(url)
def handle_url_finished(self, url):
self.player_manager.set_media(url)
self.player_manager.play()
if __name__ == "__main__":
app = QApplication(sys.argv)
dlg_main = GoodYoutubeGUI()
dlg_main.show()
sys.exit(app.exec_())
当我用叉号关闭视频时,音频仍然存在。我使用 pafy 和 vlc。我也无法在关闭视频后关闭 PyQt 应用程序。
我用的是python3.8.
import sys
import pafy
import vlc
from PyQt5.QtWidgets import QApplication, QDialog, QLabel, QHBoxLayout, QPushButton
class GoodYoutubeGUI(QDialog):
def __init__(self):
super().__init__()
self.setFixedSize(800, 800)
self.setWindowTitle("Good Youtube")
self.buttons = []
self.generate_content()
def generate_buttons_info(self):
buttons_info = {}
for _ in range(5):
button = QPushButton('Открыть видео', self)
buttons_info[button] = "https://www.youtube.com/watch?v=zPA2Een1EQA"
return buttons_info
def generate_content(self):
pos_y = 0
for button, link in self.generate_buttons_info().items():
button.clicked.connect(lambda: self.open_video(link))
button.move(100, pos_y * 100)
pos_y += 1
def open_video(self, url):
video = pafy.new("https://www.youtube.com/watch?v=zPA2Een1EQA")
best = video.getbest()
media = vlc.MediaPlayer(best.url)
media.play()
while media.get_state() != vlc.State.Ended:
continue
media.stop()
if __name__ == '__main__':
app = QApplication(sys.argv)
dlg_main = GoodYoutubeGUI()
dlg_main.show()
sys.exit(app.exec_())
您遇到以下问题:
你不应该在 Qt 事件循环中使用耗时的任务,因为它会阻止它导致 GUI 冻结,例如 while.loop 和 pafy 的 getbest 函数,第一个应该使用回调以了解视频何时完成重现,第二个必须在辅助线程中执行。
您还必须在 lambda 中传递参数,否则您将遇到范围问题。
要检测 window 何时关闭,一个可能的解决方案是将视频播放器嵌入 QWidget,然后使用事件过滤器了解 window 何时关闭然后停止玩家。
from functools import cached_property
import sys
import threading
import pafy
import vlc
from PyQt5.QtCore import pyqtSignal, QEvent, QObject
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton, QWidget
class PlayerManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.window = QWidget()
if sys.platform.startswith("linux"): # for Linux using the X Server
self.player.set_xwindow(self.window.winId())
elif sys.platform == "win32": # for Windows
self.player.set_hwnd(self.window.winId())
elif sys.platform == "darwin": # for MacOS
self.player.set_nsobject(self.window.winId())
self.window.installEventFilter(self)
@cached_property
def player(self):
player = vlc.MediaPlayer()
player.event_manager().event_attach(
vlc.EventType.MediaPlayerEndReached, self._handle_finished
)
return player
def _handle_finished(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
self.player.stop()
def play(self):
self.player.play()
self.window.show()
def set_media(self, url):
media = vlc.Media(url)
self.player.set_media(media)
def eventFilter(self, obj, event):
if obj is self.window and event.type() == QEvent.Close:
self.player.stop()
return super().eventFilter(obj, event)
class UrlProvider(QObject):
finished = pyqtSignal(str)
def find_url(self, url):
threading.Thread(target=self._find_url, args=(url,), daemon=True).start()
def _find_url(self, url):
video = pafy.new(url)
best = video.getbest()
self.finished.emit(best.url)
class GoodYoutubeGUI(QDialog):
def __init__(self):
super().__init__()
self.setFixedSize(800, 800)
self.setWindowTitle("Good Youtube")
self.buttons = []
self.url_provider.finished.connect(self.handle_url_finished)
self.generate_content()
@cached_property
def player_manager(self):
return PlayerManager()
@cached_property
def url_provider(self):
return UrlProvider()
def generate_buttons_info(self):
buttons_info = {}
for _ in range(5):
button = QPushButton("Открыть видео", self)
buttons_info[button] = "https://www.youtube.com/watch?v=zPA2Een1EQA"
return buttons_info
def generate_content(self):
pos_y = 0
for button, link in self.generate_buttons_info().items():
button.clicked.connect(lambda checked, link=link: self.open_video(link))
button.move(100, pos_y * 100)
pos_y += 1
def open_video(self, url):
self.url_provider.find_url(url)
def handle_url_finished(self, url):
self.player_manager.set_media(url)
self.player_manager.play()
if __name__ == "__main__":
app = QApplication(sys.argv)
dlg_main = GoodYoutubeGUI()
dlg_main.show()
sys.exit(app.exec_())