class QVideoPreview(QWidget): frameChanged = pyqtSignal(int, QTime) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.imageView = QImageView(self) self.frameSelection = QFrameSelect(self) self.frameSelection.frameSelectionChanged.connect(self.updateImage) layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self.imageView) layout.addWidget(self.frameSelection) def setSource(self, source): self._source = source self.frameSelection.setPtsTimeArray(source.pts_time) self.setFrameIndex(0) s, ms = divmod(int(1000 * source.pts_time[0]), 1000) m, s = divmod(s, 60) h, m = divmod(m, 60) self.updateImage(0, QTime(h, m, s, ms)) def setFrameIndex(self, value): self.frameSelection.slider.setValue(value) def updateImage(self, n, t): try: frame = next(self._source.iterFrames(n, whence="framenumber")) except Exception: return self.imageView.setFrame(frame.to_image().convert("RGBA").toqpixmap()) self.frameChanged.emit(n, t)
def _createControls(self): self.setWindowTitle("Configure Crop") layout = QVBoxLayout(self) self.setLayout(layout) self.sourceWidget = QWidget(self) self.sourceSelection = self.createSourceControl(self.sourceWidget) self.sourceSelection.currentDataChanged.connect(self.setFilterSource) srclayout = QHBoxLayout() srclayout.addWidget(QLabel("Source: ", self.sourceWidget)) srclayout.addWidget(self.sourceSelection) self.sourceWidget.setLayout(srclayout) layout.addWidget(self.sourceWidget) self.cropWidget = QCrop(self) self.cropWidget.cropRight.valueChanged.connect(self.setCropRight) self.cropWidget.cropLeft.valueChanged.connect(self.setCropLeft) self.cropWidget.cropTop.valueChanged.connect(self.setCropTop) self.cropWidget.cropBottom.valueChanged.connect(self.setCropBottom) self.slider = QFrameSelect(self) self.slider.frameSelectionChanged.connect(self.loadFrame) layout.addWidget(self.cropWidget) layout.addWidget(self.slider) self._prepareDlgButtons()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.imageView = QImageView(self) self.frameSelection = QFrameSelect(self) self.frameSelection.frameSelectionChanged.connect(self.updateImage) layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self.imageView) layout.addWidget(self.frameSelection)
def _createControls(self): self.setWindowTitle("Configure Crossfade") layout = QVBoxLayout(self) self.setLayout(layout) self.sourceWidget = QWidget(self) self.source1Selection = self.createSourceControl(self.sourceWidget) self.source1Selection.setSelectFunc(self.isValidSource1) self.source1Selection.currentDataChanged.connect(self.setFilterSource1) self.source1Fade = QCheckBox("Fade Out", self) self.source1Fade.stateChanged.connect(self.setSource1Fade) self.source2Selection = self.createSourceControl(self.sourceWidget) self.source2Selection.setSelectFunc(self.isValidSource2) self.source2Selection.currentDataChanged.connect(self.setFilterSource2) self.source2Fade = QCheckBox("Fade In", self) self.source2Fade.stateChanged.connect(self.setSource2Fade) srclayout = QVBoxLayout() src1layout = QHBoxLayout() src2layout = QHBoxLayout() srclayout.addLayout(src1layout) srclayout.addLayout(src2layout) src1layout.addWidget(QLabel("Source 1: ", self.sourceWidget)) src1layout.addWidget(self.source1Selection) src1layout.addWidget(self.source1Fade) src2layout.addWidget(QLabel("Source 2: ", self.sourceWidget)) src2layout.addWidget(self.source2Selection) src2layout.addWidget(self.source2Fade) self.sourceWidget.setLayout(srclayout) layout.addWidget(self.sourceWidget) self.imageView = QImageView(self) self.frameSelect = QFrameSelect(self) self.frameSelect.frameSelectionChanged.connect( self.handleFrameSelectionChange) layout.addWidget(self.imageView) layout.addWidget(self.frameSelect) self._prepareDlgButtons()
def _createControls(self): self.setWindowTitle("Configure Hue/Saturation/Luminosity") layout = QVBoxLayout(self) self.setLayout(layout) self.sourceWidget = QWidget(self) self.sourceSelection = self.createSourceControl(self.sourceWidget) self.sourceSelection.currentDataChanged.connect(self.setFilterSource) srclayout = QHBoxLayout() srclayout.addWidget(QLabel("Source: ", self.sourceWidget)) srclayout.addWidget(self.sourceSelection) self.sourceWidget.setLayout(srclayout) layout.addWidget(self.sourceWidget) self.imageView = QImageView(self) layout.addWidget(self.imageView) self.slider = QFrameSelect(self) self.slider.frameSelectionChanged.connect(self.loadFrame) layout.addWidget(self.slider) hueLabel = QLabel("Hue adjustment:", self) self.hueSpinBox = QSpinBox(self) self.hueSpinBox.setMinimum(-179) self.hueSpinBox.setMaximum(180) self.hueSpinBox.valueChanged.connect( self._handleHueSpinBoxValueChanged) satLabel = QLabel("Saturation factor:", self) self.satSpinBox = QDoubleSpinBox(self) self.satSpinBox.setDecimals(2) self.satSpinBox.setSingleStep(0.1) self.satSpinBox.setMinimum(0) self.satSpinBox.setMaximum(10) self.satSpinBox.valueChanged.connect( self._handleSatSpinBoxValueChanged) lumLabel = QLabel("Luminosity factor:", self) self.lumSpinBox = QDoubleSpinBox(self) self.lumSpinBox.setDecimals(2) self.lumSpinBox.setMinimum(0) self.lumSpinBox.setMaximum(10) self.lumSpinBox.valueChanged.connect( self._handleLumSpinBoxValueChanged) hlayout = QHBoxLayout() hlayout.addStretch() hlayout.addWidget(hueLabel) hlayout.addWidget(self.hueSpinBox) hlayout.addStretch() hlayout.addWidget(satLabel) hlayout.addWidget(self.satSpinBox) hlayout.addStretch() hlayout.addWidget(lumLabel) hlayout.addWidget(self.lumSpinBox) hlayout.addStretch() layout.addLayout(hlayout) self._prepareDlgButtons()
class QHSLAdjDlg(QFilterConfig): allowedtypes = ("video",) def _createControls(self): self.setWindowTitle("Configure Hue/Saturation/Luminosity") layout = QVBoxLayout(self) self.setLayout(layout) self.sourceWidget = QWidget(self) self.sourceSelection = self.createSourceControl(self.sourceWidget) self.sourceSelection.currentDataChanged.connect(self.setFilterSource) srclayout = QHBoxLayout() srclayout.addWidget(QLabel("Source: ", self.sourceWidget)) srclayout.addWidget(self.sourceSelection) self.sourceWidget.setLayout(srclayout) layout.addWidget(self.sourceWidget) self.imageView = QImageView(self) layout.addWidget(self.imageView) self.slider = QFrameSelect(self) self.slider.frameSelectionChanged.connect(self.loadFrame) layout.addWidget(self.slider) hueLabel = QLabel("Hue adjustment:", self) self.hueSpinBox = QSpinBox(self) self.hueSpinBox.setMinimum(-179) self.hueSpinBox.setMaximum(180) self.hueSpinBox.valueChanged.connect( self._handleHueSpinBoxValueChanged) satLabel = QLabel("Saturation factor:", self) self.satSpinBox = QDoubleSpinBox(self) self.satSpinBox.setDecimals(2) self.satSpinBox.setSingleStep(0.1) self.satSpinBox.setMinimum(0) self.satSpinBox.setMaximum(10) self.satSpinBox.valueChanged.connect( self._handleSatSpinBoxValueChanged) lumLabel = QLabel("Luminosity factor:", self) self.lumSpinBox = QDoubleSpinBox(self) self.lumSpinBox.setDecimals(2) self.lumSpinBox.setMinimum(0) self.lumSpinBox.setMaximum(10) self.lumSpinBox.valueChanged.connect( self._handleLumSpinBoxValueChanged) hlayout = QHBoxLayout() hlayout.addStretch() hlayout.addWidget(hueLabel) hlayout.addWidget(self.hueSpinBox) hlayout.addStretch() hlayout.addWidget(satLabel) hlayout.addWidget(self.satSpinBox) hlayout.addStretch() hlayout.addWidget(lumLabel) hlayout.addWidget(self.lumSpinBox) hlayout.addStretch() layout.addLayout(hlayout) self._prepareDlgButtons() def createNewFilterInstance(self): return HSLAdjust() def _resetControls(self): self.hueSpinBox.blockSignals(True) self.hueSpinBox.setValue(self.filtercopy.dh) self.hueSpinBox.blockSignals(False) self.satSpinBox.blockSignals(True) self.satSpinBox.setValue(self.filtercopy.sfactor) self.satSpinBox.blockSignals(False) self.lumSpinBox.blockSignals(True) self.lumSpinBox.setValue(self.filtercopy.lgamma) self.lumSpinBox.blockSignals(False) if self.filtercopy.prev is not None: self.slider.setPtsTimeArray(self.filtercopy.prev.pts_time) self.loadFrame(self.slider.slider.value(), QTime()) def _handleHueSpinBoxValueChanged(self, value): self.filtercopy.dh = value self.isModified() self.loadFrame(self.slider.slider.value(), None) def _handleSatSpinBoxValueChanged(self, value): self.filtercopy.sfactor = value self.isModified() self.loadFrame(self.slider.slider.value(), None) def _handleLumSpinBoxValueChanged(self, value): self.filtercopy.sfactor = value self.isModified() self.loadFrame(self.slider.slider.value(), None) @pyqtSlot(int, QTime) def loadFrame(self, n, t): if self.filtercopy.prev is not None: frame = next(self.filtercopy.iterFrames(n, whence="framenumber")) im = frame.to_image() pixmap = im.convert("RGBA").toqpixmap() self.imageView.setFrame(pixmap) def _prevChanged(self, source): self.slider.setPtsTimeArray(source.pts_time) self.loadFrame(self.slider.slider.value(), self.slider.currentTime.time())
class QCrossFade(QFilterConfig): allowedtypes = ("video", "audio") def _createControls(self): self.setWindowTitle("Configure Crossfade") layout = QVBoxLayout(self) self.setLayout(layout) self.sourceWidget = QWidget(self) self.source1Selection = self.createSourceControl(self.sourceWidget) self.source1Selection.setSelectFunc(self.isValidSource1) self.source1Selection.currentDataChanged.connect(self.setFilterSource1) self.source1Fade = QCheckBox("Fade Out", self) self.source1Fade.stateChanged.connect(self.setSource1Fade) self.source2Selection = self.createSourceControl(self.sourceWidget) self.source2Selection.setSelectFunc(self.isValidSource2) self.source2Selection.currentDataChanged.connect(self.setFilterSource2) self.source2Fade = QCheckBox("Fade In", self) self.source2Fade.stateChanged.connect(self.setSource2Fade) srclayout = QVBoxLayout() src1layout = QHBoxLayout() src2layout = QHBoxLayout() srclayout.addLayout(src1layout) srclayout.addLayout(src2layout) src1layout.addWidget(QLabel("Source 1: ", self.sourceWidget)) src1layout.addWidget(self.source1Selection) src1layout.addWidget(self.source1Fade) src2layout.addWidget(QLabel("Source 2: ", self.sourceWidget)) src2layout.addWidget(self.source2Selection) src2layout.addWidget(self.source2Fade) self.sourceWidget.setLayout(srclayout) layout.addWidget(self.sourceWidget) self.imageView = QImageView(self) self.frameSelect = QFrameSelect(self) self.frameSelect.frameSelectionChanged.connect( self.handleFrameSelectionChange) layout.addWidget(self.imageView) layout.addWidget(self.frameSelect) self._prepareDlgButtons() def _resetSourceModels(self): self._resetSourceModel(self.source1Selection) self._resetSourceModel(self.source2Selection) @pyqtSlot(int, QTime) def handleFrameSelectionChange(self, n, t): self.setFrame(n) def setSource1Fade(self, value): if value: self.filtercopy.flags &= ~1 else: self.filtercopy.flags |= 1 if (self.filtercopy.prev is not None and self.filtercopy.prev.type == "video"): self.setFrame(self.frameSelect.slider.value()) self.isModified() def setSource2Fade(self, value): if value: self.filtercopy.flags &= ~2 else: self.filtercopy.flags |= 2 if (self.filtercopy.prev is not None and self.filtercopy.prev.type == "video"): self.setFrame(self.frameSelect.slider.value()) self.isModified() def setFrame(self, n): try: frame = next(self.filtercopy.iterFrames(n, whence="framenumber")) except StopIteration: self.imageView.setFrame( QPixmap(self.filtercopy.width, self.filtercopy.height)) return im = frame.to_image() pixmap = im.convert("RGBA").toqpixmap() self.imageView.setFrame(pixmap) def createNewFilterInstance(self): return CrossFade() def _resetSourceControls(self): self._showSourceControls(self.inputFiles or self.availableFilters) self._setSourceSelection(self.source1Selection, self.filtercopy.source1) self._setSourceSelection(self.source2Selection, self.filtercopy.source2) def _resetControls(self): if self.filtercopy is not None: self.source1Fade.blockSignals(True) self.source1Fade.setCheckState(0 if ( 1 & self.filtercopy.flags) else 2) self.source1Fade.blockSignals(False) self.source2Fade.blockSignals(True) self.source2Fade.setCheckState(0 if ( 2 & self.filtercopy.flags) else 2) self.source2Fade.blockSignals(False) self.frameSelect.setVisible(self.filtercopy.type == "video") self.imageView.setVisible(self.filtercopy.type == "video") if self.filtercopy.type == "video": self.frameSelect.setPtsTimeArray(self.filtercopy.pts_time) self.setFrame(0) self.setEnabled(True) else: self.source1Fade.blockSignals(True) self.source1Fade.setCheckState(2) self.source1Fade.blockSignals(False) self.source2Fade.blockSignals(True) self.source2Fade.setCheckState(2) self.source2Fade.blockSignals(False) self.frameSelect.setVisible(False) self.imageView.setVisible(False) self.setEnabled(False) def setFilterSource1(self, source): self.imageView.setVisible(source is not None and source.type == "video") self.filtercopy.source1 = source self.isModified() if (source is not None and self.filtercopy.source2 is not None and source.type == "video"): self.frameSelect.setPtsTimeArray(source.pts_time) self.setFrame(self.frameSelect.slider.value()) def setFilterSource2(self, source): self.imageView.setVisible(source is not None and source.type == "video") self.filtercopy.source2 = source self.isModified() if (source is not None and self.filtercopy.source1 is not None and source.type == "video"): self.frameSelect.setPtsTimeArray(source.pts_time) self.setFrame(self.frameSelect.slider.value()) def isValidSource1(self, other): if other is self.filter: return False if (isinstance(other, BaseFilter) and self.filter in other.dependencies): return False if self.filtercopy.source2 is None: return other.type in ("video", "audio") if other.type is None: return True elif self.filtercopy.source2.type == "video": return (self.filtercopy.source2.framecount == other.framecount and self.filtercopy.source2.width == other.width and self.filtercopy.source2.height == other.height and (abs(self.filtercopy.source2.pts_time - other.pts_time) < 0.008).all()) elif self.filtercopy.source2.type == "audio": return (self.filtercopy.source2.channels == other.channels and abs(self.filtercopy.source2.duration - other.duration) < 0.00001) def isValidSource2(self, other): if other is self.filter: return False if isinstance(other, BaseFilter) and self.filter in other.dependencies: return False if other.type is None: return True if self.filtercopy.source1 is None: return other.type in ("video", "audio") elif self.filtercopy.source1.type == "video": return (self.filtercopy.source1.framecount == other.framecount and self.filtercopy.source1.width == other.width and self.filtercopy.source1.height == other.height and (abs(self.filtercopy.source1.pts_time - other.pts_time) < 0.008).all()) elif self.filtercopy.source1.type == "audio": return (self.filtercopy.source1.channels == other.channels and abs(self.filtercopy.source1.duration - other.duration) < 0.00001)
class CropDlg(QFilterConfig): allowedtypes = ("video",) def _createControls(self): self.setWindowTitle("Configure Crop") layout = QVBoxLayout(self) self.setLayout(layout) self.sourceWidget = QWidget(self) self.sourceSelection = self.createSourceControl(self.sourceWidget) self.sourceSelection.currentDataChanged.connect(self.setFilterSource) srclayout = QHBoxLayout() srclayout.addWidget(QLabel("Source: ", self.sourceWidget)) srclayout.addWidget(self.sourceSelection) self.sourceWidget.setLayout(srclayout) layout.addWidget(self.sourceWidget) self.cropWidget = QCrop(self) self.cropWidget.cropRight.valueChanged.connect(self.setCropRight) self.cropWidget.cropLeft.valueChanged.connect(self.setCropLeft) self.cropWidget.cropTop.valueChanged.connect(self.setCropTop) self.cropWidget.cropBottom.valueChanged.connect(self.setCropBottom) self.slider = QFrameSelect(self) self.slider.frameSelectionChanged.connect(self.loadFrame) layout.addWidget(self.cropWidget) layout.addWidget(self.slider) self._prepareDlgButtons() @pyqtSlot(int, QTime) def loadFrame(self, n, t): if self.filtercopy.prev is not None: frame = next( self.filtercopy.prev.iterFrames(n, whence="framenumber")) im = frame.to_image() pixmap = im.convert("RGBA").toqpixmap() self.cropWidget.setFrame(pixmap) self.cropWidget.resize(pixmap.size()) def createNewFilterInstance(self): return Crop() def _prevChanged(self, source): self._resetControlMaximums() self.slider.setPtsTimeArray(source.pts_time) self.loadFrame(self.slider.slider.value(), self.slider.currentTime.time()) def _resetControlMaximums(self): if self.filtercopy.prev is not None: self.cropWidget.cropTop.setMaximum( self.filtercopy.prev.height - self.filtercopy.cropbottom - 2) self.cropWidget.cropBottom.setMaximum( self.filtercopy.prev.height - self.filtercopy.croptop - 2) self.cropWidget.cropRight.setMaximum( self.filtercopy.prev.width - self.filtercopy.cropleft - 2) self.cropWidget.cropLeft.setMaximum( self.filtercopy.prev.width - self.filtercopy.cropright - 2) def _resetControls(self): self.cropWidget.cropTop.blockSignals(True) self.cropWidget.cropTop.setValue(self.filtercopy.croptop) self.cropWidget.cropTop.blockSignals(False) self.cropWidget.cropBottom.blockSignals(True) self.cropWidget.cropBottom.setValue(self.filtercopy.cropbottom) self.cropWidget.cropBottom.blockSignals(False) self.cropWidget.cropLeft.blockSignals(True) self.cropWidget.cropLeft.setValue(self.filtercopy.cropleft) self.cropWidget.cropLeft.blockSignals(False) self.cropWidget.cropRight.blockSignals(True) self.cropWidget.cropRight.setValue(self.filtercopy.cropright) self.cropWidget.cropRight.blockSignals(False) if self.filtercopy.prev is not None: self.cropWidget.setFrameWidth(self.filtercopy.prev.width) self.cropWidget.setFrameHeight(self.filtercopy.prev.height) self.slider.setPtsTimeArray(self.filtercopy.prev.pts_time) self.loadFrame(self.slider.slider.value(), QTime()) else: self.cropWidget.setFrameWidth(1920) self.cropWidget.setFrameHeight(1080) self.slider.setPtsTimeArray(None) @pyqtSlot(int) def setCropTop(self, croptop): self.filtercopy.croptop = croptop self.isModified() @pyqtSlot(int) def setCropBottom(self, cropbottom): self.filtercopy.cropbottom = cropbottom self.isModified() @pyqtSlot(int) def setCropLeft(self, cropleft): self.filtercopy.cropleft = cropleft self.isModified() @pyqtSlot(int) def setCropRight(self, cropright): self.filtercopy.cropright = cropright self.isModified()