(PySide6)我如何在单独的线程中运行QMediaPlayer ?



我正在尝试处理QMediaPlayer中的每个QVideoFrame并将其显示在QLabel上。

下面是示例代码。

  1. QMediaPlayer发送QVideoFrameQVideoSink
  2. 视频接收器发送帧到MyWorker
  3. MyWorkerQVideoFrame转换为QPixmap,做一些处理后发送像素图给QLabel
from PySide6.QtCore import QObject, QUrl, Signal, Slot
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import QLabel, QApplication
from PySide6.QtMultimedia import QMediaPlayer, QVideoSink, QVideoFrame
import sys
import time

class MyWorker(QObject):
pixmapChanged = Signal(QPixmap)
@Slot(QVideoFrame)
def setVideoFrame(self, frame: QVideoFrame):
qimg = frame.toImage()
pixmap = QPixmap.fromImage(qimg)
time.sleep(0.5)  # represents time-consuming work
self.pixmapChanged.emit(pixmap)

app = QApplication(sys.argv)
player = QMediaPlayer()
sink = QVideoSink()
worker = MyWorker()
widget = QLabel()
player.setVideoSink(sink)
sink.videoFrameChanged.connect(worker.setVideoFrame)
worker.pixmapChanged.connect(widget.setPixmap)
player.setSource(QUrl.fromLocalFile("my-video.mp4"))
widget.show()
player.play()
app.exec()
app.quit()

处理需要一些时间,因此标签更新速度比原始视频FPS慢。这很好,但问题是,我目前的代码没有QThread阻塞了GUI。

使用player.moveToThread(...)不起作用。我如何在单独的线程中运行QMediaPlayer?

多亏了@musicamente,我通过将worker移动到单独的线程来修复它。

注意,只有当worker准备好了,窗口才会发送帧给worker。如果没有,阻塞的信号与QVideoFrame实例一起排队,并迅速消耗所有内存。

<标题>媒体播放器h1> 相机h1> /html>

最新更新