I created a media player application using python-vlc and PyQt5, quite similar to this qtvlc code.
A minimal reproducible code is shown as follows:
class Player(QMainWindow):
"""A simple Media Player using VLC and Qt
"""
def __init__(self, master=None):
QMainWindow.__init__(self, master)
self.setWindowTitle("Media Player")
# creating a basic vlc instance
self.instance = vlc.Instance()
# creating an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.createUI()
self.isPaused = False
def createUI(self):
"""Set up the user interface, signals & slots
"""
self.widget = QWidget(self)
self.setCentralWidget(self.widget)
self.videoframe = QFrame()
self.videoframe.setAutoFillBackground(True)
pixmap = QtGui.QPixmap()
pixmap.load("path to transparent_image.png")
self.my_label = QLabel(self)
self.my_label.setPixmap(pixmap)
self.my_label.setGeometry(300, 250, 100, 100)
self.my_label.setFrameStyle(QFrame.NoFrame)
self.my_label.setAttribute(Qt.WA_TranslucentBackground)
self.vboxlayout = QVBoxLayout()
self.vboxlayout.addWidget(self.videoframe)
self.widget.setLayout(self.vboxlayout)
self.media = self.instance.media_new("path to video file")
# put the media in the media player
self.mediaplayer.set_media(self.media)
# the media player has to be 'connected' to the QFrame
# (otherwise a video would be displayed in it's own window)
# this is platform specific!
# you have to give the id of the QFrame (or similar object) to
# vlc, different platforms have different functions for this
if sys.platform.startswith('linux'): # for Linux using the X Server
self.mediaplayer.set_xwindow(self.videoframe.winId())
elif sys.platform == "win32": # for Windows
self.mediaplayer.set_hwnd(self.videoframe.winId())
elif sys.platform == "darwin": # for MacOS
self.mediaplayer.set_nsobject(self.videoframe.winId())
self.mediaplayer.play()
if __name__ == "__main__":
app = QApplication(sys.argv)
player = Player()
player.show()
player.resize(640, 480)
sys.exit(app.exec_())
Once I run the code, I can see that the transparent image is drawn on top of the video but the image instead of showing the background video through it continues to show the portion of the QFrame as its background. Can anyone help me with getting around this issue?
Related
I'm trying to play an online video using python-vlc library.
First, I was using a simple version of the player to test it out:
import vlc
#example url
url="https://player.vimeo.com/external/363536021.hd.mp4?s=6f6e87d86a49149479ebdab6c8bc421aa89f327c&profile_id=175&oauth2_token_id=57447761"
player = vlc.Instance().media_player_new()
player.set_media(vlc.Instance().media_new(url))
player.play()
while str(player.get_state()) != "State.Ended":
pass
player.stop()
It plays the while video from URL without any problems!
Now I wanted to use the more complex version with pyqt5 GUI (original source-code here):
import sys
import os.path
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPalette, QColor
from PyQt5.QtWidgets import QMainWindow, QWidget, QFrame, QSlider, QHBoxLayout, QPushButton, \
QVBoxLayout, QAction, QFileDialog, QApplication
import vlc
class Player(QMainWindow):
def __init__(self, videoUrl, master=None):
QMainWindow.__init__(self, master)
self.setWindowTitle("Media Player")
# creating a basic vlc instance
self.instance = vlc.Instance()
# creating an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.playableVideo = videoUrl
self.createUI()
self.isPaused = False
def createUI(self):
"""Set up the user interface, signals & slots
"""
self.widget = QWidget(self)
self.setCentralWidget(self.widget)
# In this widget, the video will be drawn
if sys.platform == "darwin": # for MacOS
from PyQt5.QtWidgets import QMacCocoaViewContainer
self.videoframe = QMacCocoaViewContainer(0)
else:
self.videoframe = QFrame()
self.palette = self.videoframe.palette()
self.palette.setColor (QPalette.Window,
QColor(0,0,0))
self.videoframe.setPalette(self.palette)
self.videoframe.setAutoFillBackground(True)
self.positionslider = QSlider(Qt.Horizontal, self)
self.positionslider.setToolTip("Position")
self.positionslider.setMaximum(5000)
self.positionslider.sliderMoved.connect(self.setPosition)
self.hbuttonbox = QHBoxLayout()
self.playbutton = QPushButton("Play")
self.hbuttonbox.addWidget(self.playbutton)
self.playbutton.clicked.connect(self.PlayPause)
self.stopbutton = QPushButton("Exit")
self.hbuttonbox.addWidget(self.stopbutton)
self.stopbutton.clicked.connect(self.Stop)
self.hbuttonbox.setAlignment(Qt.AlignHCenter)
self.vboxlayout = QVBoxLayout()
self.vboxlayout.addWidget(self.videoframe)
self.vboxlayout.addWidget(self.positionslider)
self.vboxlayout.addLayout(self.hbuttonbox)
self.widget.setLayout(self.vboxlayout)
self.timer = QTimer(self)
self.timer.setInterval(200)
self.timer.timeout.connect(self.updateUI)
def PlayPause(self):
"""Toggle play/pause status
"""
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.playbutton.setText("Play")
self.isPaused = True
else:
if self.mediaplayer.play() == -1:
self.OpenFile()
return
self.mediaplayer.play()
self.playbutton.setText("Pause")
self.timer.start()
self.isPaused = False
def Stop(self):
"""Stop player
"""
self.mediaplayer.stop()
self.playbutton.setText("Play")
def OpenFile(self, filename=None):
"""Open a media file in a MediaPlayer
"""
if filename is None:
filename = self.playableVideo
if not filename:
return
# create the media
if sys.version < '3':
filename = unicode(filename)
self.media = self.instance.media_new(filename)
# put the media in the media player
self.mediaplayer.set_media(self.media)
# parse the metadata of the file
self.media.parse()
# set the title of the track as window title
self.setWindowTitle(self.media.get_meta(0))
# the media player has to be 'connected' to the QFrame
# (otherwise a video would be displayed in it's own window)
# this is platform specific!
# you have to give the id of the QFrame (or similar object) to
# vlc, different platforms have different functions for this
if sys.platform.startswith('linux'): # for Linux using the X Server
self.mediaplayer.set_xwindow(self.videoframe.winId())
elif sys.platform == "win32": # for Windows
self.mediaplayer.set_hwnd(self.videoframe.winId())
elif sys.platform == "darwin": # for MacOS
self.mediaplayer.set_nsobject(int(self.videoframe.winId()))
self.PlayPause()
def setPosition(self, position):
self.mediaplayer.set_position(position / 1000.0)
def updateUI(self):
self.positionslider.setValue(self.mediaplayer.get_position() * 1000)
if not self.mediaplayer.is_playing():
self.timer.stop()
if not self.isPaused:
self.Stop()
if __name__ == "__main__":
app = QApplication(sys.argv)
player = Player("https://player.vimeo.com/external/363536021.hd.mp4?s=6f6e87d86a49149479ebdab6c8bc421aa89f327c&profile_id=175&oauth2_token_id=57447761")
player.show()
player.resize(640, 480)
if sys.argv[1:]:
player.OpenFile(sys.argv[1])
sys.exit(app.exec_())
This code keeps returning an access stream error: HTTP connection failure.
The problem is that as soon as you start playing the video it is not available since the download is not immediate but with your code you try to update the position. The solution is to update is to get the position after it started playing:
def updateUI(self):
if not self.mediaplayer.is_playing():
return
self.positionslider.setValue(self.mediaplayer.get_position() * 1000)
if not self.mediaplayer.is_playing():
self.timer.stop()
if not self.isPaused:
self.Stop()
I'm trying to get a video to play in a frame in PyQt through VLC, I followed a similar question on here to get the sample code to use:
class VideoPlayer(QMainWindow):
def __init__(self, parent, inputPath):
super(VideoPlayer, self).__init__(parent)
self.setWindowTitle("Media Player")
# creating a basic vlc instance
self.instance = vlc.Instance()
self.mediaplayer = self.instance.media_player_new()
##########video frame
self.videoframe = QFrame(
frameShape=QFrame.Box, frameShadow=QFrame.Raised
)
if sys.platform.startswith("linux"): # for Linux using the X Server
self.mediaplayer.set_xwindow(self.videoframe.winId())
elif sys.platform == "win32": # for Windows
self.mediaplayer.set_hwnd(self.videoframe.winId())
elif sys.platform == "darwin": # for MacOS
self.mediaplayer.set_nsobject(self.videoframe.winId())
central_widget = QWidget()
self.setCentralWidget(central_widget)
lay = QVBoxLayout(central_widget)
lay.addWidget(self.videoframe)
filename = inputPath
media = self.instance.media_new(filename)
self.mediaplayer.set_media(media)
self.mediaplayer.play()
Trying to run this just gives me these errors whenever I start it up though:
[0c92dc18] mmdevice audio output error: cannot initialize COM (error 0x80010106)
[0ef89108] mmdevice audio output error: cannot initialize COM (error 0x80010106)
[0f07f308] direct3d11 vout display error: SetThumbNailClip failed: 0x800706f4
[0f07f308] direct3d9 vout display error: SetThumbNailClip failed: 0x800706f4
[0f07f308] glwin32 vout display error: Win32VoutCreateWindow RegisterClass FAILED (err=1410)
[0f07f308] glwin32 vout display error: SetThumbNailClip failed: 0x800706f4
[0efbc4b8] wgl gl error: Could not get the device context
[0f07f308] directdraw vout display error: Win32VoutCreateWindow RegisterClass FAILED (err=1410)
[0f07f308] directdraw vout display error: SetThumbNailClip failed: 0x800706f4
[0f07f308] wingdi vout display error: Win32VoutCreateWindow RegisterClass FAILED (err=1410)
[0f07f308] wingdi vout display error: SetThumbNailClip failed: 0x800706f4
[0f07c670] main video output error: video output creation failed
[0ef90360] main decoder error: failed to create video output
If I run the video without using PyQt, just as:
Instance = vlc.Instance()
player = Instance.media_player_new()
Media = Instance.media_new(inputPath)
player.set_media(Media)
player.play()
time.sleep(5) # Or however long you expect it to take to open vlc
while player.is_playing():
time.sleep(1)
if 0xFF == ord("q"):
player.stop()
player.stop()
It works fine. Can anyone point me in the direction of what I might be doing wrong here?
I have tried to recreate the issue and reached to the solution below:
Installations:
pip install PyQt5
pip install python-vlc
Then go to https://www.videolan.org/vlc/ to download the VLC player
for your OS, and install it. After that run the code below:
import platform
import os
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
import vlc
class Player(QtWidgets.QMainWindow):
"""A simple Media Player using VLC and Qt
"""
def __init__(self, master=None):
QtWidgets.QMainWindow.__init__(self, master)
self.setWindowTitle("Media Player")
# Create a basic vlc instance
self.instance = vlc.Instance()
self.media = None
# Create an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.create_ui()
self.is_paused = False
def create_ui(self):
"""Set up the user interface, signals & slots
"""
self.widget = QtWidgets.QWidget(self)
self.setCentralWidget(self.widget)
# In this widget, the video will be drawn
if platform.system() == "Darwin": # for MacOS
self.videoframe = QtWidgets.QMacCocoaViewContainer(0)
else:
self.videoframe = QtWidgets.QFrame()
self.palette = self.videoframe.palette()
self.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(0, 0, 0))
self.videoframe.setPalette(self.palette)
self.videoframe.setAutoFillBackground(True)
self.positionslider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
self.positionslider.setToolTip("Position")
self.positionslider.setMaximum(1000)
self.positionslider.sliderMoved.connect(self.set_position)
self.positionslider.sliderPressed.connect(self.set_position)
self.hbuttonbox = QtWidgets.QHBoxLayout()
self.playbutton = QtWidgets.QPushButton("Play")
self.hbuttonbox.addWidget(self.playbutton)
self.playbutton.clicked.connect(self.play_pause)
self.stopbutton = QtWidgets.QPushButton("Stop")
self.hbuttonbox.addWidget(self.stopbutton)
self.stopbutton.clicked.connect(self.stop)
self.hbuttonbox.addStretch(1)
self.volumeslider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
self.volumeslider.setMaximum(100)
self.volumeslider.setValue(self.mediaplayer.audio_get_volume())
self.volumeslider.setToolTip("Volume")
self.hbuttonbox.addWidget(self.volumeslider)
self.volumeslider.valueChanged.connect(self.set_volume)
self.vboxlayout = QtWidgets.QVBoxLayout()
self.vboxlayout.addWidget(self.videoframe)
self.vboxlayout.addWidget(self.positionslider)
self.vboxlayout.addLayout(self.hbuttonbox)
self.widget.setLayout(self.vboxlayout)
menu_bar = self.menuBar()
# File menu
file_menu = menu_bar.addMenu("File")
# Add actions to file menu
open_action = QtWidgets.QAction("Load Video", self)
close_action = QtWidgets.QAction("Close App", self)
file_menu.addAction(open_action)
file_menu.addAction(close_action)
open_action.triggered.connect(self.open_file)
close_action.triggered.connect(sys.exit)
self.timer = QtCore.QTimer(self)
self.timer.setInterval(100)
self.timer.timeout.connect(self.update_ui)
def play_pause(self):
"""Toggle play/pause status
"""
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.playbutton.setText("Play")
self.is_paused = True
self.timer.stop()
else:
if self.mediaplayer.play() == -1:
self.open_file()
return
self.mediaplayer.play()
self.playbutton.setText("Pause")
self.timer.start()
self.is_paused = False
def stop(self):
"""Stop player
"""
self.mediaplayer.stop()
self.playbutton.setText("Play")
def open_file(self):
"""Open a media file in a MediaPlayer
"""
dialog_txt = "Choose Media File"
filename = QtWidgets.QFileDialog.getOpenFileName(self, dialog_txt, os.path.expanduser('~'))
if not filename:
return
# getOpenFileName returns a tuple, so use only the actual file name
self.media = self.instance.media_new(filename[0])
# Put the media in the media player
self.mediaplayer.set_media(self.media)
# Parse the metadata of the file
self.media.parse()
# Set the title of the track as window title
self.setWindowTitle(self.media.get_meta(0))
# The media player has to be 'connected' to the QFrame (otherwise the
# video would be displayed in it's own window). This is platform
# specific, so we must give the ID of the QFrame (or similar object) to
# vlc. Different platforms have different functions for this
if platform.system() == "Linux": # for Linux using the X Server
self.mediaplayer.set_xwindow(int(self.videoframe.winId()))
elif platform.system() == "Windows": # for Windows
self.mediaplayer.set_hwnd(int(self.videoframe.winId()))
elif platform.system() == "Darwin": # for MacOS
self.mediaplayer.set_nsobject(int(self.videoframe.winId()))
self.play_pause()
def set_volume(self, volume):
"""Set the volume
"""
self.mediaplayer.audio_set_volume(volume)
def set_position(self):
"""Set the movie position according to the position slider.
"""
# The vlc MediaPlayer needs a float value between 0 and 1, Qt uses
# integer variables, so you need a factor; the higher the factor, the
# more precise are the results (1000 should suffice).
# Set the media position to where the slider was dragged
self.timer.stop()
pos = self.positionslider.value()
self.mediaplayer.set_position(pos / 1000.0)
self.timer.start()
def update_ui(self):
"""Updates the user interface"""
# Set the slider's position to its corresponding media position
# Note that the setValue function only takes values of type int,
# so we must first convert the corresponding media position.
media_pos = int(self.mediaplayer.get_position() * 1000)
self.positionslider.setValue(media_pos)
# No need to call this function if nothing is played
if not self.mediaplayer.is_playing():
self.timer.stop()
# After the video finished, the play button stills shows "Pause",
# which is not the desired behavior of a media player.
# This fixes that "bug".
if not self.is_paused:
self.stop()
def main():
"""Entry point for our simple vlc player
"""
app = QtWidgets.QApplication(sys.argv)
player = Player()
player.show()
player.resize(640, 480)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
The VLC version I am using is 64 bit. Here is the output:
I have use VLC Python binding for media Player Gui and I want to add Timer to the Below Slider its like 0.00:0.00 (current video time : total duration of video) how can i add this ??
How to callback the current playing time and display as label below position slider as mention in image ?
Please help for small hint to how to do??
import sys
from PyQt5 import QtCore as qtc
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
import vlc
import os.path
class MainWindow(qtw.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
##Main framwork
# creating a basic vlc instance
self.instance = vlc.Instance()
# creating an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.createUI()
self.isPaused = False
def createUI(self):
base_widget = qtw.QWidget()
base_widget.setLayout(qtw.QHBoxLayout())
notebook = qtw.QVBoxLayout()
base_widget.layout().addLayout(notebook)
self.setCentralWidget(base_widget)
#VideoFrame Loading
self.videoframe = qtw.QFrame()
self.videoframe.setMinimumWidth(950)
self.videoframe.setMinimumHeight(525)
self.palette = self.videoframe.palette()
self.palette.setColor (qtg.QPalette.Window,
qtg.QColor(0,0,0))
self.videoframe.setPalette(self.palette)
self.videoframe.setAutoFillBackground(True)
#Position Slider
self.positionslider = qtw.QSlider(qtc.Qt.Horizontal, self)
self.positionslider.setToolTip("Position")
self.positionslider.setMaximum(100000.0)
self.positionslider.setTickPosition(qtw.QSlider.TicksBelow)
self.positionslider.setTickInterval(2000)
self.positionslider.sliderMoved.connect(self.setPosition)
self.hbuttonbox = qtw.QHBoxLayout()
self.playbutton = qtw.QPushButton("Play")
self.hbuttonbox.addWidget(self.playbutton)
self.playbutton.clicked.connect(self.PlayPause)
#Button Box
self.stopbutton = qtw.QPushButton("Stop")
self.hbuttonbox.addWidget(self.stopbutton)
self.stopbutton.clicked.connect(self.Stop)
#Volume slider
self.hbuttonbox.addStretch(1)
self.volumeslider = qtw.QSlider(qtc.Qt.Horizontal, self)
self.volumeslider.setMaximum(100)
self.volumeslider.setValue(self.mediaplayer.audio_get_volume())
self.volumeslider.setToolTip("Volume")
self.hbuttonbox.addWidget(self.volumeslider)
self.volumeslider.valueChanged.connect(self.setVolume)
notebook.addWidget(self.videoframe)
notebook.addWidget(self.positionslider)
notebook.addLayout(self.hbuttonbox)
#Actions Code
open1 = qtw.QAction("&Open", self)
open1.triggered.connect(self.OpenFile)
exit = qtw.QAction("&Exit", self)
exit.triggered.connect(sys.exit)
menubar = self.menuBar()
filemenu = menubar.addMenu("&File")
filemenu.addAction(open1)
filemenu.addSeparator()
filemenu.addAction(exit)
self.timer = qtc.QTimer(self)
self.timer.setInterval(200)
self.timer.timeout.connect(self.updateUI)
def PlayPause(self):
"""Toggle play/pause status
"""
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.playbutton.setText("Play")
self.isPaused = True
else:
if self.mediaplayer.play() == -1:
self.OpenFile()
return
self.mediaplayer.play()
self.playbutton.setText("Pause")
self.timer.start()
self.isPaused = False
def PausePlay(self):
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.playbutton.setText("Play")
self.isPaused = True
def Stop(self):
"""Stop player
"""
self.mediaplayer.stop()
self.playbutton.setText("Play")
def OpenFile(self, filename=None):
"""Open a media file in a MediaPlayer
"""
if filename is None or filename is False:
print("Attempt to open up OpenFile")
filenameraw = qtw.QFileDialog.getOpenFileName(self, "Open File", os.path.expanduser('~'))
filename = filenameraw[0]
if not filename:
return
# create the media
if sys.version < '3':
filename = unicode(filename)
self.media = self.instance.media_new(filename)
# put the media in the media player
self.mediaplayer.set_media(self.media)
# parse the metadata of the file
self.media.parse()
# set the title of the track as window title
self.setWindowTitle(self.media.get_meta(0))
# print(vlc.libvlc_media_get_meta(self.media, 6))
# print(vlc.libvlc_media_get_duration(self.media))
# the media player has to be 'connected' to the QFrame
# (otherwise a video would be displayed in it's own window)
# this is platform specific!
# you have to give the id of the QFrame (or similar object) to
# vlc, different platforms have different functions for this
if sys.platform.startswith('linux'): # for Linux using the X Server
self.mediaplayer.set_xwindow(self.videoframe.winId())
elif sys.platform == "win32": # for Windows
self.mediaplayer.set_hwnd(self.videoframe.winId())
elif sys.platform == "darwin": # for MacOS
self.mediaplayer.set_nsobject(int(self.videoframe.winId()))
self.PlayPause()
def setVolume(self, Volume):
"""Set the volume """
self.mediaplayer.audio_set_volume(Volume)
def setPosition(self, position):
"""Set the position
"""
# setting the position to where the slider was dragged
self.mediaplayer.set_position(position / 100000.0)
# the vlc MediaPlayer needs a float value between 0 and 1, Qt
# uses integer variables, so you need a factor; the higher the
# factor, the more precise are the results
# (1000 should be enough)
def updateUI(self):
"""updates the user interface"""
# setting the slider to the desired position
self.positionslider.setValue(self.mediaplayer.get_position() * 100000.0)
if not self.mediaplayer.is_playing():
# no need to call this function if nothing is played
self.timer.stop()
if not self.isPaused:
# after the video finished, the play button stills shows
# "Pause", not the desired behavior of a media player
# this will fix it
self.Stop()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv) #it's required to save a referance to MainWindow
mw = MainWindow()
mw.show()
if sys.argv[1:]:
mw.OpenFile(sys.argv[1])
sys.exit(app.exec_())
#if it goes out of scope ,it will be destroyed
I'm integrating openCV 3.0 with Qt5 in Python 3.4.3 using pyqt5. I've been trying to build an app to process videos from files, but ran into some trouble with pyqt. Specifically, I will be loading videos through a file dialog multiple times and these videos will not be the same size. Therefore, I want the main window in my app to wrap/expand to the size of the video being played.
Below is a simplified version of my code with the 3 core classes for showing the video. One for the Main Window, one for a frame viewer widget to show each video frame in the GUI, and one for a video processor to read and process the video through opencv, transform it to a QImage then send it to the viewer.
class videoProcessor(QtCore.QObject):
filename = None
cap = None
videoSignal = QtCore.pyqtSignal(QtGui.QImage)
def __init__(self):
super().__init__()
self.filename = "test.mp4"
#QtCore.pyqtSlot()
def runVideoProcessor(self):
self.cap = cv2.VideoCapture(self.filename)
while self.cap.isOpened():
ret, frame = self.cap.read()
if ret:
outimg = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
imgh, imgw, bytesPerComponent = outimg.shape
bytesPerLine = bytesPerComponent * imgw;
qtimg = QtGui.QImage(outimg.data,imgw,imgh,bytesPerLine,QtGui.QImage.Format_RGB888)
self.videoSignal.emit(qtimg)
else:
break
self.cap.release()
class frameViewer(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.image = QtGui.QImage()
self.imageAvailable = False
def paintEvent(self,event):
painter = QtGui.QPainter(self)
painter.drawImage(0,0,self.image)
self.image = QtGui.QImage()
painter.end()
#QtCore.pyqtSlot(QtGui.QImage)
def setFrame(self,image):
self.image = image
self.setFixedSize(self.image.size())
self.repaint()
class mainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.fview = frameViewer()
self.vproc = videoProcessor()
self.vproc.videoSignal.connect(self.fview.setFrame)
self.startButton = QtWidgets.QPushButton("Start")
self.startButton.clicked.connect(self.vproc.runVideoProcessor)
self.mainLayout = QtWidgets.QVBoxLayout()
self.mainLayout.addWidget(self.fview)
self.mainLayout.addWidget(self.startButton)
self.mainWidget = QtWidgets.QWidget()
self.mainWidget.setLayout(self.mainLayout)
self.mainWidget.setSizePolicy(QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Expanding)
self.setCentralWidget(self.mainWidget)
self.statusBar().showMessage('Ready')
self.setGeometry(50, 50, 300, 300)
self.setWindowTitle('OpenCV PyQt Test')
self.show()
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
mw = mainWindow()
sys.exit(app.exec_())
So far, the program can run videos but there are two main problems:
The window does not adjust to the size of the video frame until the end of the video. However, any repetition of the same video play will be in the correct size.
If I don't set self.image=QtGui.QImage() in paintEvent after drawing the image, the program crashes. However, if I put that line in, at the end of the video, the window will go blank because an empty QImage will be drawn in the last frame's place whenever the window is updated.
Any ideas on how to solve these issues? Thank you.
I have made a opencv project which processes input stream from the video and displays the processed output. I have used PyQt buttons to switch from one output to another. My PyQt window covvers almost the entire screen and when i click on my buttons, the opencv window remains behind the PyQt window. Also, I have made the main window of PyQt my parent window. How can I bring the opencv window on top of PyQt window. I searched for cvGetWindowHandle(), but didn't find it's implementation for python.
I have used PyQt4 and opencv2, and the PyQt window has not been designed using a QtDesigner.
You can always wrap OpenCV window in Qt widget...
class QtCapture(QtGui.QWidget):
def __init__(self, *args):
super(QtGui.QWidget, self).__init__()
self.fps = 24
self.cap = cv2.VideoCapture(*args)
self.video_frame = QtGui.QLabel()
lay = QtGui.QVBoxLayout()
lay.setMargin(0)
lay.addWidget(self.video_frame)
self.setLayout(lay)
def setFPS(self, fps):
self.fps = fps
def nextFrameSlot(self):
ret, frame = self.cap.read()
# OpenCV yields frames in BGR format
frame = cv2.cvtColor(frame, cv2.cv.CV_BGR2RGB)
img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
pix = QtGui.QPixmap.fromImage(img)
self.video_frame.setPixmap(pix)
def start(self):
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.nextFrameSlot)
self.timer.start(1000./self.fps)
def stop(self):
self.timer.stop()
def deleteLater(self):
self.cap.release()
super(QtGui.QWidget, self).deleteLater()
...and do with it whatever you will:
class ControlWindow(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.capture = None
self.start_button = QtGui.QPushButton('Start')
self.start_button.clicked.connect(self.startCapture)
self.quit_button = QtGui.QPushButton('End')
self.quit_button.clicked.connect(self.endCapture)
self.end_button = QtGui.QPushButton('Stop')
vbox = QtGui.QVBoxLayout(self)
vbox.addWidget(self.start_button)
vbox.addWidget(self.end_button)
vbox.addWidget(self.quit_button)
self.setLayout(vbox)
self.setWindowTitle('Control Panel')
self.setGeometry(100,100,200,200)
self.show()
def startCapture(self):
if not self.capture:
self.capture = QtCapture(0)
self.end_button.clicked.connect(self.capture.stop)
self.capture.setFPS(30)
self.capture.setParent(self)
self.capture.setWindowFlags(QtCore.Qt.Tool)
self.capture.start()
self.capture.show()
def endCapture(self):
self.capture.deleteLater()
self.capture = None
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = ControlWindow()
sys.exit(app.exec_())