python вставить видео во внутренний content
При нажатии на кнопку воспроизвести запускается видео в отдельном окне: https://c2n.me/4a0R2PO
Как сделать так чтобы при нажатии на кнопку, видео открывалось не в новом окне, а в белом окне вот здесь: https://c2n.me/4a0R1Qs
Пытался вот так: ui.QWidget.imshow('frame', frame) но не получается.
main.py:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from design import Ui_Form
import cv2
# Create app
app = QtWidgets.QApplication(sys.argv)
# init
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
# Hook logic
def PlayVideo():
video = cv2.VideoCapture('video.mp4')
while(video.isOpened()):
ret, frame = video.read()
if ret == True:
cv2.imshow('frame', frame)
if cv2.waitKey(28) & 0xFF == ord('q'):
break
else:
break
video.release()
cv2.destroyAllWindows()
ui.pushButton.clicked.connect(PlayVideo)
# Main loop
sys.exit(app.exec_())
design.py:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(824, 452)
self.frame = QtWidgets.QFrame(Form)
self.frame.setGeometry(QtCore.QRect(140, 30, 561, 341))
self.frame.setStyleSheet(".QFrame {\n"
" background-color: #fff;\n"
"}")
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(140, 380, 561, 23))
self.pushButton.setStyleSheet(".QPushButton {\n"
" background: #222;\n"
" color: #fff;\n"
" text-align: center\n"
"}")
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.pushButton.setText(_translate("Form", "Воспроизвести"))
Ответы (2 шт):
Я не знаю насколько вам важно использовать библиотеку cv2,
но для начала предлагаю вам попробовать вариант без ее использования.
Класс QVideoWidget предоставляет виджет, который представляет видео, созданное медиа-объектом.
PS. Если для вас важно использование OpenCV - напишите, что-нибудь придумаем :)
import sys
from PyQt5.QtCore import QUrl, QSize
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QVBoxLayout, QWidget
class VideoWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setMinimumSize(QSize(300, 300))
self.resize(500, 500)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.button = QPushButton('Play', self)
self.button.clicked.connect(self.playMedia)
video_widget = QVideoWidget(self)
self.mediaPlayer = QMediaPlayer(self, QMediaPlayer.VideoSurface)
self.mediaPlayer.setVideoOutput(video_widget)
# vvvvvvvvvvvvvvvvv <-- установите свое
self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile("Samonastrojka.avi")))
self.mainLayout = QVBoxLayout(self.centralWidget)
self.mainLayout.addWidget(video_widget)
self.mainLayout.addWidget(self.button)
def playMedia(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
self.button.setText('Play')
else:
self.mediaPlayer.play()
self.button.setText('Pause')
if __name__ == '__main__':
app = QApplication(sys.argv)
player = VideoWindow()
player.show()
exitCode = app.exec_()
sys.exit(exitCode)
Для объединения opencv и Qt можно поступить так:
- В отдельном потоке считываются кадры из заданного источника через opencv и сигналом их передавать
- В окне виджета этот поток создается и запускается, а кадры размещаются на виджете (в данном случае на
QLabel)
Но я бы рекомендовал использовать встроенные средства Qt, если это возможно. Для этого есть модули QtMultimedia и QtMultimediaWidgets
import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QLabel, QVBoxLayout
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtGui import QImage, QPixmap
from design import Ui_Form
class ThreadOpenCV(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, source):
super().__init__()
self.source = source
def run(self):
cap = cv2.VideoCapture(self.source)
while True:
ret, frame = cap.read()
if ret:
# https://stackoverflow.com/a/55468544/6622587
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbImage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
cv2.waitKey(28)
class Widget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
self.label_video = QLabel()
layout = QVBoxLayout()
layout.addWidget(self.label_video)
self.ui.frame.setLayout(layout)
self.thread = ThreadOpenCV("video.mp4")
self.thread.changePixmap.connect(self.setImage)
self.ui.pushButton.clicked.connect(self.playVideo)
def playVideo(self):
self.thread.start()
def setImage(self, image):
self.label_video.setPixmap(QPixmap.fromImage(image))
# Create app
app = QtWidgets.QApplication(sys.argv)
mw = Widget()
mw.show()
sys.exit(app.exec_())

