class PlayVideo(DisplayEvent): def __init__(self, frame, settings): super().__init__(frame, settings) self.url = QUrl(settings.get("url")) self.start_time = settings.get("start", 0) * 1000 self.duration = settings.get("duration") self.loop = settings.get("loop", True) self.volume = settings.get("volume", 100) self.playback_rate = settings.get("playbackRate", 1.0) def do_tick(self): if self.player: self.logging.info("position: %s/%s status: %s error: %s" % ( self.player.position(), self.player.duration(), self.player.mediaStatus(), self.player.errorString(), )) if self.player.errorString(): self.logging.error(self.player.errorString()) self.cancel() def do_initialize(self): super().do_initialize() self.video = QVideoWidget(self.widget) self.add_widget(self.video) self.video.show() self.media = QMediaContent(self.url) self.playlist = QMediaPlaylist(self.video) self.playlist.addMedia(self.media) self.playlist.setPlaybackMode( QMediaPlaylist.Loop if self.loop else QMediaPlaylist.Sequential) self.player = QMediaPlayer(self.widget) self.player.setVideoOutput(self.video) self.player.setVolume(self.volume) self.player.setPlaybackRate(self.playback_rate) def do_run(self): super().do_run() self.player.setPlaylist(self.playlist) self.player.setPosition(self.start_time) self.player.play() if self.player.errorString(): self.logging.error(self.player.errorString()) self.cancel() def do_stop(self): super().do_stop() self.player.stop() def do_reset(self): self.player = None self.video = None
class IntroWindow(QMainWindow, Form): def __init__(self): Form.__init__(self) QMainWindow.__init__(self) self.setWindowIcon(QIcon("logo.png")) p = self.palette() p.setColor(QPalette.Window, Qt.gray) self.setPalette(p) self.setupUi(self) self.a = 1 self.videowidget = QVideoWidget() self.vertical.addWidget(self.videowidget) self.videoplayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoplayer.setVideoOutput(self.videowidget) self.sliderfilm.setRange(0, 0) self.volume.setRange(0, 100) self.videoplayer.setVolume(100) self.volume.setValue(100) self.play.setEnabled(False) self.increaseRate.setEnabled(False) self.decreaseRate.setEnabled(False) self.sliderfilm.installEventFilter(self) self.volume.installEventFilter(self) self.frames.installEventFilter(self) self.frame_2.installEventFilter(self) self.frames.installEventFilter(self) # putting Icons on buttons self.increaseRate.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.decreaseRate.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.open.setIcon(self.style().standardIcon(QStyle.SP_DirHomeIcon)) self.skipforward.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.skipback.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.sliderfilm.sliderMoved.connect(self.setpos) self.videoplayer.positionChanged.connect(self.position) self.videoplayer.durationChanged.connect(self.changed) self.videoplayer.volumeChanged.connect(self.setvolpos) self.volume.sliderMoved.connect(self.setvolpos) self.actionOpen.triggered.connect(self.Loadvideo) self.actionSearch_By_Tag.triggered.connect(self.opensecond) self.actionFullscreen.triggered.connect(self.screen) self.skipforward.clicked.connect(self.skipforw) self.skipback.clicked.connect(self.skipbac) self.increaseRate.clicked.connect(self.incRate) self.decreaseRate.clicked.connect(self.decRate) self.play.clicked.connect(self.play_video) self.open.clicked.connect(lambda: self.Loadvideo(self.videoplayer)) self.stop.clicked.connect(self.stopp) self.listView.hide() self.tolfilm = 0 self.listviewstatus = 0 self.listbtn.clicked.connect(lambda: self.list()) self.listView.itemClicked.connect(self.listwidgetclicked) self.theme1.triggered.connect(lambda: self.theme01()) self.theme2.triggered.connect(lambda: self.theme02()) self.theme3.triggered.connect(lambda: self.theme03()) self.theme4.triggered.connect(lambda: self.theme04()) self.actionFarsi.triggered.connect(lambda: self.farsi()) self.actionEnglish.triggered.connect(lambda: self.english()) self.filename = "" self.x = 0 self.videowidget3 = QVideoWidget() self.verticalLayout_8.addWidget(self.videowidget3) self.videoplayer3 = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoplayer3.setVideoOutput(self.videowidget3) self.widget.hide() self.stop.setEnabled(False) self.m = 0 self.dataL = [] with open("config.txt") as f: self.config = f.read() if int(self.config) == 11: self.theme01() self.farsi() if int(self.config) == 12: self.theme01() self.english() elif int(self.config) == 21: self.farsi() self.theme02() elif int(self.config) == 22: self.english() self.theme02() elif int(self.config) == 31: self.farsi() self.theme03() elif int(self.config) == 32: self.english() self.theme03() elif int(self.config) == 41: self.farsi() self.theme04() elif int(self.config) == 42: self.english() self.theme04() def farsi(self): self.menuLanguage.setTitle("زبان") self.menuView.setTitle("نمایش") self.theme1.setText("تم ۱") self.theme2.setText("تم ۲") self.theme3.setText("تم ۳") self.theme4.setText("تم ۴") self.menuFile.setTitle("فایل") self.actionOpen.setText("باز کردن ویدیو") self.actionSearch_By_Tag.setText("پنل تگ ها") self.actionFullscreen.setText("تمام صفحه") self.actionEnglish.setText("انگلیسی") self.actionFarsi.setText("فارسی") self.decreaseRate.setStatusTip("کاهش سرعت") self.decreaseRate.setToolTip("کاهش سرعت") self.increaseRate.setStatusTip("افزایش سرعت") self.increaseRate.setToolTip("افزایش سرعت") self.open.setStatusTip("باز کردن ویدیو") self.open.setToolTip("باز کردن ویدیو") self.stop.setStatusTip("توقف") self.stop.setToolTip("توقف") self.skipback.setStatusTip("عقب رفتن") self.skipback.setToolTip("عقب رفتن") self.play.setStatusTip("شروع/ایست") self.play.setToolTip("شروع/ایست") self.skipforward.setStatusTip("جلو رفتن") self.skipforward.setToolTip("جلو رفتن") self.volume.setStatusTip("صدا") self.volume.setToolTip("صدا") self.listbtn.setStatusTip("دسترسی آسان") self.listbtn.setToolTip( "پنلی شامل تگ ها و پنجره ای برای پیش نمایش را نمایان/پنهان میکند که با کلیک کردن بر روی هر کدام ویدیو به آن لحظه میرود" ) with open("config.txt") as f: self.config = f.read() if int(self.config) // 10 == 1: with open("config.txt", "w") as f2: f2.write("11") if int(self.config) // 10 == 2: with open("config.txt", "w") as f2: f2.write("21") if int(self.config) // 10 == 3: with open("config.txt", "w") as f2: f2.write("31") if int(self.config) // 10 == 4: with open("config.txt", "w") as f2: f2.write("41") def english(self): self.menuLanguage.setTitle("Language") self.menuView.setTitle("View") self.theme1.setText("Theme1") self.theme2.setText("Theme2") self.theme3.setText("Theme3") self.theme4.setText("Theme4") self.menuFile.setTitle("File") self.actionOpen.setText("Open Video") self.actionSearch_By_Tag.setText("Tags Panel") self.actionFullscreen.setText("Fullscreen") self.actionEnglish.setText("English") self.actionFarsi.setText("Persian") self.decreaseRate.setStatusTip("Decrease Play Speed") self.decreaseRate.setToolTip("Decrease Play Speed") self.increaseRate.setStatusTip("Increase Play Speed") self.increaseRate.setToolTip("Increase Play Speed") self.open.setStatusTip("Open Video") self.open.setToolTip("Open Video") self.stop.setStatusTip("Stop") self.stop.setToolTip("Stop") self.skipback.setStatusTip("Previous") self.skipback.setToolTip("Previous") self.play.setStatusTip("Play/Pause") self.play.setToolTip("Play/Pause") self.skipforward.setStatusTip("Next") self.skipforward.setToolTip("Next") self.volume.setStatusTip("Volume") self.volume.setToolTip("Volume") self.listbtn.setStatusTip("Easy Access") self.listbtn.setToolTip( "Shows/Hides a panel for the tags that can be clicked on to take the video to its moment and also a preview window" ) with open("config.txt") as f: self.config = f.read() if self.config == "": with open("config.txt", w) as f2: f2.write("11") self.config = "11" if int(self.config) // 10 == 1: with open("config.txt", "w") as f2: f2.write("12") if int(self.config) // 10 == 2: with open("config.txt", "w") as f2: f2.write("22") if int(self.config) // 10 == 3: with open("config.txt", "w") as f2: f2.write("32") if int(self.config) // 10 == 4: with open("config.txt", "w") as f2: f2.write("42") def moviess(self): x = self.filename.split("/") file_name = self.filename[:self.filename.find(x[len(x) - 1])] png = "" png2 = "" folders = os.listdir(file_name + r"/") for file in folders: if file.find(".mp4") > 0: png = png + ";" + file_name + file png2 = ";" + file_name + file + png2 png = png + ";" self.png = png png2 = png2 + ";" self.png2 = png2 def hoverleave(self): self.widget.hide() def gotovolume(self): x, _ = win32api.GetCursorPos() self.videoplayer.setVolume( int((x - self.mapToGlobal(self.volume.pos()).x()) / self.volume.width() * 100)) self.volume.setValue( int((x - self.mapToGlobal(self.volume.pos()).x()) / self.volume.width() * 100)) if self.m % 2 == 1: self.m += 1 self.videoplayer.setMuted(False) def goto(self): x, _ = win32api.GetCursorPos() if self.filename != "": self.videoplayer.setPosition( (x - self.mapToGlobal(self.sliderfilm.pos()).x()) / self.sliderfilm.width() * self.dur * 1000) def onHovered(self): x, _ = win32api.GetCursorPos() if self.filename != "": if self.listviewstatus % 2 == 1: self.videoplayer3.setPosition( (x - self.mapToGlobal(self.sliderfilm.pos()).x()) / self.sliderfilm.width() * self.dur * 1000) self.widget.show() def eventFilter(self, obj, event): if obj == self.sliderfilm and event.type() == QtCore.QEvent.HoverMove: self.onHovered() elif (obj == self.frames or obj == self.frame_2) and event.type() == QtCore.QEvent.Enter: self.hoverleave() elif obj == self.sliderfilm and event.type( ) == QtCore.QEvent.MouseButtonPress: self.goto() elif obj == self.volume and event.type( ) == QtCore.QEvent.MouseButtonPress: self.gotovolume() elif obj == self.frames and event.type( ) == QtCore.QEvent.MouseButtonDblClick: if not self.isFullScreen(): self.fulls() else: self.unfull() return super(QMainWindow, self).eventFilter(obj, event) def stopp(self): self.stop.setEnabled(False) self.videoplayer.stop() self.videoplayer.setPosition(0) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) def listwidgetclicked(self, item): t = item.text() t = t[t.find(">") + 1:] pt = datetime.strptime(t, "%H:%M:%S") total_seconds = pt.second + pt.minute * 60 + pt.hour * 3600 if self.a == 0: self.videoplayer.setPosition(total_seconds * 1000) def list(self): if self.listviewstatus % 2 == 1: self.listView.hide() self.widget.hide() self.listbtn.setText("^") self.listviewstatus += 1 else: self.listbtn.setText("v") self.listviewstatus += 1 self.listView.show() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: if self.isFullScreen(): self.unfull() elif e.key() == Qt.Key_6: if self.filename != "": self.videoplayer.setPosition(self.videoplayer.position() + 5000) elif e.key() == Qt.Key_4: if self.filename != "": self.videoplayer.setPosition(self.videoplayer.position() - 5000) elif e.key() == Qt.Key_Space: if self.filename != "": self.play_video() elif e.key() == Qt.Key_M: if self.m % 2 == 0: self.m += 1 self.videoplayer.setMuted(True) self.volume.setEnabled(False) self.vvv = self.volume.value() self.volume.setValue(0) else: self.m += 1 self.volume.setValue(self.vvv) self.volume.setEnabled(True) self.videoplayer.setMuted(False) def screen(self): if not self.isFullScreen(): self.fulls() else: self.unfull() # forward media 5s def skipforw(self): a = self.png.find(self.filename) aa = self.png.find(";", a + 1) filename = self.png[aa + 1:self.png.find(";", aa + 1)] if filename != "": self.filename = filename self.videoplayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.videoplayer3.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) title = filename.split("/") title = title[len(title) - 1] self.setWindowTitle(f"Taz Player openning{title}") self.videoplayer3.play() self.videoplayer3.pause() self.widget.hide() self.videoplayer.setPosition(0) self.videoplayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) clip = VideoFileClip(filename) self.dur = clip.duration def skipbac(self): a = self.png2.find(self.filename) aa = self.png2.find(";", a + 1) filename = self.png2[aa + 1:self.png2.find(";", aa + 1)] if filename != "": self.filename = filename self.videoplayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.videoplayer3.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) title = filename.split("/") title = title[len(title) - 1] self.setWindowTitle(f"Taz Player openning{title}") self.videoplayer3.play() self.videoplayer3.pause() self.widget.hide() self.videoplayer.setPosition(0) self.videoplayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) clip = VideoFileClip(filename) self.dur = clip.duration # set increase rate def incRate(self): if self.videoplayer.playbackRate() == 0: x = self.videoplayer.playbackRate() + 1 else: x = self.videoplayer.playbackRate() self.videoplayer.setPlaybackRate(x + 0.25) # set decrease rate def decRate(self): if self.videoplayer.playbackRate() == 0: x = self.videoplayer.playbackRate() + 1 else: x = self.videoplayer.playbackRate() self.videoplayer.setPlaybackRate(x - 0.25) # Handling Tags def fillListView(self): for i in range(len(self.dataL)): self.listView.addItem(self.dataL[i][0] + "->" + self.dataL[i][1]) def updateTagFile(self): fname = self.fileName.split(".") fname = fname[0] with open(fname + ".csv", mode="w") as f: writer = csv.writer( f, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL, lineterminator="\n", ) for line in self.dataL: writer.writerow(line) def giveTime(self): vidPos = self.videoplayer.position() h = int(vidPos / 1000 // 3600) m = int((vidPos / 1000 - h * 3600) // 60) s = int(((vidPos / 1000 - h * 3600 - m * 60) % 60) % 60) * 100 // 100 if h < 10: h = "0" + str(h) if m < 10: m = "0" + str(m) if s < 10: s = "0" + str(s) return f"{h}:{m}:{s}" def insertTag(self, tableWidget): t = tableWidget tag = "New Tag" tagTime = self.giveTime() l = len(self.dataL) i = 0 flag = False while tagTime > self.dataL[i][1]: i += 1 if i >= l: break if i < l: if tagTime == self.dataL[i][1]: flag = True if not flag: self.dataL.insert(i, [tag, tagTime]) t.insertRow(i) t.setItem( i, 0, QTableWidgetItem(tag), ) t.setItem( i, 1, QTableWidgetItem(tagTime), ) t.editItem(t.item(i, 0)) def removeRow(self, tableWidget): if len(self.dataL) > 0: self.dataL.remove(self.dataL[tableWidget.currentRow()]) tableWidget.removeRow(tableWidget.currentRow()) def updateList(self, tableWidget): for i in range(tableWidget.rowCount()): self.dataL[i] = [ tableWidget.item(i, 0).text(), tableWidget.item(i, 1).text(), ] def undoChanges(self): fname = self.fileName.split(".") fname = fname[0] with open(fname + ".csv", mode="r+") as f: data = csv.reader(f) self.dataL = list(data) def fillTable(self, tableWidget): tableWidget.setRowCount(len(self.dataL)) for i in range(len(self.dataL)): tableWidget.setItem(i, 0, QTableWidgetItem(self.dataL[i][0])) tableWidget.setItem(i, 1, QTableWidgetItem(self.dataL[i][1])) def openTagFile(self): filename, _ = QFileDialog.getOpenFileName( self, "Open Tag File", filter="*.csv", ) if filename != "": self.fileName = filename with open(filename, mode="r+") as f: data = csv.reader(f) self.dataL = list(data) def opensecond(self): login_page = LoginPage() login_page.setWindowFlags(QtCore.Qt.WindowCloseButtonHint) if int(self.config) % 10 == 1: login_page.Save.setText("برو به") login_page.apply.setText("اعمال تغییرات") login_page.buttonBox.button(QDialogButtonBox.Ok).setText("تایید") login_page.buttonBox.button( QDialogButtonBox.Cancel).setText("انصراف") login_page.AddRow.setText("افزودن تگ") login_page.DeleteRow.setText("حذف تگ") login_page.OpenTagButton.setText("باز کردن فایل تگ") login_page.tableWidget.setHorizontalHeaderLabels(["تگ", "زمان"]) else: login_page.tableWidget.setHorizontalHeaderLabels(["Tag", "Time"]) self.fillTable(login_page.tableWidget) login_page.buttonBox.accepted.connect(lambda: [ self.updateList(login_page.tableWidget), self.listbtn.setFocus(), self.listView.clear(), self.fillListView(), self.updateTagFile(), ]) login_page.buttonBox.rejected.connect(lambda: [ self.listbtn.setFocus(), self.undoChanges(), ]) login_page.apply.clicked.connect(lambda: [ self.updateList(login_page.tableWidget), self.listView.clear(), self.fillListView(), ]) login_page.AddRow.clicked.connect(lambda: [ self.insertTag(login_page.tableWidget), ]) login_page.Save.clicked.connect(lambda: [ login_page.shows(self), self.updateList(login_page.tableWidget), self.listbtn.setFocus(), self.listView.clear(), self.fillListView(), ]) login_page.DeleteRow.clicked.connect(lambda: [ self.removeRow(login_page.tableWidget), ]) login_page.OpenTagButton.clicked.connect(lambda: [ self.openTagFile(), self.fillTable(login_page.tableWidget), self.listView.clear(), self.fillListView(), ]) login_page.tableWidget.sortByColumn(1, Qt.AscendingOrder) # if int(self.config) % 10 == 2: # login_page.tableWidget.setHorizontalHeaderLabels(["Tag", "Time"]) # else: # login_page.tableWidget.setHorizontalHeaderLabels(["تگ", "زمان"]) login_page.exec_() # End of Handling Tags def fulls(self): self.decreaseRate.hide() self.increaseRate.hide() self.centralwidget.setContentsMargins(0, 0, 0, 0) self.play.hide() self.open.hide() self.skipforward.hide() self.skipback.hide() self.label.hide() self.label_2.hide() self.volume.hide() self.menubar.hide() self.sliderfilm.hide() self.statusBar.hide() self.showFullScreen() self.listbtn.hide() self.widget.hide() self.listView.hide() self.frame_2.hide() self.stop.hide() self.listviewstatus = 1 def unfull(self): self.frame_2.show() self.stop.show() self.list() self.centralwidget.setContentsMargins(10, 10, 10, 10) self.decreaseRate.show() self.increaseRate.show() self.play.show() self.open.show() self.skipforward.show() self.skipback.show() self.label.show() self.label_2.show() self.volume.show() self.menubar.show() self.sliderfilm.show() self.statusBar.show() self.showNormal() self.listbtn.show() ##setting position of film def setpos(self, position): self.videoplayer.setPosition(position) def position(self, position): position2 = self.tolfilm * 1000 - position + 1000 hour = int((position / 3600000) % 24) hour2 = int((position2 / 3600000) % 24) if hour < 10: hour = "0" + str(hour) if hour2 < 10: hour2 = "0" + str(hour2) minute = int((position / 60000) % 60) minute2 = int((position2 / 60000) % 60) if minute < 10: minute = "0" + str(minute) if minute2 < 10: minute2 = "0" + str(minute2) second = int((position / 1000) % 60) second2 = int((position2 / 1000) % 60) if second < 10: second = "0" + str(second) if second2 < 10: second2 = "0" + str(second2) self.label.setText(f"{hour}:{minute}:{second}") self.label_2.setText(f"{hour2}:{minute2}:{second2}") self.sliderfilm.setValue(position) if position2 < 1000: self.videoplayer.stop() self.sliderfilm.setValue(0) self.stop.setEnabled(False) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) def changed(self, duration): self.sliderfilm.setRange(0, duration) ##setting position of volume def setvolpos(self, position): self.videoplayer.setVolume(position) ##open button or open from menu bar def Loadvideo(self, videoplayer): self.a = 0 filename, _ = QFileDialog.getOpenFileName( self, "Open Video", filter="*.mp4;*.mov;*.wmv;*.webm;*.wmv;*.m4v;*.m4a;*.flv", ) if filename != "": self.videoplayer.setPosition(0) self.filename = filename if filename != "": self.fileName = filename.split(".")[0] fname = filename.split(".") fnmae = fname[0] if os.path.isfile(fnmae + ".csv"): with open(fnmae + ".csv", mode="r+") as f: data = csv.reader(f) self.dataL = list(data) self.listView.clear(), self.fillListView() clip = VideoFileClip(filename) self.dur = clip.duration self.videoplayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.videoplayer3.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.moviess() clip = VideoFileClip(filename) self.tolfilm = int(clip.duration) title = filename.split("/") title = title[len(title) - 1] self.setWindowTitle(f"Taz Player openning : {title}") self.videoplayer3.play() self.videoplayer3.pause() self.widget.hide() self.stop.setEnabled(True) self.videoplayer.play() self.play.setEnabled(True) self.play.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.increaseRate.setEnabled(True) self.decreaseRate.setEnabled(True) ##play button def play_video(self): if self.videoplayer.state() == QMediaPlayer.PlayingState: self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.videoplayer.pause() else: self.videoplayer.play() self.stop.setEnabled(True) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) def theme01(self): self.videowidget.setStyleSheet("background-color: #404040") self.setStyleSheet("background-color: #A0A0A0") if self.theme1.text() == "Theme1": with open("config.txt", "w") as f: f.write("12") else: with open("config.txt", "w") as f: f.write("11") def theme02(self): self.videowidget.setStyleSheet("background-color: #330019") self.setStyleSheet("background-color: #990000") if self.theme1.text() == "Theme1": with open("config.txt", "w") as f: f.write("22") else: with open("config.txt", "w") as f: f.write("21") def theme03(self): self.videowidget.setStyleSheet("background-color: #35557F") self.setStyleSheet("background-color: #003366") if self.theme1.text() == "Theme1": with open("config.txt", "w") as f: f.write("32") else: with open("config.txt", "w") as f: f.write("31") def theme04(self): self.videowidget.setStyleSheet("background-color: #00FF00") self.setStyleSheet("background-color: #4C9900") if self.theme1.text() == "Theme1": with open("config.txt", "w") as f: f.write("42") else: with open("config.txt", "w") as f: f.write("41")
class GameWindow(QWidget): def __init__(self, parent=None): super(GameWindow,self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget() self.mediaPlayer.setVideoOutput(self.videoWidget) self.stringLabel = QLabel() self.stringLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.stringLabel.setTextFormat(Qt.RichText) self.stringLabel.setAlignment(Qt.AlignHCenter) layout = QVBoxLayout() layout.addWidget(self.videoWidget) layout.addWidget(self.stringLabel) self.setLayout(layout) self.mediaPlayer.positionChanged.connect(self.positionChanged) def openFile(self, fileName): if fileName != '': self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(fileName))) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def playV(self, file, rate, visibility, labelString): self.position = 0 self.startPos = 0 self.duration = 0 self.durChanged = False self.stopPos = False self.openFile(file) self.mediaPlayer.setPlaybackRate(rate) if visibility: self.videoWidget.show() self.stringLabel.show() self.stringLabel.setText(labelString) else: self.videoWidget.hide() self.stringLabel.show() self.stringLabel.setText(labelString) self.play() def closeEvent(self, event): event.ignore() self.mediaPlayer.stop() super(GameWindow, self).closeEvent(event) def positionChanged(self, pos): self.position = pos if not self.durChanged and self.position > 0: self.durationChanged(self.mediaPlayer.duration()) self.durChanged = True if self.startPos > 0 and not self.stopPos and not self.videoWidget.isVisible(): if self.position > self.startPos + 20000: self.play() self.stopPos = True def durationChanged(self, dur): self.duration = dur if self.duration > 40000 and not self.videoWidget.isVisible(): self.startPos = random.randint(5000, self.duration - 25000) self.mediaPlayer.setPosition(self.startPos) def showPoints(self, pointsString): self.videoWidget.hide() self.stringLabel.show() self.stringLabel.setText(pointsString)
class Player(QMainWindow): def __init__(self, playlist, parent=None): super(Player, self).__init__(parent) self.setWindowTitle("Behavior Voting System") self.config = configparser.ConfigParser() self.config.read('configFile.cfg') self.voteOptions = self.config['Epoch_Specs']['BUTTON_NAMES'].split( ",") self.currVid = "" self.totalVids = len(os.listdir(self.config['Paths']['CLIP_PATH'])) #Set Up Media Player self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget() self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.setUpButtons() self.setLayout() #Launch Login Window self.loginWindow = Login() self.loginWindow.resize(640, 400) self.loginWindow.exec_() self.csv = self.loginWindow.getCSV() #set a default vote for one vote setting if self.config['Epoch_Specs']['ONE_VOTE_MAX'] == 'True': self.voteList[0].select() #Play First Video self.getVid() def toggleButton(self): s = self.sender() if self.config['Epoch_Specs']['ONE_VOTE_MAX'] == 'True': for vote in self.voteList: vote.reset() s.select() #Makes spaceBar do the same thing as clicking "Next Video" def keyPressEvent(self, e): if e.key() == QKeySequence( self.config['Keyboard_Shortcuts']['PLAY_SHORTCUT']): if self.config['Video_Control_Specs'][ 'LEFT_RIGHT_BUTTONS'] == 'True': self.forwardFrame.setDown(False) self.backFrame.setDown(False) self.playVid() if e.key() == QKeySequence("Return"): self.speedSelect.clearFocus() self.mediaPlayer.setPlaybackRate(float(self.speedSelect.text())) def forward(self): self.mediaPlayer.pause() p = self.mediaPlayer.position() if p + 100 < self.mediaPlayer.duration(): self.mediaPlayer.setPosition(p + 100) def back(self): self.mediaPlayer.pause() p = self.mediaPlayer.position() if p - 100 > 0: self.mediaPlayer.setPosition(p - 100) #Return string of selected action for current vid def getSelected(self): selected = " " comma = False for i in range(len(self.voteList)): if self.voteList[i].getVal(): if comma: selected = selected + ", " selected = selected + self.voteOptions[i] comma = True if selected == " ": selected = "None" return selected #confirms selection, writes selection to csv, and then plays next video def next(self): if self.csv == 0: self.loginWindow.exec_() self.csv = self.loginWindow.getCSV() return reply = 0 msgBox = QMessageBox() msgBox.setText("Correct Action Labels?") s = self.getSelected() msgBox.setInformativeText(s + '\n') msgBox.setStandardButtons(QMessageBox.No | QMessageBox.Yes) msgBox.setDefaultButton(QMessageBox.Yes) msgBox.setStyleSheet( "QLabel{min-width:600 px; font-size: 20px;} QPushButton{ width:250px; font-size: 18px; }" ) h = msgBox.exec_() if h == QMessageBox.No: return self.loginWindow.getFinished().add(self.currVid.split(".")[0]) s = s.replace(" ", "") s = s.replace("None", "") self.csv.write(self.currVid + "," + s + "\n") for vote in self.voteList: vote.reset() if self.config['Epoch_Specs']['ONE_VOTE_MAX'] == 'True': self.voteList[0].select() self.getVid() #get and load random video def getVid(self): if len(self.loginWindow.getFinished()) == self.totalVids: msgBox = QMessageBox() msgBox.setText("Annotations Complete") msgBox.exec_() self.csv.close() self.csv = 0 return self.currVid = random.choice( os.listdir(self.config['Paths']['CLIP_PATH'])) while self.currVid in self.loginWindow.getFinished(): self.currVid = random.choice( os.listdir(self.config['Paths']['CLIP_PATH'])) self.path = self.config['Paths']['CLIP_PATH'] + self.currVid self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(self.path))) self.mediaPlayer.play() self.setFocus() #play button def playVid(self): self.mediaPlayer.setPlaybackRate(float(self.speedSelect.text())) if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() #restart video def restart(self): if self.config['Video_Control_Specs']['LEFT_RIGHT_BUTTONS'] == 'True': self.forwardFrame.setDown(False) self.backFrame.setDown(False) self.mediaPlayer.setPlaybackRate(float(self.speedSelect.text())) self.setPosition(0) #change play/pause button based on state and restart video if video ends def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.playButton.setText( "PAUSE VIDEO (" + self.config['Keyboard_Shortcuts']['PLAY_SHORTCUT'] + ")") elif self.mediaPlayer.state() == QMediaPlayer.PausedState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) self.playButton.setText( "PLAY VIDEO (" + self.config['Keyboard_Shortcuts']['PLAY_SHORTCUT'] + ")") else: self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(self.path))) self.mediaPlayer.pause() def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def closeEvent(self, event): if self.csv != 0: self.csv.close() def setUpButtons(self): # Set Up Vote Buttons self.voteList = [] shortcuts = self.config['Keyboard_Shortcuts']['VOTE_SHORTCUTS'].split( ',') for i in range(len(self.voteOptions)): button = VoteButton(" " + self.voteOptions[i]) button.clicked.connect(self.toggleButton) button.setShortcut(QKeySequence( str(shortcuts[i]).replace(" ", ""))) button.setIconSize(QSize(35, 35)) self.voteList.append(button) # Set Up Submit Button self.nextButton = QPushButton( "SUBMIT ANNOTATIONS (" + self.config['Keyboard_Shortcuts']['SUBMIT_SHORTCUT'] + ")") self.nextButton.clicked.connect(self.next) self.nextButton.setShortcut( QKeySequence(self.config['Keyboard_Shortcuts']['SUBMIT_SHORTCUT'])) self.nextButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) # Set Up Video Scroll Bar if self.config['Video_Control_Specs']['SCROLL_BAR'] == 'True': self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) # Set Up Play Button if self.config['Video_Control_Specs']['PLAY_BUTTON'] == 'True': self.playButton = QPushButton( "PLAY VIDEO (" + self.config['Keyboard_Shortcuts']['PLAY_SHORTCUT'] + ")") self.playButton.clicked.connect(self.playVid) self.playButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) # Set Up Restart Video Button if self.config['Video_Control_Specs']['RESTART_BUTTON'] == 'True': self.restartButton = QPushButton( "RESTART (" + self.config['Keyboard_Shortcuts']['RESTART_SHORTCUT'] + ")") self.restartButton.clicked.connect(self.restart) self.restartButton.setShortcut( QKeySequence( self.config['Keyboard_Shortcuts']['RESTART_SHORTCUT'])) self.restartButton.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.restartButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) # Set Up Left Right Buttons if self.config['Video_Control_Specs']['LEFT_RIGHT_BUTTONS'] == 'True': self.backFrame = QPushButton() self.forwardFrame = QPushButton() self.backFrame.clicked.connect(self.back) self.forwardFrame.clicked.connect(self.forward) self.backFrame.setShortcut( QKeySequence( self.config['Keyboard_Shortcuts']['LEFT_SHORTCUT'])) self.forwardFrame.setShortcut( QKeySequence( self.config['Keyboard_Shortcuts']['RIGHT_SHORTCUT'])) self.backFrame.setIcon(QIcon("./icons/back.png")) self.forwardFrame.setIcon(QIcon("./icons/forward.png")) self.backFrame.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.forwardFrame.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) #Set Up Speed Spin Box if self.config['Video_Control_Specs']['SPEED_CONTROL'] == 'True': self.speedButton = QLabel("Select Speed: ") self.speedSelect = QDoubleSpinBox() self.speedSelect.setValue(1.0) self.speedSelect.setSingleStep(0.1) self.speedSelect.setFocusPolicy(Qt.ClickFocus) def setLayout(self): #Set Layout verticalSpacerSmall = QSpacerItem(10, 10, QSizePolicy.Fixed, QSizePolicy.Fixed) verticalSpacerLarge = QSpacerItem(10, 200, QSizePolicy.Fixed, QSizePolicy.Fixed) voteBox = QHBoxLayout() voteWidget = QWidget(self) for i in range(len(self.voteOptions)): voteBox.addWidget(self.voteList[i]) voteWidget.setLayout(voteBox) vidBox = QVBoxLayout() vidWidget = QWidget(self) vidBox.addWidget(self.videoWidget, 8) if self.config['Video_Control_Specs']['SCROLL_BAR'] == 'True': vidBox.addWidget(self.positionSlider, 1) vidBox.addWidget(voteWidget, 2) vidBox.addWidget(self.nextButton, 1) vidWidget.setLayout(vidBox) if self.config['Video_Control_Specs']['LEFT_RIGHT_BUTTONS'] == 'True': frameBox = QHBoxLayout() frameWidget = QWidget(self) frameBox.addWidget(self.backFrame) frameBox.addWidget(self.forwardFrame) frameWidget.setLayout(frameBox) if self.config['Video_Control_Specs']['SPEED_CONTROL'] == 'True': speedBox = QHBoxLayout() speedWidget = QWidget(self) speedBox.addWidget(self.speedButton) speedBox.addWidget(self.speedSelect) speedWidget.setLayout(speedBox) controlBox = QVBoxLayout() controlWidget = QWidget(self) controlBox.addWidget(self.playButton) if self.config['Video_Control_Specs']['LEFT_RIGHT_BUTTONS'] == 'True': controlBox.addWidget(frameWidget) controlBox.addWidget(self.restartButton) if self.config['Video_Control_Specs']['SPEED_CONTROL'] == 'True': controlBox.addWidget(speedWidget) controlBox.addItem(verticalSpacerLarge) controlWidget.setLayout(controlBox) wid = QWidget(self) self.setCentralWidget(wid) mainBox = QHBoxLayout() mainBox.addWidget(vidWidget, 4) mainBox.addWidget(controlWidget, 1) wid.setLayout(mainBox)
class Window(QWidget): def __init__(self): super().__init__() self.audio = "" self.sampFreq = 0 self.setWindowTitle("Silence Skipper Video Player") self.setGeometry(350, 100, 700, 500) self.setWindowIcon(QIcon('helicopter.jpg')) p = self.palette() p.setColor(QPalette.Window, Qt.black) self.setPalette(p) self.init_ui() self.show() def init_ui(self): # create media player object self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) # create videowidget object videowidget = QVideoWidget() # create open button openBtn = QPushButton('Open Video') openBtn.clicked.connect(self.open_file) # create button for playing self.playBtn = QPushButton() self.playBtn.setEnabled(False) self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.clicked.connect(self.play_video) self.playBtnShortcut = QShortcut(QKeySequence('Space'), self) self.playBtnShortcut.activated.connect(self.play_video) # create skip forward button self.skipForward = QPushButton() self.skipForward.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.skipForward.setEnabled(False) self.skipForward.clicked.connect(self.skip_forward) self.forwardShortcut = QShortcut(QKeySequence('Right'), self) self.forwardShortcut.activated.connect(self.skip_forward) self.forwardShortcut = QShortcut(QKeySequence('Shift+Right'), self) self.forwardShortcut.activated.connect(self.skip_forward_tiny) #make mutton invis self.skipForward.setVisible(False) # create skip backward button self.skipBackwards = QPushButton() self.skipBackwards.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.skipBackwards.setEnabled(False) self.skipBackwards.clicked.connect(self.skip_backwards) self.backwardsShortcut = QShortcut(QKeySequence('Left'), self) self.backwardsShortcut.activated.connect(self.skip_backwards) self.backwardsShortcutTiny = QShortcut(QKeySequence('Shift+Left'), self) self.backwardsShortcutTiny.activated.connect(self.skip_backwards_tiny) #make mutton invis self.skipBackwards.setVisible(False) # create speed setter button self.speedButton = MyQLineEdit() self.speedButton.textChanged[str].connect(self.speed_popup) speed = "1" self.speedButton.setText(speed) self.speedButton.setMaxLength(4) self.speedButton.setFixedWidth(30) self.label = QLabel('Yellow', self) self.label.setStyleSheet("color:white;") self.label.setText("sound threshold factor: ") self.label.setAlignment(Qt.AlignRight) self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) #self.label.setFixedWidth(160) self.soundThreshold = MyQLineEdit() self.soundThreshold.textChanged[str].connect(self.sound_thresh) self.soundThreshold.setText(str(audioThreshold)) self.soundThreshold.setMaxLength(5) self.soundThreshold.setFixedWidth(35) self.soundThreshold.setAlignment(Qt.AlignLeft) #self.speedButton.editingFinished.connect(self.speed_popup) # create slider self.slider = QJumpSlider(Qt.Horizontal, mediaP=self.mediaPlayer) #self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, 0) self.slider.sliderMoved.connect(self.set_position) # create label self.label2 = QLabel('Yellow', self) self.label2.setStyleSheet( "background-color: yellow; border: 1px solid black;") self.label2.setText("duration") self.label2.setAlignment(Qt.AlignRight) self.label2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) hboxLayout2 = QHBoxLayout() hboxLayout2.setContentsMargins(0, 0, 0, 0) hboxLayout2.addWidget(self.label) hboxLayout2.addWidget(self.soundThreshold) # create hbox layout hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) # set widgets to the hbox layout hboxLayout.addWidget(openBtn) hboxLayout.addWidget(self.playBtn) hboxLayout.addWidget(self.skipBackwards) hboxLayout.addWidget(self.skipForward) hboxLayout.addWidget(self.slider) hboxLayout.addWidget(self.speedButton) hboxLayout.addWidget(self.label2) # create vbox layout vboxLayout = QVBoxLayout() vboxLayout.addLayout(hboxLayout2) vboxLayout.addWidget(videowidget) vboxLayout.addLayout(hboxLayout) vboxLayout.setContentsMargins(10, 10, 10, 10) self.setLayout(vboxLayout) self.mediaPlayer.setVideoOutput(videowidget) # media player signals self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.position_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) def open_file(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Video") print(filename) if filename != '': if os.path.exists("audio.wav"): os.remove("audio.wav") command = "ffmpeg_dir\\bin\\ffmpeg -i " + filename + " -ac 1 -ar 11025 -vn audio.wav" subprocess.call(command, shell=True) self.sampFreq, self.audio = wavfile.read('audio.wav') print(self.audio.shape) print(self.sampFreq) self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.playBtn.setEnabled(True) self.skipForward.setEnabled(True) self.skipBackwards.setEnabled(True) self.mediaPlayer.setPosition(1) def play_video(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def skip_forward(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.setPosition(self.mediaPlayer.position() + 5000) else: self.mediaPlayer.setPosition(self.mediaPlayer.position() + 33) def skip_forward_tiny(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000) def skip_backwards(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.setPosition(self.mediaPlayer.position() - 5000) else: self.mediaPlayer.setPosition(self.mediaPlayer.position() - 33) def skip_backwards_tiny(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000) def mediastate_changed(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def position_changed(self, position): self.slider.setValue(position) print(self.mediaPlayer.duration()) self.label2.setText( str(convert(int(position / 1000))) + "/" + str(convert(int(self.mediaPlayer.duration() / 1000)))) def duration_changed(self, duration): self.slider.setRange(0, duration) def set_position(self, position): self.mediaPlayer.setPosition(position) def speed_popup(self, text): print(text) self.mediaPlayer.setPlaybackRate(float(text)) def sound_thresh(self, text): global audioThreshold audioThreshold = float(text) print(audioThreshold) def handle_errors(self): self.playBtn.setEnabled(False) self.label.setText("Error: " + self.mediaPlayer.errorString())
class Window(QWidget): def __init__(self): super().__init__() self.flag = True self.setWindowTitle("Advanced Programming Player") self.setGeometry(350, 100, 800, 600) self.setWindowIcon(QIcon("player.png")) ############ # SIAVASH ############ # self.palette = self.palette() # self.palette.setColor(QPalette.Window, QColor('lavenderblush'))#(142, 145, 20)) # self.setPalette(self.palette) ############ file = QFile(":/light.qss") file.open(QFile.ReadOnly | QFile.Text) stream = QTextStream(file) self.setStyleSheet(stream.readAll()) self.time = [] self.subject = [] self.init_ui() self.show() def init_ui(self): self.flag = True # Create Media Player Object self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) # Create video widget object videoWidget = QVideoWidget( ) #difference between media player and widget object # Create open button openBtn = QPushButton("Open Video") openBtn.clicked.connect(self.open_file) # Create button for playing self.playBtn = QPushButton() self.playBtn.setEnabled(False) self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum) self.playBtn.clicked.connect(self.play_video) # Create button for stopping the playback self.stopBtn = QPushButton() self.stopBtn.setEnabled(False) self.stopBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stopBtn.clicked.connect(self.stop_video) #Creating button for getting tags self.tagBtn = QPushButton("Import tags") self.tagBtn.setEnabled(True) self.tagBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum) self.tagBtn.clicked.connect(self.getTags) #Create button for changing theme self.tmBtn = QPushButton('Dark') self.tmBtn.setEnabled(True) self.tmBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum) self.tmBtn.clicked.connect(self.set_theme) #Create button for playback speed #New self.pbkBtn = QCheckBox("2X") self.pbkBtn.setChecked(False) self.pbkBtn.toggled.connect(self.set_rate) #Creat button for switching the window #New self.btn_switch = QPushButton("Tags") self.btn_switch.clicked.connect(self.switch_window) # Create time slider self.timeSlider = QSlider(Qt.Horizontal) self.timeSlider.setRange(0, 100) self.timeSlider.setEnabled(False) self.timeSlider.sliderMoved.connect(self.set_position) # Create current and total time labels self.currentTimeLabel = QLabel() self.currentTimeLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.currentTimeLabel.setText("<font color='black'>00:00") self.totalTimeLabel = QLabel() self.totalTimeLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.totalTimeLabel.setText("00:00") # Create volume slider self.volumeSlider = QSlider(Qt.Horizontal) self.volumeSlider.setRange(0, 100) self.volumeSlider.setValue(80) self.volumeSlider.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.volumeSlider.setEnabled(False) self.volumeSlider.sliderMoved.connect(self.set_volume) # Create label self.label = QLabel() self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create hbox layout hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) # Create spacer item self.spacerItem = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) labelImage = QLabel(self) pixmap = QPixmap("volume.png") labelImage.setPixmap(pixmap) # set widgets to the hbox layout hboxLayout.addWidget(openBtn) hboxLayout.addWidget(self.playBtn) hboxLayout.addWidget(self.stopBtn) hboxLayout.addWidget(self.tagBtn) hboxLayout.addWidget(self.tmBtn) hboxLayout.addWidget(self.btn_switch) hboxLayout.addWidget(self.pbkBtn) hboxLayout.addSpacerItem(self.spacerItem) hboxLayout.addWidget(labelImage) hboxLayout.addWidget(self.volumeSlider) # set the time labels to another hbox layout hboxLayout2 = QHBoxLayout() hboxLayout2.setContentsMargins(0, 0, 0, 0) hboxLayout2.addWidget(self.currentTimeLabel) hboxLayout2.addWidget(self.timeSlider) hboxLayout2.addWidget(self.totalTimeLabel) # Create vbox layout vboxLayout = QVBoxLayout() vboxLayout.addWidget(videoWidget) vboxLayout.addLayout(hboxLayout2) vboxLayout.addLayout(hboxLayout) vboxLayout.addWidget(self.label) self.setLayout(vboxLayout) self.mediaPlayer.setVideoOutput(videoWidget) # Media player signals #self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.time_position_changed) self.mediaPlayer.durationChanged.connect(self.time_duration_changed) def open_file(self): # Opening the file using the file dialog and qurl filename, _ = QFileDialog.getOpenFileName(self, "Open Video") if filename != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.playBtn.setEnabled(True) self.stopBtn.setEnabled(True) self.timeSlider.setEnabled(True) self.volumeSlider.setEnabled(True) # When the file dialog is opened the video starts to play automatically self.play_video() def play_video(self): # Changing the state of the playback when the play/pause button is pressed if self.mediaPlayer.state() == QMediaPlayer.PlayingState: # Setting the icon of the play/pause button and pausing the playback self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) self.mediaPlayer.pause() else: # Setting the icon of the play/pause button, # the volume of the player and starting the playback self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.mediaPlayer.setVolume(80) self.mediaPlayer.play() def stop_video(self): # Disabling all the sliders and buttons except the openVideo button self.playBtn.setEnabled(False) self.stopBtn.setEnabled(False) self.timeSlider.setEnabled(False) self.volumeSlider.setEnabled(False) # Stopping the playback self.mediaPlayer.stop() def time_position_changed(self, position): # Setting the value of the time slider and currentTimeLabel self.timeSlider.setValue(position) self.currentTimeLabel.setText(time_format(position)) def time_duration_changed(self, duration): # Setting the range of time slider and the value of totalTimeLabel self.timeSlider.setRange(0, duration) self.totalTimeLabel.setText(time_format(duration)) def set_position(self, position): self.mediaPlayer.setPosition(position) def set_volume(self, volume): self.mediaPlayer.setVolume(volume) def handle_errors(self): self.playBtn.setEnabled(False) self.label.setText(f"Error: {self.mediaPlayer.errorString()}") def getTags(self): # Opens the excel file and stores time and subject filename, _ = QFileDialog.getOpenFileName(self) wb = open_workbook(filename) for s in wb.sheets(): values = [] for row in range(s.nrows): for col in range(s.ncols): values.append(s.cell(row, col).value) self.time = [values[i] for i in range(len(values)) if i % 2 == 0] #storing time in time list self.subject = [values[i] for i in range(len(values)) if i % 2 != 0 ] #storing corresponding subjects in subject list #print(self.time) #just for verification #print(self.subject) #just for verification purpose def set_theme(self): if not self.flag: # self.palette.setColor(QPalette.Window, QColor('lavenderblush')) # self.palette.setColor(QPalette.Button, QColor('lightsalmon')) file = QFile(":/light.qss") file.open(QFile.ReadOnly | QFile.Text) stream = QTextStream(file) self.setStyleSheet(stream.readAll()) self.tmBtn.setText("Dark") else: # self.palette.setColor(QPalette.Window, QColor('gray')) # self.palette.setColor(QPalette.Button, QColor('darkgray')) file = QFile(":/dark.qss") file.open(QFile.ReadOnly | QFile.Text) stream = QTextStream(file) self.setStyleSheet(stream.readAll()) self.tmBtn.setText("Light") # self.setPalette(self.palette) self.flag = not self.flag def set_rate(self): # sometimes it becomes laggy ---#New if self.pbkBtn.isChecked(): self.mediaPlayer.setPlaybackRate(2) if not self.pbkBtn.isChecked(): self.mediaPlayer.setPlaybackRate(1) def switch_window(self): #New/last version edit self.tag_window = NewDialog(self) self.tag_window.show()
class VideoWindow(QMainWindow): def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle("tofu") self.setWindowIcon(QIcon('src/static/img/tofu.png')) self.comm = SignalBus.instance() self.comm.newLabelSignal.connect(self.bindLabelEvent) self.comm.delLabelSignal.connect(self.unbindLabelEvent) self.rate = 1 self.initUI() self.set_default_shortcuts() self.shortcuts = {} def initUI(self): videoWidget = self.create_player() self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.create_menu_bar() wid = QWidget(self) self.setCentralWidget(wid) self.set_layout(videoWidget, wid) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def create_player(self): self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() self.editorWidget = LabelEditorWidget() self.creatorWidget = LabelCreatorWidget() self.create_control() self.playButton.clicked.connect(self.play) self.speedUpButton.clicked.connect(self.speed) self.slowDownButton.clicked.connect(self.slow) self.adv3Button.clicked.connect(partial(self.advance, 3)) self.goBack3Button.clicked.connect(partial(self.back, 3)) self.advanceButton.clicked.connect(partial(self.advance, 10)) self.goBackButton.clicked.connect(partial(self.back, 10)) self.positionSlider.sliderMoved.connect(self.setPosition) return videoWidget def set_default_shortcuts(self): self.playButton.setShortcut(QKeySequence(Qt.Key_Space)) self.speedUpButton.setShortcut(QKeySequence(Qt.Key_Up)) self.slowDownButton.setShortcut(QKeySequence(Qt.Key_Down)) self.advanceButton.setShortcut(QKeySequence(Qt.Key_Right)) self.goBackButton.setShortcut(QKeySequence(Qt.Key_Left)) def create_control(self): self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.speedUpButton = QPushButton() self.speedUpButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.speedUpButton.setEnabled(False) self.slowDownButton = QPushButton() self.slowDownButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.slowDownButton.setEnabled(False) self.adv3Button = QPushButton() self.adv3Button.setIcon(self.style().standardIcon( QStyle.SP_ArrowRight)) self.adv3Button.setEnabled(False) self.advanceButton = QPushButton() self.advanceButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.advanceButton.setEnabled(False) self.goBack3Button = QPushButton() self.goBack3Button.setIcon(self.style().standardIcon( QStyle.SP_ArrowLeft)) self.goBack3Button.setEnabled(False) self.goBackButton = QPushButton() self.goBackButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) self.goBackButton.setEnabled(False) self.timeBox = QLabel(format_time(0), self) self.timeBox.setAlignment(Qt.AlignCenter) self.rateBox = QLabel(str(self.rate) + 'x', self) self.rateBox.setAlignment(Qt.AlignCenter) self.labelSlider = LabelSliderWidget() self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) def create_menu_bar(self): openAction = create_action('open.png', '&Open', 'Ctrl+O', 'Open video', self.openFile, self) csvAction = create_action('save.png', '&Export', 'Ctrl+S', 'Export to csv', self.exportCsv, self) exitAction = create_action('exit.png', '&Exit', 'Ctrl+Q', 'Exit', self.exitCall, self) menuBar = self.menuBar() fileMenu = menuBar.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(csvAction) fileMenu.addAction(exitAction) def set_layout(self, videoWidget, wid): labellingLayout = QVBoxLayout() labellingLayout.addWidget(self.creatorWidget) labellingLayout.addWidget(self.editorWidget) controlLayout = self.make_control_layout() videoAreaLayout = QVBoxLayout() videoAreaLayout.addWidget(videoWidget) videoAreaLayout.addLayout(controlLayout) videoAreaLayout.addWidget(self.errorLabel) layout = QHBoxLayout() layout.addLayout(videoAreaLayout, 4) layout.addLayout(labellingLayout) wid.setLayout(layout) def make_control_layout(self): buttonsLayout = QHBoxLayout() buttonsLayout.setContentsMargins(0, 0, 0, 0) buttonsLayout.addWidget(self.timeBox) buttonsLayout.addWidget(self.slowDownButton) buttonsLayout.addWidget(self.goBackButton) buttonsLayout.addWidget(self.goBack3Button) buttonsLayout.addWidget(self.playButton) buttonsLayout.addWidget(self.adv3Button) buttonsLayout.addWidget(self.advanceButton) buttonsLayout.addWidget(self.speedUpButton) buttonsLayout.addWidget(self.rateBox) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.positionSlider) layout.addWidget(self.labelSlider) layout.addLayout(buttonsLayout) return layout def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open video", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.openedFile = os.path.basename(fileName) self.setWindowTitle("tofu - " + self.openedFile) self.playButton.setEnabled(True) self.speedUpButton.setEnabled(True) self.slowDownButton.setEnabled(True) self.advanceButton.setEnabled(True) self.adv3Button.setEnabled(True) self.goBackButton.setEnabled(True) self.goBack3Button.setEnabled(True) self.rate = 1 def exitCall(self): sys.exit(app.exec_()) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def slow(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.rate -= 0.5 # TODO: Workaround pt 1 # https://forum.qt.io/topic/88490/change-playback-rate-at-... # ...runtime-problem-with-position-qmediaplayer/8 currentPos = self.mediaPlayer.position() # TODO: Workaround pt 1 self.mediaPlayer.setPlaybackRate(self.rate) # TODO: Workaround pt 2 self.mediaPlayer.setPosition(currentPos) # TODO: Workaround pt 2: end self.rateBox.setText(str(self.rate) + 'x') def speed(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.rate += 0.5 # TODO: Workaround pt 1 # https://forum.qt.io/topic/88490/change-playback-rate-at-... # ...runtime-problem-with-position-qmediaplayer/8 currentPos = self.mediaPlayer.position() # TODO: Workaround pt 1 self.mediaPlayer.setPlaybackRate(self.rate) # TODO: Workaround pt 2 self.mediaPlayer.setPosition(currentPos) # TODO: Workaround pt 2: end self.rateBox.setText(str(self.rate) + 'x') def advance(self, t=10): currentPos = self.mediaPlayer.position() nextPos = currentPos + t * 1000 self.setPosition(nextPos) def back(self, t=10): currentPos = self.mediaPlayer.position() nextPos = max(currentPos - t * 1000, 0) self.setPosition(nextPos) def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) self.timeBox.setText(format_time(int(position / 1000))) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.speedUpButton.setEnabled(False) self.slowDownButton.setEnabled(False) self.advanceButton.setEnabled(False) self.goBackButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def bindLabelEvent(self, keySeq, label): bind = QAction(label, self) bind.setShortcut(keySeq) bind.triggered.connect(partial(self.createMark, label)) self.shortcuts[keySeq.toString()] = bind self.addAction(bind) def unbindLabelEvent(self, keySeqStr): self.removeAction(self.shortcuts[keySeqStr]) del self.shortcuts[keySeqStr] def exportCsv(self): suggestedName = os.path.splitext(self.openedFile)[0] + '.csv' fileUrl, _ = QFileDialog.getSaveFileUrl( self, QDir.homePath(), QUrl.fromLocalFile(suggestedName)) fileName = fileUrl.toLocalFile() if fileName != '': with open(fileName, mode='w') as csv_file: writer = csv.writer(csv_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) marks = self.editorWidget.get_marks() writer.writerows(marks) @pyqtSlot() def createMark(self, label): state = self.mediaPlayer.state() if state == QMediaPlayer.PlayingState or state == \ QMediaPlayer.PausedState: self.editorWidget.new_mark(self.mediaPlayer.position() / 1000, label)
class VideoWindow(QMainWindow): def __init__(self, app, parent=None): super(VideoWindow, self).__init__(parent) self.app = app self.setWindowTitle("sofa") self.setWindowIcon(QIcon('src/static/img/tofu.png')) self.rate = 1 self.isNewMark = False self.openedFile = None self.initUI() self.set_default_shortcuts() self.shortcuts = {} self.comm = SignalBus.instance() def initUI(self): videoWidget = self.create_player() self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.create_menu_bar() self.wid = QWidget(self) self.setCentralWidget(self.wid) self.set_layout(videoWidget, self.wid) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def create_player(self): self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() self.clipsWidget = BadClipsWidget() self.create_control() self.playButton.clicked.connect(self.play) self.speedUpButton.clicked.connect(self.speed) self.slowDownButton.clicked.connect(self.slow) self.adv3Button.clicked.connect(partial(self.advance, 3)) self.goBack3Button.clicked.connect(partial(self.back, 3)) self.advanceButton.clicked.connect(partial(self.advance, 10)) self.goBackButton.clicked.connect(partial(self.back, 10)) self.positionSlider.sliderMoved.connect(self.setPosition) self.cutButton.clicked.connect(self.createMark) return videoWidget def set_default_shortcuts(self): self.playButton.setShortcut(QKeySequence(Qt.Key_Space)) self.speedUpButton.setShortcut(QKeySequence(Qt.Key_Up)) self.slowDownButton.setShortcut(QKeySequence(Qt.Key_Down)) self.advanceButton.setShortcut(QKeySequence(Qt.Key_Right)) self.goBackButton.setShortcut(QKeySequence(Qt.Key_Left)) self.cutButton.setShortcut(QKeySequence(Qt.Key_C)) def create_control(self): self.playButton = _create_button( self.style().standardIcon(QStyle.SP_MediaPlay)) self.speedUpButton = _create_button( self.style().standardIcon(QStyle.SP_MediaSeekForward)) self.slowDownButton = _create_button( self.style().standardIcon(QStyle.SP_MediaSeekBackward)) self.adv3Button = _create_button( self.style().standardIcon(QStyle.SP_ArrowRight)) self.advanceButton = _create_button( self.style().standardIcon(QStyle.SP_MediaSkipForward)) self.goBack3Button = _create_button( self.style().standardIcon(QStyle.SP_ArrowLeft)) self.goBackButton = _create_button( self.style().standardIcon(QStyle.SP_MediaSkipBackward)) self.cutButton = _create_button(self.style().standardIcon( QStyle.SP_MessageBoxCritical)) self.timeBox = QLabel(format_time(0), self) self.timeBox.setAlignment(Qt.AlignCenter) self.rateBox = QLabel(str(self.rate) + 'x', self) self.rateBox.setAlignment(Qt.AlignCenter) self.hlightSliderTips = HlightSliderTipsWidget() self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) def create_menu_bar(self): openAction = create_action('open.png', '&Open', 'Ctrl+O', 'Open video', self.openFile, self) saveAction = create_action('save.png', '&Save Clips', 'Ctrl+S', 'Save anonimized clips', self.saveClips, self) exitAction = create_action('exit.png', '&Exit', 'Ctrl+Q', 'Exit', self.exitCall, self) menuBar = self.menuBar() fileMenu = menuBar.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(saveAction) fileMenu.addAction(exitAction) def set_layout(self, videoWidget, wid): labellingLayout = QVBoxLayout() labellingLayout.addWidget(self.clipsWidget) controlLayout = self.make_control_layout() videoAreaLayout = QVBoxLayout() videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) videoAreaLayout.addWidget(videoWidget) videoAreaLayout.addLayout(controlLayout) videoAreaLayout.addWidget(self.errorLabel) layout = QHBoxLayout() layout.addLayout(videoAreaLayout, 4) layout.addLayout(labellingLayout) wid.setLayout(layout) def make_control_layout(self): buttonsLayout = QHBoxLayout() buttonsLayout.setContentsMargins(0, 0, 0, 0) buttonsLayout.addWidget(self.timeBox) buttonsLayout.addWidget(self.slowDownButton) buttonsLayout.addWidget(self.goBackButton) buttonsLayout.addWidget(self.goBack3Button) buttonsLayout.addWidget(self.playButton) buttonsLayout.addWidget(self.adv3Button) buttonsLayout.addWidget(self.advanceButton) buttonsLayout.addWidget(self.speedUpButton) buttonsLayout.addWidget(self.rateBox) cutLayout = QHBoxLayout() cutLayout.setContentsMargins(0, 0, 0, 0) cutLayout.addSpacerItem(QSpacerItem(200, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)) cutLayout.addWidget(self.cutButton) cutLayout.addSpacerItem(QSpacerItem(200, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.positionSlider) layout.addWidget(self.hlightSliderTips) layout.addLayout(buttonsLayout) layout.addLayout(cutLayout) return layout def openFile(self): self.rawFileName, _ = QFileDialog.getOpenFileName(self, "Open video", QDir.homePath()) if self.rawFileName != '': should_process = QMessageBox.question(self.wid, 'Open video', 'Do you want to pre process the video?', QMessageBox.Yes | QMessageBox.No) if should_process == QMessageBox.Yes: self.fileName = TMP_VIDEO_PATH process = ProcVideoDialog(self.rawFileName, self.fileName, self) self.comm.videoProcessed.connect(self.openMedia) else: self.fileName = self.rawFileName self.processMetaData() self.openMedia() def processMetaData(self): ''' Get array indicating "suspicious" frames ''' # open metadata file self.metaDataFile = self.fileName.rsplit(".", 1)[0] + ".csv" # get only the array with "colors" (==0: green; !=0: red) self.colorsArray = get_metadata_colors(self.metaDataFile) self.hlightSliderTips.setColorsArray(self.colorsArray, useYellow=False) @pyqtSlot() def openMedia(self): self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(self.fileName))) self.openedFile = os.path.basename(self.fileName) self.setWindowTitle("sofa - " + self.openedFile) self.playButton.setEnabled(True) self.speedUpButton.setEnabled(True) self.slowDownButton.setEnabled(True) self.advanceButton.setEnabled(True) self.adv3Button.setEnabled(True) self.goBackButton.setEnabled(True) self.goBack3Button.setEnabled(True) self.cutButton.setEnabled(True) self.rate = 1 def exitCall(self): if self.openedFile is not None: os.remove(self.fileName) sys.exit(self.app.exec_()) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def slow(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.rate -= 0.5 # TODO: Workaround pt 1 # https://forum.qt.io/topic/88490/change-playback-rate-at-... # ...runtime-problem-with-position-qmediaplayer/8 currentPos = self.mediaPlayer.position() # TODO: Workaround pt 1 self.mediaPlayer.setPlaybackRate(self.rate) # TODO: Workaround pt 2 self.mediaPlayer.setPosition(currentPos) # TODO: Workaround pt 2: end self.rateBox.setText(str(self.rate)+'x') def speed(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.rate += 0.5 # TODO: Workaround pt 1 # https://forum.qt.io/topic/88490/change-playback-rate-at-... # ...runtime-problem-with-position-qmediaplayer/8 currentPos = self.mediaPlayer.position() # TODO: Workaround pt 1 self.mediaPlayer.setPlaybackRate(self.rate) # TODO: Workaround pt 2 self.mediaPlayer.setPosition(currentPos) # TODO: Workaround pt 2: end self.rateBox.setText(str(self.rate)+'x') def advance(self, t=10): currentPos = self.mediaPlayer.position() nextPos = currentPos + t*1000 self.setPosition(nextPos) def back(self, t=10): currentPos = self.mediaPlayer.position() nextPos = max(currentPos - t*1000, 0) self.setPosition(nextPos) def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) self.hlightSliderTips.setValue(position) self.timeBox.setText(format_time(int(position/1000))) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) self.hlightSliderTips.setRange(duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.speedUpButton.setEnabled(False) self.slowDownButton.setEnabled(False) self.advanceButton.setEnabled(False) self.goBackButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def saveClips(self): prefix = os.path.splitext(os.path.basename(self.rawFileName))[0] + \ '_slice_' dirPath = QFileDialog.getExistingDirectory(self, 'Select Dir') if dirPath != '': try: self.errorLabel.setText('Saving clips... please wait') video = VideoFileClip(self.fileName) marks = self.clipsWidget.get_marks() begin_time = 0.0 for i, m in enumerate(marks): end_time = float(m[0]) out_path = os.path.join(dirPath, prefix+str(i)+".mp4") clip = video.subclip(begin_time, end_time) clip.write_videofile(out_path) begin_time = float(m[1]) end_video = self.mediaPlayer.duration()/1000 if begin_time < end_video and len(marks) > 0: i = len(marks) out_path = os.path.join(dirPath, prefix+str(i)+".mp4") clip = video.subclip(begin_time) clip.write_videofile(out_path) self.errorLabel.setText('Clips saved at ' + dirPath) QMessageBox.information(self.wid, 'Sucess', 'Clips succesfully saved') except: self.errorLabel.setText('Error: Could not save file.') QMessageBox.warning(self.wid, 'Error', 'Could not save file. Check permissions') @pyqtSlot() def createMark(self): state = self.mediaPlayer.state() if state == QMediaPlayer.PlayingState or state == \ QMediaPlayer.PausedState: self.clipsWidget.new_mark(self.mediaPlayer.position()/1000, self.isNewMark) self.isNewMark = not self.isNewMark
class InputManager: __instance = None def __init__(self): if not InputManager.__instance: self.ui_manager = UIManager.get_instance() self.radio_stations_manager = RadioStationsManager() self.player = None self.playlist = None self.probe = None self.load_state() if not self.playlist: self.init_state() self.init_signals() def init_signals(self): self.player.durationChanged.connect(self.duration_changed_slot) self.player.positionChanged.connect(self.position_changed_slot) self.player.currentMediaChanged.connect( self.current_media_changed_slot) self.player.stateChanged.connect(self.state_changed_slot) def set_position(self, new_pos): self.ui_manager.set_position_slider_value(new_pos) self.player.setPosition(new_pos) def get_duration(self): return self.player.duration() def get_position(self): return self.player.position() def duration_changed_slot(self, duration): self.ui_manager.set_position_slider_max_value(duration) def position_changed_slot(self, position): self.ui_manager.set_position_slider_value(position) def get_volume(self): return self.player.volume() def set_volume(self, value): self.ui_manager.set_volume_slider_value(value) self.player.setVolume(value) def current_media_changed_slot(self): self.ui_manager.sync_row(self.get_media_position()) def state_changed_slot(self, new_state): if new_state == QMediaPlayer.StoppedState or new_state == QMediaPlayer.PausedState: self.ui_manager.change_play_btn_state(False) else: self.ui_manager.change_play_btn_state(True) def next_media(self): self.playlist.next() def previous_media(self): self.playlist.previous() @classmethod def get_instance(cls, *args, **kwargs): if not cls.__instance: cls.__instance = InputManager(*args, **kwargs) return cls.__instance def init_state(self): self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.probe = QAudioProbe() self.probe.setSource(self.player) self.probe_connected = False self.timer = QTimer() self.timer.setInterval(100) self.timer.setSingleShot(True) self.recent_files_manager = RecentFilesManager() self.ui_manager.set_output(self.player) self.player.setPlaylist(self.playlist) def load_state(self): file = QFile("file.dat") file.open(QIODevice.ReadOnly) in_stream = QDataStream(file) cur_playlist = QVariant() in_stream >> cur_playlist self.playlist = cur_playlist.value() def get_radio_stations(self, limit=None, category=None): stations = self.radio_stations_manager.get_all_stations( limit, category) return stations def get_radio_categories(self): categories = self.radio_stations_manager.get_all_categories() return categories def save_state(self): file = QFile("file.dat") file.open(QIODevice.WriteOnly) out = QDataStream(file) out << QVariant(self.current_playlist) def add_folder(self, path: str): files = get_dir_files(path) for file in files: self.add_media(path + "/" + file, get_format(file)) def add_file(self, filename: str): format = get_format(filename) if format != FILE_FORMAT.INVALID: return self.add_media(filename, format) raise RuntimeError("Invalid file format") def add_media(self, filename: str, format: FILE_FORMAT): url = QUrl.fromLocalFile( filename) if format != FILE_FORMAT.URL else QUrl(filename) content = QMediaContent(url) self.ui_manager.append_playlist(url.fileName(), format) self.recent_files_manager.write_recent_file(url.path()) self.ui_manager.init_recent_files() self.playlist.addMedia(content) def set_media_position(self, pos): self.playlist.setCurrentIndex(pos) def get_media_position(self): return self.playlist.currentIndex() def get_current_format(self): position = self.get_media_position() if position == -1: return None item = self.ui_manager.get_list_item(self.get_media_position()) return item.data(PlaylistItemDataRole.FORMAT) def play(self): format = self.get_current_format() if format is None: return self.ui_manager.change_play_btn_state(True) if format == FILE_FORMAT.AUDIO: self.probe.audioBufferProbed.connect(self.process_buffer) self.probe_connected = True else: self.probe_connected = False self.ui_manager.show_video() self.player.play() def pause(self): self.player.pause() def stop(self): self.player.stop() def is_muted(self): return self.player.isMuted() def is_paused(self): return self.player.state() in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState) def mute(self, toggle): self.ui_manager.change_mute_state(toggle, self.get_volume()) self.player.setMuted(toggle) def get_playback_rate(self): return self.player.playbackRate() def set_playback_rate(self, value): self.player.setPlaybackRate(value) def process_buffer(self, buffer): if not self.probe_connected: return if not self.timer.isActive(): self.timer.start() else: if self.timer.remainingTime() == 0: data = buffer.data() chunked = chunk(list(data.asarray(buffer.byteCount())), 12) to_visualizer = [int(sum(e) // 12 // 75) for e in chunked] self.show_visualization(to_visualizer) def show_visualization(self, to_visualizer): self.ui_manager.update_equalizer(to_visualizer) def get_audio_devices(self): return QAudioDeviceInfo.availableDevices(QAudio.AudioOutput) def get_recent_files(self): return self.recent_files_manager.get_recent_files() def clear_recent_files(self): return self.recent_files_manager.clear_recent_files() def exit(self): self.ui_manager.exit()
class IntroWindow(QMainWindow, Form): def __init__(self): Form.__init__(self) QMainWindow.__init__(self) self.setWindowIcon(QIcon("logo.png")) p = self.palette() p.setColor(QPalette.Window, Qt.gray) self.setPalette(p) self.setupUi(self) self.a = 1 self.videowidget = QVideoWidget() self.vertical.addWidget(self.videowidget) self.videoplayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoplayer.setVideoOutput(self.videowidget) self.sliderfilm.setRange(0, 0) self.volume.setRange(0, 100) self.videoplayer.setVolume(100) self.volume.setValue(100) self.play.setEnabled(False) self.increaseRate.setEnabled(False) self.decreaseRate.setEnabled(False) # putting Icons on buttons self.increaseRate.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.decreaseRate.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.open.setIcon(self.style().standardIcon(QStyle.SP_DirHomeIcon)) self.skipforward.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.skipback.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.sliderfilm.sliderMoved.connect(self.setpos) self.videoplayer.positionChanged.connect(self.position) self.videoplayer.durationChanged.connect(self.changed) self.videoplayer.volumeChanged.connect(self.setvolpos) self.volume.sliderMoved.connect(self.setvolpos) self.actionOpen.triggered.connect(self.Loadvideo) self.actionSearch_By_Tag.triggered.connect(self.opensecond) self.actionFullscreen.triggered.connect(self.screen) self.skipforward.clicked.connect(self.skipforw) self.skipback.clicked.connect(self.skipbac) self.increaseRate.clicked.connect(self.incRate) self.decreaseRate.clicked.connect(self.decRate) self.play.clicked.connect(self.play_video) self.open.clicked.connect(lambda: self.Loadvideo(self.videoplayer)) self.stop.clicked.connect(self.stopp) self.listView.hide() self.addtolist() self.listviewstatus = 0 self.listbtn.clicked.connect(lambda: self.list()) self.listView.itemClicked.connect(self.listwidgetclicked) self.theme1.triggered.connect(lambda: self.theme01()) self.theme2.triggered.connect(lambda: self.theme02()) self.theme3.triggered.connect(lambda: self.theme03()) self.theme4.triggered.connect(lambda: self.theme04()) # def itemClicked(item): # print("sassss") # self.button = QPushButton("button", self) ####how to hid window flag # self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint) # self.hide() # self.show() def stopp(self): self.stop.setEnabled(False) self.videoplayer.stop() self.videoplayer.setPosition(0) def listwidgetclicked(self, item): t = item.text() pt = datetime.strptime(t, "%H:%M:%S") total_seconds = pt.second + pt.minute * 60 + pt.hour * 3600 if self.a == 0: self.videoplayer.setPosition(total_seconds * 1000) def list(self): if self.listviewstatus % 2 == 1: self.listView.hide() self.listbtn.setText("^") self.listviewstatus += 1 else: self.listbtn.setText("v") self.listviewstatus += 1 self.listView.show() # def resizeEvent(self, cls): # print(self.geometry()) # width = self.frameGeometry().width() # height = self.frameGeometry().height() # self.button.move(width - 200, height - 200) def mouseDoubleClickEvent(self, cls): if not self.isFullScreen(): # self.showFullScreen() self.fulls() else: self.unfull() # self.showNormal() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: if self.isFullScreen(): self.unfull() # self.showNormal() def screen(self): if not self.isFullScreen(): # self.showFullScreen() self.fulls() else: self.unfull() # self.showNormal() # forward media 5s def skipforw(self): self.videoplayer.setPosition(self.videoplayer.position() + 5000) def skipbac(self): self.videoplayer.setPosition(self.videoplayer.position() - 5000) # set increase rate def incRate(self): if self.videoplayer.playbackRate() == 0: x = self.videoplayer.playbackRate() + 1 else: x = self.videoplayer.playbackRate() self.videoplayer.setPlaybackRate(x + 0.25) # set decrease rate def decRate(self): if self.videoplayer.playbackRate() == 0: x = self.videoplayer.playbackRate() + 1 else: x = self.videoplayer.playbackRate() self.videoplayer.setPlaybackRate(x - 0.25) def addtolist(self): data = pd.read_excel("tags.xlsx") firstline = pd.DataFrame(data, index=[0]) x = pd.DataFrame(data, columns=[list(firstline)[0]]) self.listView.addItem(str(list(firstline)[1])) for i in range(x.size): self.listView.addItem(str(data.iat[i, 1])) def opensecond(self): login_page = LoginPage() login_page.setWindowFlags(QtCore.Qt.WindowCloseButtonHint) data = pd.read_excel("tags.xlsx") firstline = pd.DataFrame(data, index=[0]) x = pd.DataFrame(data, columns=[list(firstline)[0]]) login_page.tableWidget.setRowCount(x.size) login_page.tableWidget.insertRow(1) login_page.tableWidget.setItem( 0, 0, QtWidgets.QTableWidgetItem(list(firstline)[0])) login_page.tableWidget.setItem( 0, 1, QtWidgets.QTableWidgetItem(str(list(firstline)[1]))) for i in range(x.size): for j in range(2): login_page.tableWidget.setItem( i + 1, j, QtWidgets.QTableWidgetItem(str(data.iat[i, j]))) # self.listView.addItem(str(data.iat[i, j])) login_page.buttonBox.accepted.connect(lambda: login_page.shows(self)) login_page.tableWidget.setHorizontalHeaderLabels(["Tag", "Time"]) login_page.exec_() def fulls(self): self.decreaseRate.hide() self.increaseRate.hide() self.centralwidget.setContentsMargins(0, 0, 0, 0) self.play.hide() ################################################ # self.stop.hide() ################################################ self.open.hide() ################################################ self.skipforward.hide( ) ################################################ self.skipback.hide() ################################################ # self.horizontalSpacer_2.hide() # self.horizontalSpacer.hide() self.label.hide() ################################################ self.volume.hide() ################################################ self.menubar.hide( ) ################################################################ self.sliderfilm.hide( ) ################################################ self.statusBar.hide() self.showFullScreen() ################################################ self.listbtn.hide() self.listView.hide() def unfull(self): self.centralwidget.setContentsMargins(10, 10, 10, 10) self.decreaseRate.show() self.increaseRate.show() self.play.show() ################################################ # self.stop.show() ################################################ self.open.show() ################################################ self.skipforward.show( ) ################################################ self.skipback.show() ################################################ # self.horizontalSpacer_2.hide() # self.horizontalSpacer.hide() self.label.show() ################################################ self.volume.show() ################################################ self.menubar.show( ) ################################################################ self.sliderfilm.show( ) ################################################ self.statusBar.show() self.showNormal() ################################################ self.listbtn.show() # self.listView.show() ##setting position of film def setpos(self, position): self.videoplayer.setPosition(position) def position(self, position): hour = int((position / 3600000) % 24) if hour < 10: hour = "0" + str(hour) minute = int((position / 60000) % 60) if minute < 10: minute = "0" + str(minute) second = int((position / 1000) % 60) if second < 10: second = "0" + str(second) self.label.setText(f"{hour}:{minute}:{second}") self.sliderfilm.setValue(position) def changed(self, duration): self.sliderfilm.setRange(0, duration) ##setting position of volume def setvolpos(self, position): self.videoplayer.setVolume(position) ##stop button # def stopp(self): # self.stop.setEnabled(False) # self.play.setText("Start") # self.videoplayer.stop() # self.videoplayer.setPosition(0) ##open button or open from menu bar def Loadvideo(self, videoplayer): self.a = 0 filename, _ = QFileDialog.getOpenFileName(self, "Open Video") if filename != "": self.videoplayer.setPosition(0) types = (".mov" in filename) or (".png" in filename) or (".mp4" in filename) if types: if filename != "": self.videoplayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.videoplayer.play() self.play.setEnabled(True) self.play.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.increaseRate.setEnabled(True) self.decreaseRate.setEnabled(True) ##play button def play_video(self): if self.videoplayer.state() == QMediaPlayer.PlayingState: self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.videoplayer.pause() else: self.videoplayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) def theme01(self): self.videowidget.setStyleSheet("background-color: #404040") self.setStyleSheet("background-color: #A0A0A0") def theme02(self): self.videowidget.setStyleSheet("background-color: #330019") self.setStyleSheet("background-color: #990000") def theme03(self): self.videowidget.setStyleSheet("background-color: #35557F") self.setStyleSheet("background-color: #003366") def theme04(self): self.videowidget.setStyleSheet("background-color: #00FF00") self.setStyleSheet("background-color: #4C9900")
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() #Load mainwindow.ui from Qt Designer uic.loadUi('../ui/mainwindow.ui', self) #Load all settings self.initMainWindow() #Show the main window self.show() def initMainWindow(self): """ This function initialize all the buttons and all the setting for displaying and control the video. """ self.setWindowIcon( QtGui.QIcon( "../resources/icons/GUI_Icons/1519132568_movavi-video-editor.png" )) #delete all temp files self.deleteAllTemp() self.setWindowTitle("VideoEditor") """<Objects>""" #Object for controling all edit functions self.edit = Panel() """</Objects>""" """--------------------<Global variables>----------------------------""" #Thread manager variable self.threadmanager = True #Audio file holder self.audioFile = '' #frame time variable self.frameTime = '' #frame file path self.frameFilePath = '' #Total number of curent media opened self.totalIndex = -1 #Dictionary for index and path for the media self.curentFiles = {} #Index that indicates the curent media selected self.curentIndex = self.totalIndex #Curent index of Concatenate ListView self.curentIndexOfConcatenateList = -1 #Dictionary with all video path for concatenate self.concatenateVideos = {} #Total number of videos added to the concatenate list view self.totalNrOfVideosConcat = -1 #Media play speed self.speed = 1 # self.subtitlesFileVG = '' """-------------------</Global variables>----------------------------""" """----------------<Media player settings>---------------------------""" #Create a mediaplayer object to control the video self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setVolume(50) #Create a playlist object for multiple videos self.playlist = QMediaPlaylist() self.mediaPlayer.setPlaylist(self.playlist) self.model = PlaylistModel(self.playlist) self.videoFiles.setModel(self.model) self.playlist.currentIndexChanged.connect( self.playlist_position_changed) selection_model = self.videoFiles.selectionModel() selection_model.selectionChanged.connect( self.playlist_selection_changed) #Create videoWidget object for displaying the video videoWidget = QVideoWidget() #videoWidget set self.videoPreviewLayout = QVBoxLayout() self.videoPreviewLayout.addWidget(videoWidget) self.vpfVideoPreview.setLayout(self.videoPreviewLayout) """----------------</Media player settings>--------------------------""" """-----------------<Buttons&Labels settings>-------------------------""" #Create Open Video button in taskbar self.open = QAction('&Open Video', self) self.open.setStatusTip('Open Video') self.menuFiles.addAction(self.open) self.setAcceptDrops(True) #PlayButton self.playButton.setEnabled(False) #Speed label self.speedLabel.setText("1.0x") #Slider settings timeline self.videoTimeSlider.setRange(0, 0) #Slider settings volume self.volume.setRange(0, 100) self.volume.setValue(50) self.volumeTextDisplay.setText("50%") #Cut lock buttons self.lockButtonStart.setCheckable(True) self.lockButtonFinish.setCheckable(True) #Cut text editor settings self.cutStart.setReadOnly(True) self.cutFinish.setReadOnly(True) self.cutStart.setText("0:00:00") self.cutFinish.setText("0:00:00") #Resolution Image settings self.resolutionIcon.setPixmap( QPixmap("../resources/icons/GUI_Icons/720.png")) """-----------------</Buttons&Labels settings>-------------------------""" """-----------------<Buttons connections>------------------------------""" """ -----------<Player buttons>--------- """ #Play button self.playButton.clicked.connect(self.playVideo) #back 15 seconds Button self.skipbackButton.clicked.connect(self.skipbackFunction) #skip 15 seconds forward Button self.skipforwardButton.clicked.connect(self.skipforwadFunction) #fastorForward button self.fastForward.clicked.connect(self.fastForwardFunction) #rewind button self.rewind.clicked.connect(self.rewindFunction) #Add video button self.addButton.clicked.connect(self.openFile) #Remove video button self.deleteButton.clicked.connect(self.RemoveVideo) #save video self.saveVideo.clicked.connect(self.saveVideoFunction) #Time slider self.videoTimeSlider.sliderMoved.connect(self.setPosition) #Volume slider self.volume.sliderMoved.connect(self.volumeControl) #media player change state self.mediaPlayer.stateChanged.connect(self.mediaStateChange) self.mediaPlayer.positionChanged.connect(self.positionChange) self.mediaPlayer.durationChanged.connect(self.durationChange) """ -----------</Player buttons>--------- """ #Open file self.open.triggered.connect(self.openFile) """ -------------<Edit Buttons>----------------- """ """<Concatenate>""" #Create a model for Concatenate Lisview self.concatenateModel = QtGui.QStandardItemModel() #Set the model to the Concatenate List view self.concatenateList.setModel(self.concatenateModel) #Concatenate list of videos self.concatenateList.clicked[QtCore.QModelIndex].connect( self.setConcatenateIndex) #Add button to concatenate list self.addConcatenate.clicked.connect(self.addVideoToConcatenate) # When you receive the signal, you call QtGui.QStandardItemModel.itemFromIndex() # on the given model index to get a pointer to the item self.removeConcatenate.clicked.connect(self.removeVideoToConcatenate) #Concatenate Button self.concatenateButton.clicked.connect(self.concatenateThreadFunction) """</Concatenate>""" """<Cut>""" #Lock cut filed1 self.lockButtonStart.clicked.connect(self.lockButtonChangeIconStart) #Lock cut filed2 self.lockButtonFinish.clicked.connect(self.lockButtonChangeIconFinish) #Cut button self.cutButton.clicked.connect(self.cutThreadFunction) """</Cut>""" """<Resolution>""" #Resoluiton ComboBox for selecting the desired resolution self.ResolutionsList.currentIndexChanged.connect( self.changeResolutionDisplay) #Change resolution button self.changeResolution.clicked.connect(self.changeResolutionThread) """</Resoluton>""" """<Mirror>""" #Mirror button self.mirroringButton.clicked.connect(self.mirrorThread) """</Mirror>""" """<Audio replace>""" self.openAudioFile.clicked.connect(self.openAudio) self.removeAudioFile.clicked.connect(self.removeAudioFileFunction) self.audioModeSelect.currentIndexChanged.connect( self.changeAudioBackground) self.AddAudio.clicked.connect(self.SoundReplaceThread) """</Audio replace>""" """<GetFrame>""" self.getFrameButton.clicked.connect(self.GetFrameFunction) #self.saveFrameButton.setShortcut("Ctrl+S") self.saveFrameButton.setStatusTip('Save File') self.saveFrameButton.clicked.connect(self.saveFrame) """"</GetFrame>""" """<AddSubtitles>""" self.loadSubtitles.clicked.connect(self.loadSubtitlesFunction) self.cleanButton.clicked.connect(self.removeSubtitlesFunction) self.addSubtitle.clicked.connect(self.addSubtitlesThread) """</AddSubtitles>""" """<VideoGrep>""" self.loadSubtitlesVG.clicked.connect(self.loadSubtitlesVideoGrep) self.cleanButtonVideoGrep.clicked.connect( self.removeSubtitlesVideoGrep) self.videoGrep.clicked.connect(self.videoGrepThread) """</VideoGrep>""" """ -------------</Edit Buttons>----------------- """ """ -------------<Shortcut Buttons>--------------- """ self.soundShortcut.clicked.connect(self.soundShortcutKey) self.getFrameShortcut.clicked.connect(self.getFrameShortcutKey) self.cutShortcut.clicked.connect(self.cutShortcutKey) self.concatShortcut.clicked.connect(self.concatShortcutKey) self.mirrorShortcut.clicked.connect(self.mirrorShortcutKey) """ -------------</Shortcut Buttons>--------------- """ """-----------------</Buttons connections>----------------------------""" """-------------------<Threads for editing>--------------------------""" self.pool = QThreadPool() """-------------------</Threads for editing>--------------------------""" """<Experimental>""" qtimeline = QTimeLine(360, 1) self.test = QVBoxLayout() qtimeline2 = QTimeLine(360, 1) self.test.addWidget(qtimeline) self.test.addWidget(qtimeline2) self.sfTimeLineFrame.setLayout(self.test) #self.editMenu.setCurrentIndex(5) """</Experimental>""" #Set output to the video self.mediaPlayer.setVideoOutput(videoWidget) """ ------------------<Concatenate functions>---------------------------""" def setConcatenateIndex(self, index): """ Set the curent index of the selected item from concatenate list view (self.concatenateList) """ #Get the item from the model of index "index" item = self.concatenateModel.itemFromIndex(index) #Get the "item " row index self.curentIndexOfConcatenateList = item.index().row() print(self.concatenateVideos) def addVideoToConcatenate(self): """ Add from 'concatenateVideoList' a video to 'concatenateList' """ try: #Add the current video selected from the ComboBox to the concatenate list view item = QtGui.QStandardItem(self.curentFiles[ self.concatenateVideoList.currentIndex()].split('/')[-1]) self.concatenateModel.appendRow(item) self.totalNrOfVideosConcat += 1 self.concatenateVideos[ self.totalNrOfVideosConcat] = self.curentFiles[ self.concatenateVideoList.currentIndex()] except: print("No video") QMessageBox.about(self, "No video", "Please add a video! ") print(self.concatenateVideoList.currentIndex()) def removeVideoToConcatenate(self): """ Remove video from concatenation list. """ try: self.concatenateModel.removeRow(self.curentIndexOfConcatenateList) del self.concatenateVideos[self.curentIndexOfConcatenateList] self.totalNrOfVideosConcat -= 1 self.SortFilesIndexConcat() except: QMessageBox.about(self, "No video", "No video to remove or not selected! ") print("Error when removing video from list") def concatenate(self): """ This function is used for concatenate multiple videos from the list. """ if (self.curentIndex == -1 and self.totalIndex != -1): self.curentIndex = 0 try: videosToConcatenate = [] #I'm adding the main video videosToConcatenate.append(self.curentFiles[self.curentIndex]) #Add the path to all videos to be concatenated for key in self.concatenateVideos: videosToConcatenate.append(self.concatenateVideos[key]) #Save the current index befor concatenation because #during the concatenation the user could change the curent video #so it would affect curentFiles indexOfRootVideo = self.curentIndex print(videosToConcatenate) #Call concatenate function and save the url of the modified video self.curentFiles[indexOfRootVideo] = self.edit.concat( videosToConcatenate) #Update the media with the edited video self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile("../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile(self.curentFiles[indexOfRootVideo]))) #Clear concatenate list view self.concatenateModel.removeRows(0, self.concatenateModel.rowCount()) #Clear the dict that holds all the data for concatenation self.concatenateVideos.clear() #Reste the number of videos to be concatenated self.totalNrOfVideosConcat = -1 except: print( "A problem occured during concatenation process.Check 'concatenate' function" ) def SortFilesIndexConcat(self): """ This function sort the curentFiles dictionary. When an element is deleted from curentFiles the function sort the index of the curentFiles ascending. """ newIndex = 0 newCurentFiles = {} #loop through the curentFiles and update the index for key in self.concatenateVideos: newCurentFiles[newIndex] = self.concatenateVideos[key] newIndex += 1 #curentFiles files is updated to the new dictionary of files self.concatenateVideos = newCurentFiles.copy() """-------------------</Concatenate functions>--------------------------""" """-----------------------<Cut functions>--------------------------------""" def lockButtonChangeIconStart(self): """ Function for changing the icon when the button is pressed. """ if (self.lockButtonStart.isChecked() == True): self.lockButtonStart.setIcon( QIcon("../resources/icons/GUI_Icons/icons8-lock-80.png")) else: self.lockButtonStart.setIcon( QIcon("../resources/icons/GUI_Icons/icons8-padlock-80.png")) def lockButtonChangeIconFinish(self): """ Function for changing the icon when the button is pressed. """ if (self.lockButtonFinish.isChecked() == True): self.lockButtonFinish.setIcon( QIcon("../resources/icons/GUI_Icons/icons8-lock-80.png")) else: self.lockButtonFinish.setIcon( QIcon("../resources/icons/GUI_Icons/icons8-padlock-80.png")) def restCutButtons(self): """ This function is used to reset all the value for cut section. """ self.cutStart.setText("0:00:00") self.cutFinish.setText("0:00:00") if (self.lockButtonStart.isChecked() == True): self.lockButtonStart.toggle() if (self.lockButtonFinish.isChecked() == True): self.lockButtonFinish.toggle() self.lockButtonChangeIconStart() self.lockButtonChangeIconFinish() def cutFunction(self): """ Function used for cut a video from 'start' to 'finish' and replace in the 'curentFiles'(dictionary that holds all opend video) the curent video path with the path provided by the 'edit.cut' """ try: #if both buttons are pressed the the function can be called if (self.lockButtonStart.isChecked() == True and self.lockButtonFinish.isChecked() == True): try: #save the current index before cut because user can change the 'curentIndex' during execution indexOfRootVideo = self.curentIndex #call the cut function and the result path is saved in currentFiles self.curentFiles[indexOfRootVideo] = self.edit.cut( [self.curentFiles[indexOfRootVideo]], [ self.cutStart.toPlainText(), self.cutFinish.toPlainText() ]) #Set the new video self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( self.curentFiles[indexOfRootVideo]))) #Reset all values for cut function except: print("Problem in at self.edit.cut or mediaPlayer") except: print("Problem in cutFunction function") """-----------------------</Cut functions>-------------------------------""" """-----------------------<Mirror functions>-----------------------------""" def mirrorVideo(self): if (self.curentIndex == -1 and self.totalIndex != -1): self.curentIndex = 0 try: indexOfRootVideo = self.curentIndex result = '' result = self.edit.video_mirroring( [self.curentFiles[indexOfRootVideo]]) if (result != ''): self.curentFiles[indexOfRootVideo] = result self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( self.curentFiles[indexOfRootVideo]))) except: print("Problem in change mirror function") """-----------------------</Mirror functions>-----------------------------""" """-----------------------<Resoluton functions>-----------------------------""" def changeResolutionF(self): """ Function for changing the video resolution. """ if (self.curentIndex == -1 and self.totalIndex != -1): self.curentIndex = 0 currentResolution = self.ResolutionsList.currentText( )[0:len(self.ResolutionsList.currentText()) - 1] try: indexOfRootVideo = self.curentIndex self.curentFiles[indexOfRootVideo] = self.edit.video_resize( [self.curentFiles[indexOfRootVideo]], currentResolution) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile("../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile(self.curentFiles[indexOfRootVideo]))) except: print("Problem in change resolution") def changeResolutionDisplay(self): """ Usef for changing image in resolution section when the user select a resolution. """ resolutionsIconList = [ "../resources/icons/GUI_Icons/720.png", "../resources/icons/GUI_Icons/540.png", "../resources/icons/GUI_Icons/360.png", "../resources/icons/GUI_Icons/240.png", "../resources/icons/GUI_Icons/144.png" ] if (self.ResolutionsList.currentIndex() == 0): self.resolutionIcon.setPixmap(QPixmap(resolutionsIconList[0])) elif (self.ResolutionsList.currentIndex() == 1): self.resolutionIcon.setPixmap(QPixmap(resolutionsIconList[1])) elif (self.ResolutionsList.currentIndex() == 2): self.resolutionIcon.setPixmap(QPixmap(resolutionsIconList[2])) elif (self.ResolutionsList.currentIndex() == 3): self.resolutionIcon.setPixmap(QPixmap(resolutionsIconList[3])) elif (self.ResolutionsList.currentIndex() == 4): self.resolutionIcon.setPixmap(QPixmap(resolutionsIconList[4])) """-----------------------</Resoluton functions>--------------------------""" """-----------------------<Sound Repalce functions>--------------------------""" def openAudio(self): try: fileName = QFileDialog.getOpenFileName(self, "Open Audio") mimetypes.init() mimestart = mimetypes.guess_type(fileName[0])[0] if mimestart != None: mimestart = mimestart.split('/')[0] if mimestart == 'audio': print("Audio file detected") self.audioFile = fileName[0] self.audioFileCheck.setIcon( QIcon("../resources/icons/GUI_Icons/check.png")) else: QMessageBox.about( self, "Audio", "This is not an audio file.Please load an audio file.." ) print("Non audio file detected") else: QMessageBox.about(self, "Audio", "This file format is not accepted.") print("Not accepted file") except: QMessageBox.about(self, "Audio", "Changing sound track failed.") print("Problem in open audio function") def removeAudioFileFunction(self): self.audioFile = '' self.audioFileCheck.setIcon( QIcon("../resources/icons/GUI_Icons/ezgif-7-e04c11fb7018.png")) def changeAudioBackground(self): if (self.audioModeSelect.currentIndex() == 0): self.aduioModeImage.setPixmap( QPixmap("../resources/img/soundAdd.png")) elif (self.audioModeSelect.currentIndex() == 1): self.aduioModeImage.setPixmap( QPixmap("../resources/img/soundReplace.png")) def SoundReplaceFunction(self): if (self.curentIndex == -1 and self.totalIndex != -1): self.curentIndex = 0 audioMode = self.audioModeSelect.currentText() print(audioMode) try: if (self.audioFile != ''): if (self.totalIndex != -1): indexOfRootVideo = self.curentIndex self.curentFiles[ indexOfRootVideo] = self.edit.soundReplace( [self.curentFiles[indexOfRootVideo]], self.audioFile, audioMode) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( self.curentFiles[indexOfRootVideo]))) else: print("No video uploaded") else: print("No aduio file uploaded") except: print("Problem in SoundReplaceFunction") """-----------------------</Sound Repalce functions>-------------------------""" """-----------------------<GetFrame functions>-------------------------""" def GetFrameFunction(self): if (self.curentIndex == -1 and self.totalIndex != -1): self.curentIndex = 0 try: if (self.totalIndex != -1 and self.frameTime != ''): indexOfRootVideo = self.curentIndex print(self.frameTime) self.frameFilePath = '' self.frameFilePath = self.edit.getFrame( [self.curentFiles[indexOfRootVideo]], self.frameTime) self.extractedFrame.setPixmap(QPixmap(self.frameFilePath)) else: print("No video uploaded or frameTime is empty") except: print("Problem in GetFrameFunction") def saveFrame(self): try: fileName = QFileDialog.getSaveFileName(self, 'Save File', "img.jpg", '*.jpg') img = cv2.imread(self.frameFilePath) cv2.imwrite(fileName[0], img) except: QMessageBox.about(self, "Save image", "Problem during saving image.") print("Problem during saving image") """-----------------------</GetFrame functions>-------------------------""" """-----------------------<Add Subtitles functions>-----------------------""" def loadSubtitlesFunction(self): try: fileName = QFileDialog.getOpenFileName(self, "Open Subtitles") if (fileName[0].split('.')[-1] == "srt"): self.subtitlesFile = fileName[0] self.subtitlesCheck.setIcon( QIcon("../resources/icons/GUI_Icons/check.png")) else: QMessageBox.about( self, "Subtitles", "Couldn't load subtitles.Please use file with .srt extension." ) except: print("Problem in load Subtitles function") def removeSubtitlesFunction(self): self.subtitlesFile = '' self.subtitlesCheck.setIcon( QIcon("../resources/icons/GUI_Icons/ezgif-7-e04c11fb7018.png")) def addSubtitlesFunction(self): if (self.curentIndex == -1 and self.totalIndex != -1): self.curentIndex = 0 try: if (self.subtitlesFile != ''): if (self.totalIndex != -1): indexOfRootVideo = self.curentIndex self.curentFiles[ indexOfRootVideo] = self.edit.addSubtitles( [self.curentFiles[indexOfRootVideo]], self.subtitlesFile) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( self.curentFiles[indexOfRootVideo]))) else: print("No video uploaded") else: print("No subtitles file uploaded") except: print("Problem in addSubtitlesFunction") """-----------------------</Add Subtitles functions>----------------------""" """-----------------------</VideoGrep functions>--------------------------""" def loadSubtitlesVideoGrep(self): try: fileName = QFileDialog.getOpenFileName(self, "Open Subtitles") if (fileName[0].split('.')[-1] == "srt"): self.subtitlesFileVG = fileName[0] self.subtitlesCheckVideoGrep.setIcon( QIcon("../resources/icons/GUI_Icons/check.png")) else: QMessageBox.about( self, "Subtitles", "Couldn't load subtitles.Please use file with .srt extension." ) except: print("Problem in load Subtitles function") def removeSubtitlesVideoGrep(self): self.subtitlesFileVG = '' self.subtitlesCheckVideoGrep.setIcon( QIcon("../resources/icons/GUI_Icons/ezgif-7-e04c11fb7018.png")) def videoGrepFunction(self): try: if (self.subtitlesFileVG != ''): if (self.totalIndex != -1): indexOfRootVideo = self.curentIndex vgMode = self.VGMODE.currentText() if (vgMode == "Clasic"): words = self.vglistSpeciale.toPlainText().split(',') else: words = [ self.firstWord.toPlainText(), self.secondWord.toPlainText() ] self.curentFiles[ indexOfRootVideo] = self.edit.find_sequence( [self.curentFiles[indexOfRootVideo]], words, self.subtitlesFileVG, vgMode) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "../resources/videos/blackvideo.mp4"))) self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( self.curentFiles[indexOfRootVideo]))) else: print("No video uploaded") else: print("No subtitles file uploaded") except: print("Problem in video Grep Function") """-----------------------</VideoGrep functions>--------------------------""" """--------------------------<File functions>----------------------------""" def openFile(self): """ Function for opening a video file from taskbar. """ fileName = QFileDialog.getOpenFileName(self, "OpenVideo") #Checks if fileName is a valid file if fileName[0] != '': #Set to mediaPlayer object the file(video) self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName[0]))) #Update total number of curent media opened self.totalIndex = self.totalIndex + 1 self.curentIndex = self.totalIndex #Update the curentFiles dict which holds the path for the opened videos self.curentFiles[self.totalIndex] = fileName[0] if (self.totalIndex == 0): self.curentIndex = 0 #Enable the play button after the video was set self.playButton.setEnabled(True) #Add media to the playlist self.playlist.addMedia( QMediaContent(QUrl.fromLocalFile(fileName[0]))) #Add item to the list for avalabile videos for concatenate self.concatenateVideoList.addItem(fileName[0].split('/')[-1]) #A new media was added so we sent a signal to updated List view self.model.layoutChanged.emit() """------------------------</File functions>----------------------------""" """------------------<Media player functions>---------------------------""" def playVideo(self): """" Function for controling the video Play/Pause """ #Checks the state of the video.If the video is playing it will be paused. if self.mediaPlayer.state() == QMediaPlayer.PlayingState: #Pause the video self.mediaPlayer.pause() else: #If the video is paused it will be playing self.mediaPlayer.play() def mediaStateChange(self, ): """ This function is changing the icon of the playButton. If the video is going from playing to "pause",the icon will change to pause icon.Otherwise the playingButton will change to "play" icon """ if self.mediaPlayer.state() == QMediaPlayer.PlayingState: #Change playButton icon into "Pause icon" self.playButton.setIcon( QIcon("../resources/icons/GUI_Icons/002-pause.png")) else: #Change playButton icon into "Play icon" self.playButton.setIcon( QIcon("../resources/icons/GUI_Icons/play.png")) def convert(self, seconds): """ Function for converting duration of the video(seconds) into Hour/minute/seconds and returning that format. """ seconds = seconds % (24 * 3600) hour = seconds // 3600 seconds %= 3600 minutes = seconds // 60 seconds %= 60 return "%d:%02d:%02d" % (hour, minutes, seconds) def positionChange(self, position): """ This function is activated when the video is changing the time.When that happens is updating the Time slider the new position and the time label. """ self.videoTimeSlider.setValue(position) #Convert position into seconds duration = position / 1000 self.frameTime = int(duration) self.videoTimeDisplay.setText(self.convert(duration)) if (self.lockButtonStart.isChecked() == False): self.cutStart.setText(self.convert(duration)) if (self.lockButtonFinish.isChecked() == False): self.cutFinish.setText(self.convert(duration)) def durationChange(self, duration): """ This function update the range of the time splider when the video position is changing. """ self.videoTimeSlider.setRange(0, duration) def setPosition(self, position): """ Sets the video time based on time slider. When the user is changing the time slider to a specific time,the video position is updated. """ self.mediaPlayer.setPosition(position) def skipforwadFunction(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 15000) def skipbackFunction(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 15000) def rewindFunction(self): if (self.speed - 0.1 >= 0.1): self.speed -= 0.1 self.mediaPlayer.setPlaybackRate(self.speed) self.speedLabel.setText(str(round(self.speed, 2)) + "x") def fastForwardFunction(self): if (self.speed + 0.1 <= 2.1): self.speed += 0.1 self.mediaPlayer.setPlaybackRate(self.speed) self.speedLabel.setText(str(round(self.speed, 2)) + "x") def volumeControl(self, volume): """ This function is used for changing the volume of the video and update the volume label.Also,is used to change the color of the slider based on the volume.If is < 50 is green, <50 && < 75 yellow and red for 74 > """ self.volume.setValue(volume) self.mediaPlayer.setVolume(volume) self.volumeTextDisplay.setText(str(volume) + "%") if (volume <= 50): #green self.volume.setStyleSheet(styleSheet.volumeStageOne) elif (volume > 50 and volume <= 75): #yellow self.volume.setStyleSheet(styleSheet.volumeStageTwo) else: #red self.volume.setStyleSheet(styleSheet.volumeStageThree) #If the volume is zero the icon of the volume is changed if (volume == 0): self.volumeIcon.setIcon( QIcon("../resources/icons/GUI_Icons/mute.png")) else: self.volumeIcon.setIcon( QIcon("../resources/icons/GUI_Icons/speaker.png")) def playlist_selection_changed(self, ix): # We receive a QItemSelection from selectionChanged. i = ix.indexes()[0].row() self.playlist.setCurrentIndex(i) self.curentIndex = i self.speed = 1 self.mediaPlayer.setPlaybackRate(self.speed) self.speedLabel.setText(str(self.speed) + "x") try: self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile(self.curentFiles[self.curentIndex]))) #Reset cut text and icon self.restCutButtons() except: print( "Error in playlist_selection_changed function.Media player couldn't be updated" ) def playlist_position_changed(self, i): if i > -1: ix = self.model.index(i) print("playlist_position_changed") self.videoFiles.setCurrentIndex(ix) def RemoveVideo(self): """ This function is connected to the remove button on Project files. It removes the file from List view and curentFiles dictionary.It also changethe mediaPlayer output based on what media was left.If the is media left the video output will be the firs mediaFile from the list.If the List view have no media left,the video output will be an video of 1 seconds with black background to clear the screen. """ if (self.totalIndex != -1): if (self.curentIndex != -1): try: #Delete media from index "curentIndex" self.playlist.removeMedia(self.curentIndex) #Delete video from concatenate ComboBox self.concatenateVideoList.removeItem(self.curentIndex) try: #Delete the file name from index "curentIndex" from curentFiles del self.curentFiles[self.curentIndex] #Decrement the total number of videos opened self.totalIndex = self.totalIndex - 1 #Update index of every video from curentFiles self.SortFilesIndex() if (self.totalIndex == -1): try: self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "../resources/videos/blackvideo.mp4" ))) #Block the play button self.playButton.setEnabled(False) #Reset the time slider self.videoTimeSlider.setValue(0) #Reset the time slider self.videoTimeSlider.setRange(0, 0) except: print("The black video couldn't be loaded") else: try: self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( self.curentFiles[0]))) except: print("The mediaPlayer couldn't be updated") except: print("The value from index " + str(self.curentIndex) + " could not be deleted form curentFiles") except: print("Media cannot be deleted from playlist") else: #Block the play button self.playButton.setEnabled(False) #Reset the time slider self.videoTimeSlider.setValue(0) #Reset the time slider self.videoTimeSlider.setRange(0, 0) def saveVideoFunction(self): try: import shutil extension = self.curentFiles[self.curentIndex].split('.')[-1] extension = "*." + extension fileName = QFileDialog.getSaveFileName(self, 'Save video', "video_name", extension) shutil.move(self.curentFiles[self.curentIndex], fileName[0]) print("Save video Done") except: print("Error during the video saving") def SortFilesIndex(self): """ This function sort the curentFiles dictionary. When an element is deleted from curentFiles the function sort the index of the curentFiles ascending. """ newIndex = 0 newCurentFiles = {} #loop through the curentFiles and update the index for key in self.curentFiles: newCurentFiles[newIndex] = self.curentFiles[key] newIndex += 1 #curentFiles files is updated to the new dictionary of files self.curentFiles = newCurentFiles.copy() def soundShortcutKey(self): self.editMenu.setCurrentIndex(4) def getFrameShortcutKey(self): self.editMenu.setCurrentIndex(5) def cutShortcutKey(self): self.editMenu.setCurrentIndex(1) def concatShortcutKey(self): self.editMenu.setCurrentIndex(0) def mirrorShortcutKey(self): self.editMenu.setCurrentIndex(3) """------------------</Media player functions>-----------------------""" """----------------------<Thread functions>--------------------------""" """---<Concatenate>---""" def concatenateThreadFunction(self): #If is true that means that no thread is running and can start a thread if (self.threadmanager == True): try: #If is false that means that a thread is already executing self.threadmanager = False worker = Worker(self.concatenate) #When the thread is done threadmanager will be True worker.signals.finished.connect(self.ReleaseThread) self.pool.start(worker) except: print("Problem with concatenate thread") else: print("A thread is already running") """---</Concatenate>---""" """---<Cut>---""" def cutThreadFunction(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.cutFunction) worker.signals.finished.connect(self.restCutButtons) worker.signals.finished.connect(self.ReleaseThread) self.pool.start(worker) except: print("Problem with cut thread") else: print("A thread is already running") """---</Cut>---""" """---<Resolution>---""" def changeResolutionThread(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.changeResolutionF) worker.signals.finished.connect(self.ReleaseThread) self.pool.start(worker) except: print("Problem with resolution thread") else: print("A thread is already running") """---</Resolution>---""" """---<Mirror>---""" def mirrorThread(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.mirrorVideo) worker.signals.finished.connect(self.ReleaseThread) self.pool.start(worker) except: print("Problem with mirror thread") else: print("A thread is already running") """---</Mirror>---""" """---<SoundReplace>---""" def SoundReplaceThread(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.SoundReplaceFunction) worker.signals.finished.connect(self.ReleaseThread) worker.signals.finished.connect(self.removeAudioFileFunction) self.pool.start(worker) except: print("Problem with SoundReplace thread") else: print("A thread is already running") """---</SoundReplace>---""" def ReleaseThread(self): self.threadmanager = True print(self.curentFiles) """---<GetFrame>---""" def GetFrameThread(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.GetFrameFunction) worker.signals.finished.connect(self.ReleaseThread) self.pool.start(worker) except: print("Problem with getFrame thread") else: print("A thread is already running") """---</GetFrame>---""" """---<AddSubtitles>---""" def addSubtitlesThread(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.addSubtitlesFunction) worker.signals.finished.connect(self.ReleaseThread) worker.signals.finished.connect(self.removeSubtitlesFunction) self.pool.start(worker) except: print("Problem with add subtitles thread") else: print("A thread is already running") """---</AddSubtitles>--""" """---</VideoGrep>--""" def videoGrepThread(self): if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.videoGrepFunction) worker.signals.finished.connect(self.ReleaseThread) worker.signals.finished.connect(self.removeSubtitlesVideoGrep) self.pool.start(worker) except: print("Problem with VideoGrep thread") else: print("A thread is already running") """---</VideoGrep>--""" """---------------------</Thread functions>--------------------------""" def deleteAllTemp(self): import os, shutil folder = ProjectFolders.tmpDir for filename in os.listdir(folder): file_path = os.path.join(folder, filename) try: if os.path.isfile(file_path) or os.path.islink(file_path): os.unlink(file_path) elif os.path.isdir(file_path): shutil.rmtree(file_path) except Exception as e: print('Failed to delete %s. Reason: %s' % (file_path, e)) def closeEvent(self, event): """ Popup a dialog when the user is trying to close the main app. """ reply = QMessageBox.question( self, 'Window Close', 'Are you sure you want to close the window?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: if (self.threadmanager == True): try: self.threadmanager = False worker = Worker(self.deleteAllTemp) worker.signals.finished.connect(self.ReleaseThread) self.pool.start(worker) except: print("Problem with getFrame thread") else: print("A thread is already running") event.accept() print('Window closed') else: event.ignore()
class MainWindow(qtw.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.show() self.PLOT_DIR = 'Plots' self.PDF_DIR = 'PDFs' self.amplitude = [[], []] self.graphChannels = [self.ui.graph_before,self.ui.graph_after] self.spectrogramChannels = [self.ui.spectrogram_before, self.ui.spectrogram_after] self.ui.pushButton.clicked.connect(lambda: self.generatePDF()) self.ui.actionSave.triggered.connect(lambda: self.generatePDF()) self.audio_player_before = QMediaPlayer() self.audio_player_after = QMediaPlayer() self.plot = {'before': self.ui.graph_before, 'after': self.ui.graph_after} self.spectrogram = {'before': self.ui.spectrogram_before, 'after': self.ui.spectrogram_after} self.bands_powers = [0.0, 0.25, 0.50, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0] self.bands = [None] * 10 self.band_slider = { 0: self.ui.band_1, 1: self.ui.band_2, 2: self.ui.band_3, 3: self.ui.band_4, 4: self.ui.band_5, 5: self.ui.band_6, 6: self.ui.band_7, 7: self.ui.band_8, 8: self.ui.band_9, 9: self.ui.band_10, } self.min_slider_ = [0, 2205, 4410, 6615, 8820, 11025, 13230, 15435, 17640, 19845, 22050] self.max_silder_ = [0, 2205, 4410, 6615, 8820, 11025, 13230, 15435, 17640, 19845, 22050] self.current_min = 0 self.current_max = 22050 self.ui.max_freq_content.setDisabled(True) self.ui.max_freq_content.setStyleSheet('selection-background-color: grey') self.ui.min_freq_content.setDisabled(True) self.ui.min_freq_content.setStyleSheet('selection-background-color: grey') self.ui.max_freq_content.valueChanged.connect(lambda: self.range_max()) self.ui.min_freq_content.valueChanged.connect(lambda: self.range_min()) self.spectrogram_time_min, self.spectrogram_time_max = 0, 0 for slider in self.band_slider.values(): slider.setDisabled(True) slider.setStyleSheet('selection-background-color: grey'); self.available_palettes = ['twilight', 'Blues', 'Greys', 'ocean', 'nipy_spectral'] self.current_color_palette = self.available_palettes[0] self.ui.band_1.valueChanged.connect(lambda: self.slider_gain_updated(0)) self.ui.band_2.valueChanged.connect(lambda: self.slider_gain_updated(1)) self.ui.band_3.valueChanged.connect(lambda: self.slider_gain_updated(2)) self.ui.band_4.valueChanged.connect(lambda: self.slider_gain_updated(3)) self.ui.band_5.valueChanged.connect(lambda: self.slider_gain_updated(4)) self.ui.band_6.valueChanged.connect(lambda: self.slider_gain_updated(5)) self.ui.band_7.valueChanged.connect(lambda: self.slider_gain_updated(6)) self.ui.band_8.valueChanged.connect(lambda: self.slider_gain_updated(7)) self.ui.band_9.valueChanged.connect(lambda: self.slider_gain_updated(8)) self.ui.band_10.valueChanged.connect(lambda: self.slider_gain_updated(9)) self.filtered_bands = [] self.modified_signal = np.array([]) self.current_slider_gain = [1.0] * 10 self.band_label = { 0: self.ui.band_1_label, 1: self.ui.band_2_label, 2: self.ui.band_3_label, 3: self.ui.band_4_label, 4: self.ui.band_5_label, 5: self.ui.band_6_label, 6: self.ui.band_7_label, 7: self.ui.band_8_label, 8: self.ui.band_9_label, 9: self.ui.band_10_label, } self.controls = { 'before': { 'play':self.ui.play_btn_before, 'pause': self.ui.pause_btn_before, 'stop': self.ui.stop_btn_before, 'jump_forward': self.ui.jump_forward_btn_before, 'jump_backward': self.ui.jump_back_btn_before, 'current_time': self.ui.current_time_before, 'total_time': self.ui.total_time_before, 'time_slider': self.ui.time_seeker_before }, 'after':{ 'play':self.ui.play_btn_after, 'pause': self.ui.pause_btn_after, 'stop': self.ui.stop_btn_after, 'jump_forward': self.ui.jump_forward_btn_after, 'jump_backward': self.ui.jump_back_btn_after, 'current_time': self.ui.current_time_after, 'total_time': self.ui.total_time_after, 'time_slider': self.ui.time_seeker_after } } self.plot_widget = { 'before': self.ui.graph_before, 'after': self.ui.graph_after } self.spectrogram_widget = { 'before': self.ui.spectrogram_before, 'after': self.ui.spectrogram_after } self.data_line = { 'before': None, 'after': None } self.ui.actionExit.triggered.connect(self.close) self.ui.actionNew.triggered.connect(self.new_instance) self.ui.actionOpen.triggered.connect(self.open_audio_file) self.ui.zoom_in_btn_after.clicked.connect(self.zoomin) self.ui.zoom_in_btn_before.clicked.connect(self.zoomin) self.ui.zoom_out_btn_after.clicked.connect(self.zoomout) self.ui.zoom_out_btn_before.clicked.connect(self.zoomout) self.ui.jump_back_btn_before.clicked.connect(self.back) self.ui.jump_back_btn_after.clicked.connect(self.back) self.ui.jump_forward_btn_before.clicked.connect(self.forward) self.ui.jump_forward_btn_after.clicked.connect(self.forward) self.ui.play_btn_before.clicked.connect(self.audio_player_before.play) self.ui.pause_btn_before.clicked.connect(self.audio_player_before.pause) self.ui.stop_btn_before.clicked.connect(self.audio_player_before.stop) self.ui.play_btn_after.clicked.connect(self.audio_player_after.play) self.ui.pause_btn_after.clicked.connect(self.audio_player_after.pause) self.ui.stop_btn_after.clicked.connect(self.audio_player_after.stop) self.ui.palettes_box.currentTextChanged.connect(self.change_palette) self.ui.playback_speed_before.currentIndexChanged.connect(lambda: self.audio_player_before.setPlaybackRate(float(self.ui.playback_speed_before.currentText()[1:]))) self.audio_player_before.durationChanged.connect(lambda duration: self.update_duration(duration)) self.ui.playback_speed_after.currentIndexChanged.connect(lambda: self.audio_player_after.setPlaybackRate(float(self.ui.playback_speed_after.currentText()[1:]))) self.audio_player_after.durationChanged.connect(lambda duration: self.update_duration_after(duration)) def range_max(self): self.current_max = self.max_silder_[int(self.ui.max_freq_content.value())] self.ui.max_freq_content_lab.setText(str(self.current_max)) self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def range_min(self): self.current_min = self.min_slider_[int(self.ui.min_freq_content.value())] self.ui.min_freq_content_lab.setText(str(self.current_min)) self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def change_palette(self): self.current_color_palette = self.available_palettes[self.ui.palettes_box.currentIndex()] self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def slider_gain_updated(self, index): slider_gain = self.bands_powers[self.band_slider[index].value()] self.band_label[index].setText(f'{slider_gain}') self.current_slider_gain[index] = slider_gain self.modify_signal() def modify_signal(self): frequency_content = np.fft.rfftfreq(len(self.samples), d=1/self.sampling_rate) modified_signal = np.fft.rfft(self.samples) for index, slider_gain in enumerate(self.current_slider_gain): frequency_range_min = (index + 0) * self.sampling_rate / (2 * 10) frequency_range_max = (index + 1) * self.sampling_rate / (2 * 10) x = frequency_content > frequency_range_min y = frequency_content <= frequency_range_max z = [] for a, b in zip(x, y): z.append(a and b) modified_signal[z] *= slider_gain self.samples_after = np.fft.irfft(modified_signal) samplerate = 44100 try: shutil.rmtree('wav') os.mkdir('wav') except: os.mkdir('wav') now = datetime.now() now = f'{now:%Y-%m-%d %H-%M-%S.%f %p}' scipy.io.wavfile.write(f"wav/SBME{now}.wav", samplerate, self.samples_after.astype(np.int16)) path = os.listdir('wav') self.audio_player_after.setMedia(QMediaContent(qtc.QUrl.fromLocalFile(f'wav/{path[0]}'))) self.audio_player_after.positionChanged.connect(lambda position: self.update_timestamp(position, self.ui.current_time_after, self.ui.time_seeker_after)) self.ui.time_seeker_after.valueChanged.connect(self.audio_player_after.setPosition) self.plot_graph(self.samples_after, self.sampling_rate, 'after') def open_audio_file(self): filename = qtw.QFileDialog.getOpenFileName( None, 'Load Audio', './', "Audio File(*.wav)") path = filename[0] self.audio_player_before.setMedia(QMediaContent(qtc.QUrl.fromLocalFile(path))) self.sampling_rate, self.samples = scipy.io.wavfile.read(path) self.plot_graph(self.samples, self.sampling_rate, 'before') self.audio_player_before.positionChanged.connect(lambda position: self.update_timestamp(position, self.ui.current_time_before, self.ui.time_seeker_before)) self.ui.time_seeker_before.valueChanged.connect(self.audio_player_before.setPosition) for slider in self.band_slider.values(): slider.setDisabled(False) slider.setStyleSheet('selection-background-color: blue') self.ui.max_freq_content.setDisabled(False) self.ui.max_freq_content.setStyleSheet('selection-background-color: blue') self.ui.min_freq_content.setDisabled(False) self.ui.min_freq_content.setStyleSheet('selection-background-color: blue') self.modify_signal() def update_duration(self, duration): self.ui.time_seeker_before.setMaximum(duration) if duration >= 0: self.ui.total_time_before.setText(time_stamp(duration)) def update_duration_after(self, duration): self.ui.time_seeker_after.setMaximum(duration) if duration >= 0: self.ui.total_time_after.setText(time_stamp(duration)) def update_timestamp(self, position, currentTimeLabel, timeSlider): if position >= 0: currentTimeLabel.setText(time_stamp(position)) timeSlider.blockSignals(True) timeSlider.setValue(position) timeSlider.blockSignals(False) def plot_graph(self, samples, sampling_rate, widget): # Preparing received data peak_value = np.amax(samples) normalized_data = samples / peak_value length = samples.shape[0] / sampling_rate time = list(np.linspace(0, length, normalized_data.shape[0])) drawing_pen = pg.mkPen(color=(255, 0, 0), width=0.5) self.plot_widget[widget].removeItem(self.data_line[widget]) self.data_line[widget] = self.plot_widget[widget].plot( time, normalized_data, pen=drawing_pen) self.plot_widget[widget].plotItem.setLabel(axis='left', text='Normalized Amplitude') self.plot_widget[widget].plotItem.setLabel(axis='bottom', text='time [s]') self.plot_widget[widget].plotItem.getViewBox().setLimits(xMin=0, xMax=np.max(time), yMin=-1.1, yMax=1.1) self.spectrogram_time_min, self.spectrogram_time_max = self.plot_widget[widget].plotItem.getAxis('bottom').range # self.playback_position[widget] = pyqtgraph.LinearRegionItem(values=(0, 0)) # self.plot_widget[widget].plotItem.getViewBox().addItem(self.playback_position[widget]) self.plot_spectrogram(samples, sampling_rate, widget) def plot_spectrogram(self, samples, sampling_rate, widget): axes = self.spectrogram_widget[widget].getFigure().clear() axes = self.spectrogram_widget[widget].getFigure().add_subplot(111) data = samples.astype('float32') D = np.abs(librosa.stft(data))**2 S = librosa.feature.melspectrogram(S=D, y=data, sr=sampling_rate, n_mels=128, fmin=self.current_min ,fmax=self.current_max) S_dB = librosa.power_to_db(S, ref=np.max) img = librosa.display.specshow(S_dB, x_axis='time', y_axis='mel', sr=sampling_rate, fmin=self.current_min ,fmax=self.current_max, ax=axes, cmap=self.current_color_palette) self.spectrogram_widget[widget].getFigure().colorbar(img, ax=axes, format='%+2.0f dB') axes.set(xlim=[self.spectrogram_time_min, self.spectrogram_time_max]) self.spectrogram_widget[widget].draw() def zoomin(self) -> None: self.ui.graph_before.plotItem.getViewBox().scaleBy((0.75, 1.0)) self.ui.graph_before.plotItem.getViewBox().setXLink(self.ui.graph_after.plotItem) self.spectrogram_time_min, self.spectrogram_time_max = self.ui.graph_before.plotItem.getAxis('bottom').range self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def zoomout(self) -> None: self.ui.graph_before.plotItem.getViewBox().scaleBy((1.25, 1.0)) self.ui.graph_before.plotItem.getViewBox().setXLink(self.ui.graph_after.plotItem) self.spectrogram_time_min, self.spectrogram_time_max = self.ui.graph_before.plotItem.getAxis('bottom').range self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def back(self): self.ui.graph_before.plotItem.getViewBox().translateBy((-0.5, 0.0)) self.ui.graph_before.plotItem.getViewBox().setXLink(self.ui.graph_after.plotItem) self.spectrogram_time_min, self.spectrogram_time_max = self.ui.graph_before.plotItem.getAxis('bottom').range self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def forward(self): self.ui.graph_before.plotItem.getViewBox().translateBy((0.5, 0.0)) self.ui.graph_before.plotItem.getViewBox().setXLink(self.ui.graph_after.plotItem) self.spectrogram_time_min, self.spectrogram_time_max = self.ui.graph_before.plotItem.getAxis('bottom').range self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def generatePDF(self): images = [0, 0] Idx = 0 for channel in range(2): self.amplitude[channel] images[channel] = 1 Idx += 1 if not Idx: qtw.QMessageBox.information( self, 'failed', 'You have to plot a signal first') return try: shutil.rmtree(self.PLOT_DIR) os.mkdir(self.PLOT_DIR) except FileNotFoundError: os.mkdir(self.PLOT_DIR) for channel in range(2): if images[channel]: exporter = pg.exporters.ImageExporter( self.graphChannels[channel].scene()) exporter.export(f'{self.PLOT_DIR}/plot-{channel}.png') self.spectrogramChannels[channel].fig.savefig(f'{self.PLOT_DIR}/spec-{channel}.png') pdf = PDF() plots_per_page = pdf.construct(self.PLOT_DIR) [['plot1', 'spec1'], ['plot2', 'spec2']] for elem in plots_per_page: pdf.print_page(elem, self.PLOT_DIR) now = datetime.now() now = f'{now:%Y-%m-%d %H-%M-%S.%f %p}' try: os.mkdir(self.PDF_DIR) except: pass pdf.output(f'{self.PDF_DIR}/{now}.pdf', 'F') try: shutil.rmtree(self.PLOT_DIR) except: pass qtw.QMessageBox.information(self, 'success', 'PDF has been created') def new_instance(self): self.new_instance = MainWindow() self.new_instance.show()
class FFWindow(QtWidgets.QWidget): def __init__(self, movie_dir, pos_snapshot_dir, neg_snapshot_dir): super().__init__() self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.movie_dir = movie_dir video_list = glob.glob(os.path.join(self.movie_dir, "*.mp4")) print("{} movies found".format(len(video_list))) # We want to be able to cycle through them self.video_files = itertools.cycle(iter(video_list)) # Check the output directories exist self.pos_snapshot_dir = pos_snapshot_dir if not os.path.exists(self.pos_snapshot_dir): os.makedirs(self.pos_snapshot_dir) self.neg_snapshot_dir = neg_snapshot_dir if not os.path.exists(self.neg_snapshot_dir): os.makedirs(self.neg_snapshot_dir) self.setWindowTitle('FrameFinder') self.video_widget = QVideoWidget() # self.video_widget.setFixedSize(640, 360) # self.video_widget. self.video_widget.setMinimumSize(640, 360) self.video_widget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.media_player.setVideoOutput(self.video_widget) self.position_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) self.position_slider.setRange(0, 0) self.position_slider.sliderMoved.connect(self.set_position) self.errorLabel = QtWidgets.QLabel() # self.errorLabel.setSizePolicy(QtWidgets.QSizePolicy.Preferred, # QtWidgets.QSizePolicy.Maximum) self.fileLabel = QtWidgets.QLabel() self.rewind_but = QtWidgets.QPushButton() self.rewind_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_ArrowLeft)) self.rewind_but.setText("Normal [A]") self.rewind_but.clicked.connect(self.rewind) self.slow_rewind_but = QtWidgets.QPushButton() self.slow_rewind_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_ArrowLeft)) self.slow_rewind_but.setText("Slow [S]") self.slow_rewind_but.clicked.connect(self.slow_rewind) self.play_but = QtWidgets.QPushButton() self.play_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_MediaPlay)) self.play_but.setText("[D]") self.play_but.clicked.connect(self.playtoggle) self.slow_forward_but = QtWidgets.QPushButton() self.slow_forward_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_ArrowRight)) self.slow_forward_but.setText("Slow [F]") self.slow_forward_but.clicked.connect(self.slow_forward) self.forward_but = QtWidgets.QPushButton() self.forward_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_ArrowRight)) self.forward_but.setText("Normal [G]") self.forward_but.clicked.connect(self.forward) self.fast_forward_but = QtWidgets.QPushButton() self.fast_forward_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_ArrowRight)) self.fast_forward_but.setText("Fast [H]") self.fast_forward_but.clicked.connect(self.fast_forward) self.pos_snapshot_but = QtWidgets.QPushButton() self.pos_snapshot_but.setText("Snapshot Positive [P]") self.pos_snapshot_but.clicked.connect(self.pos_snapshot) self.neg_snapshot_but = QtWidgets.QPushButton() self.neg_snapshot_but.setText("Snapshot Negative [O]") self.neg_snapshot_but.clicked.connect(self.neg_snapshot) self.next_but = QtWidgets.QPushButton() self.next_but.setText("Next movie [N]") self.next_but.clicked.connect(self.next_video) video_vbox = QtWidgets.QVBoxLayout() video_vbox.addWidget(self.video_widget) video_vbox.addWidget(self.position_slider) control_box = QtWidgets.QHBoxLayout() control_box.addWidget(self.rewind_but) control_box.addWidget(self.slow_rewind_but) control_box.addWidget(self.play_but) control_box.addWidget(self.slow_forward_but) control_box.addWidget(self.forward_but) control_box.addWidget(self.fast_forward_but) video_vbox.addLayout(control_box) video_vbox.addWidget(self.errorLabel) video_vbox.addWidget(self.fileLabel) file_box = QtWidgets.QHBoxLayout() file_box.addWidget(self.pos_snapshot_but) file_box.addWidget(self.neg_snapshot_but) file_box.addWidget(self.next_but) v_box = QtWidgets.QVBoxLayout() # v_box.addStretch() v_box.addLayout(video_vbox) v_box.addLayout(file_box) # v_box.addStretch() self.setLayout(v_box) self.media_player.stateChanged.connect(self.status_changed) # self.media_player.availabilityChanged.connect(self.status_changed) self.media_player.positionChanged.connect(self.position_changed) self.media_player.durationChanged.connect(self.duration_changed) self.media_player.error.connect(self.handleError) self.next_video() # Set up some keyboard shortcuts shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("a"), self) shortcut.activated.connect(self.rewind_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("s"), self) shortcut.activated.connect(self.slow_rewind_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("d"), self) shortcut.activated.connect(self.play_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence(" "), self) shortcut.activated.connect(self.play_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("f"), self) shortcut.activated.connect(self.slow_forward_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("g"), self) shortcut.activated.connect(self.forward_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("h"), self) shortcut.activated.connect(self.fast_forward_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("p"), self) shortcut.activated.connect(self.pos_snapshot_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("o"), self) shortcut.activated.connect(self.neg_snapshot_but.animateClick) shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("n"), self) shortcut.activated.connect(self.next_but.animateClick) def playtoggle(self): if self.media_player.state() == QMediaPlayer.PlayingState: self.pause() else: self.play() def pause(self): self.media_player.pause() def play(self): self.media_player.play() # This is a nasty hack. The video tends to zoom to 1:1 # when you play, but rescales itself when you resize the window. # Faking a window resize is the only way I could find to fix the zoom. size = self.size() self.resize(size.width() + 1, size.height() + 1) self.resize(size.width(), size.height()) def rewind(self): self.media_player.setPlaybackRate(-1) self.errorLabel.setText("Rewind 1x") self.play() def slow_rewind(self): self.media_player.setPlaybackRate(-0.25) self.errorLabel.setText("Rewind 0.25x") self.play() def slow_forward(self): self.media_player.setPlaybackRate(0.25) self.errorLabel.setText("Forward 0.25x") self.play() def forward(self): self.media_player.setPlaybackRate(1.0) self.errorLabel.setText("Forward 1x") self.play() def fast_forward(self): self.media_player.setPlaybackRate(2.0) self.errorLabel.setText("Forward 2x") self.play() def status_changed(self): if self.media_player.state() == QMediaPlayer.PlayingState: self.play_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_MediaPause)) else: self.play_but.setIcon(self.style().standardIcon( QtWidgets.QStyle.SP_MediaPlay)) self.play_but.repaint() # print ("Status", self.media_player.mediaStatus()) def position_changed(self, position): # print("Position changed to", position) self.position_slider.setValue(position) def duration_changed(self, duration): print("Duration changed to", duration) self.position_slider.setRange(0, duration) def set_position(self, position): self.media_player.setPosition(position) def pos_snapshot(self): self.snapshot(self.pos_snapshot_dir) def neg_snapshot(self): self.snapshot(self.neg_snapshot_dir) def snapshot(self, snap_dir): video_path = self.media.canonicalUrl().path() position = self.media_player.position() video_file, extension = os.path.splitext(os.path.basename(video_path)) snapshot_file = os.path.join(snap_dir, "{}_{}.jpg".format(video_file, position)) # Use ffmpeg because it's not clear how to get # the frame back from the video surface cmd = [ "ffmpeg", "-ss", str(position / 1000), "-i", video_path, "-frames", "1", snapshot_file ] print(" ".join(cmd)) retcode = subprocess.call(cmd) if retcode == 0: self.errorLabel.setText("Saved {}".format(snapshot_file)) else: self.errorLabel.setText("Error running ffmpeg") def next_video(self): # Display the next file if there is one try: self.errorLabel.clear() next_video = os.path.join(os.getcwd(), next(self.video_files)) print(next_video) self.pause() self.media = QMediaContent(QtCore.QUrl.fromLocalFile(next_video)) self.media_player.setMedia(self.media) self.fileLabel.setText(next_video) self.play() except StopIteration: pass def handleError(self): self.errorLabel.setText("Error: " + self.media_player.errorString())
class VideoPlayer(QWidget): def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self.setWindowTitle("ViSA") self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() openButton = QPushButton("Load Video File") openButton.clicked.connect(self.openFile) self.startValue = 0 self.endValue = 0 self.forwardButton = QPushButton() self.forwardButton.setEnabled(False) self.forwardButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.forwardButton.clicked.connect(self.forward) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.backwardButton = QPushButton() self.backwardButton.setEnabled(False) self.backwardButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.backwardButton.clicked.connect(self.backward) self.playBackSpeed = QComboBox() self.playBackSpeed.addItem("0.25") self.playBackSpeed.addItem("0.5") self.playBackSpeed.addItem("0.75") self.playBackSpeed.addItem("1") self.playBackSpeed.addItem("1.25") self.playBackSpeed.addItem("1.5") self.playBackSpeed.addItem("1.75") self.playBackSpeed.addItem("2") self.playBackSpeed.setCurrentIndex(3) self.playBackSpeed.setVisible(False) self.start = QSlider(Qt.Horizontal) self.start.setRange(0, 0) self.start.sliderMoved.connect(self.setPosition) self.startLabel = QLabel() self.end = QSlider(Qt.Horizontal) self.end.setRange(0, 0) self.end.sliderMoved.connect(self.setPosition) self.endLabel = QLabel() controlLayout = QHBoxLayout() controlLayout.setContentsMargins(250, 0, 350, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.backwardButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.forwardButton) controlLayout.addWidget(self.playBackSpeed) sliders = QVBoxLayout() sliders.setContentsMargins(0, 0, 0, 0) sliderLayout = QHBoxLayout() sliderLayout.setContentsMargins(0, 0, 0, 0) sliderLayout.addWidget(self.startLabel) sliderLayout.addWidget(self.start) sliders.addLayout(sliderLayout) sliderLayout = QHBoxLayout() sliderLayout.setContentsMargins(0, 0, 0, 0) sliderLayout.addWidget(self.endLabel) sliderLayout.addWidget(self.end) sliders.addLayout(sliderLayout) self.editGesture = QLineEdit() self.editGesture.setVisible(False) self.editGesture.setPlaceholderText("Add Gesture") self.editGesture.setFixedWidth(200) self.gestures = QComboBox() self.gestures.addItem("Walking") self.gestures.setVisible(False) self.gesture = "Walking" self.submit = QPushButton("Submit") self.submit.clicked.connect(self.addGesture) self.submit.setVisible(False) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) footer = QHBoxLayout() footer.setContentsMargins(250, 0, 350, 0) footer.addWidget(self.editGesture) footer.addWidget(self.gestures) footer.addWidget(self.submit) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addLayout(sliders) layout.addLayout(footer) layout.addWidget(self.errorLabel) self.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.start.valueChanged.connect(self.valueChangedStart) self.end.valueChanged.connect(self.valueChangedEnd) self.mediaPlayer.error.connect(self.handleError) self.gestures.activated[str].connect(self.onGestureChanged) self.playBackSpeed.activated[str].connect(self.playBackSpeedChanged) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", ".") if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) self.gestures.setVisible(True) self.submit.setVisible(True) self.editGesture.setVisible(True) self.forwardButton.setEnabled(True) self.backwardButton.setEnabled(True) self.playBackSpeed.setVisible(True) self.errorLabel.setText(" ") def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def forward(self): self.mediaPlayer.setPosition(self.end.value() + 2000) def backward(self): self.mediaPlayer.setPosition(self.end.value() - 2000) def playBackSpeedChanged(self, value): self.mediaPlayer.setPlaybackRate(float(value)) def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.end.setValue(position) def durationChanged(self, duration): self.start.setRange(0, duration) self.end.setRange(0, duration) self.startLabel.setText("00:00:00") self.endLabel.setText("00:00:00") def onGestureChanged(self, text): self.gesture = text def setPosition(self, position): self.mediaPlayer.setPosition(position) def valueChangedStart(self): position = self.start.value() self.mediaPlayer.setPosition(position) self.startLabel.setText(self.getDurationInSeconds(position)) self.startValue = position def valueChangedEnd(self): position = self.end.value() self.mediaPlayer.setPosition(position) self.endLabel.setText(self.getDurationInSeconds(position)) self.endValue = position def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def getDurationInSeconds(self, value): return time.strftime('%H:%M:%S', time.gmtime(math.ceil(value / 1000))) def addGesture(self): gesture = self.editGesture.text().strip() with open('manifest.csv', 'a', newline='') as writer: writer = csv.writer(writer) duration = round(self.endValue // 1000, 2) - round( self.startValue // 1000, 2) if len(gesture) == 0: gesture = self.gesture gesture = gesture.replace(" ", "_") writer.writerow( [round(self.startValue // 1000, 2), duration, gesture]) if len(self.editGesture.text()) > 0: if self.editGesture.text() not in [ self.gestures.itemText(i) for i in range(self.gestures.count()) ]: self.gestures.addItem(self.editGesture.text()) QMessageBox.about(self, "Info", gesture + "Gesture Added!")
class test(QMainWindow, Ui_video_player): def __init__(self, *args, **kwargs): super(test, self).__init__(*args, **kwargs) self.player = QMediaPlayer() self.flag = 0 # 用于获取视频全长度 self.setupUi(self) # 初始化ui self.bind() # 绑定事件 self.rate_list = [0.25, 0.5, 1, 1.25, 1.5, 2, 2.5] # 记录下标 self.fastest_rate = len(self.rate_list) - 1 self.slowest_rate = 0 self.index = 2 def bind(self): self.upload_delete_button.clicked.connect(self.upload_file) self.on_off_button.clicked.connect(self.play_pause) # 播放和暂停 self.back_button.clicked.connect(self.jog_rate) # 慢倍速 self.forward_button.clicked.connect(self.accelerate) # 快倍速 def upload_file(self): file = QFileDialog.getOpenFileName( self, "选择文件", "C:/Users/陈键淞/Desktop", " MP4 Files(*.mp4);;AVI Files(*.avi)") # 此处进行视频处理 if file[0]: self.player.setVideoOutput(self.video_play_widget) # 视频播放输出的widget self.player.setMedia(QMediaContent(QUrl.fromLocalFile( file[0]))) # 选取视频文件 self.player.setVolume(50) # 设置初始播放音量 self.player.setPlaybackRate(self.rate_list[self.index]) # 设置初始播放速度 self.player.positionChanged.connect(self.show_video_slider) # 视频进度 self.volume_slider.valueChanged.connect( self.drag_volume_slider) # 拖动音量条调节音量 self.timer_slider.sliderMoved.connect( self.drag_video_slider) # 拖动进度条改变播放进度 self.timer_slider.sliderReleased.connect( self.drag_video_slider_over) # 拖动进度条调整完成 self.on_off_button.setObjectName("off_button") self.on_off_button.setIcon(QIcon("../ico/stop.png")) self.player.play() # 播放视频 # 控制视频播放和暂停 def play_pause(self): if self.on_off_button.objectName() == "off_button": self.player.pause() print(self.player.State) self.on_off_button.setObjectName("on_button") self.on_off_button.setIcon(QIcon("../ico/start.png")) elif self.on_off_button.objectName() == "on_button": self.player.play() self.on_off_button.setObjectName("off_button") self.on_off_button.setIcon(QIcon("../ico/stop.png")) # 监听视频当前进度 def show_video_slider(self, position): video_length = self.player.duration() self.timer_slider.setRange(0, int(video_length / 1000) + 1) # 设置进度条范围 self.timer_slider.setValue(round(int(position / 1000))) self.now_timer_label.setText( # 当前视频进度 str(int(position / 1000) // 60).zfill(2) + ':' + str(int(position / 1000) % 60).zfill(2)) # 设置视频全长度 if self.flag == 0: video_length = self.player.duration() self.timer_slider.setRange(0, int(video_length / 1000) + 1) # 设置进度条范围 self.whole_timer_label.setText( # 全视频长度 str(int(video_length / 1000) // 60).zfill(2) + ':' + str(int(video_length / 1000) % 60).zfill(2)) self.flag = 1 # 拖动音量进度条,调节音量 def drag_volume_slider(self): self.player.setVolume(self.volume_slider.value()) if self.volume_slider.value() == 0: self.volume_label.setPixmap(QPixmap("../ico/no_volume.png")) elif self.volume_slider.value() < 30: self.volume_label.setPixmap(QPixmap("../ico/small_volume.png")) elif self.volume_slider.value() < 70: self.volume_label.setPixmap(QPixmap("../ico/center_volume.png")) else: self.volume_label.setPixmap(QPixmap("../ico/high_volume.png")) # 拖动视频进度条,调节视频进度, 有bug,尚未解决 def drag_video_slider(self): self.player.pause() self.timer_slider.valueChanged.connect(self.set_video_value) def set_video_value(self): self.player.setPosition(self.timer_slider.value() * 1000) def drag_video_slider_over(self): self.player.play() def jog_rate(self): if self.index > self.slowest_rate: self.index -= 1 self.player.pause() self.player.setPlaybackRate(self.rate_list[self.index]) self.player.play() def accelerate(self): if self.index < self.fastest_rate: self.index += 1 self.player.pause() self.player.setPlaybackRate(self.rate_list[self.index]) self.player.play()
class VideoWindow(QMainWindow): def __init__(self): super().__init__() self.label3 = QLabel(self) pix = QPixmap('background.png') self.label3.setPixmap(pix) self.label3.setGeometry(100, 0, 640, 480) self.setWindowTitle("MALLIK AUDIO/VIDEO PLAYER") self.setWindowIcon(QIcon('video icon.png')) videoWidget = QVideoWidget() self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.sliderMoved.connect(self.setPosition) self.positionSlider2 = QSlider(Qt.Horizontal) self.positionSlider2.setMinimum(55) self.positionSlider2.setMaximum(100) self.positionSlider2.setValue(55) self.positionSlider2.valueChanged.connect(self.volumeChanged) self.positionSlider2.setTickPosition(QSlider.TicksBothSides) self.backward = QPushButton() self.backward.setEnabled(True) self.backward.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) # self.backward.clicked.connect(self.backwar) self.forward = QPushButton() self.forward.setEnabled(True) self.forward.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) # Create new action openAction = QAction(QIcon('open3.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.triggered.connect(self.openFile) # Create exit action exitAction = QAction(QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # Create menu bar and add action menuBar = self.menuBar() fileMenu = menuBar.addMenu(QIcon('open8.png'), '&File') # fileName = QFileDialog.getOpenFileName(self, "Open Movie",QDir.homePath()) menuBar2 = self.menuBar() fileMenu2 = menuBar2.addMenu('playback') action = QAction(QIcon('forward.png'), '&1.5', self) action.triggered.connect(self.forward1) fileMenu2.addAction(action) action1 = QAction(QIcon('forward.png'), '&2.0', self) action1.triggered.connect(self.forward2) fileMenu2.addAction(action1) action2 = QAction(QIcon('forward.png'), '&0.25', self) action2.triggered.connect(self.forward3) fileMenu2.addAction(action2) action3 = QAction('&audio', self) # action3.triggered.connect(self.audio) fileMenu2.addAction(action3) fileMenu.addAction(openAction) fileMenu.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.addWidget(self.playButton) # controlLayout.addWidget(self.backward) controlLayout.addWidget(self.positionSlider) # controlLayout.addWidget(self.forward) controlLayout.addWidget(self.positionSlider2) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) # print(self.mediaPlayer.currentMedia().canonicalUrl().toString()) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.currentMediaChanged.connect(self.songChanged) def songChanged(self, media): if not media.isNull(): url = media.canonicalUrl() self.statusBar().showMessage(url.fileName()) def openFile(self, fileName): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.mediaPlayer.setPosition(0) self.playButton.setEnabled(True) def exitCall(self): sys.exit(app.exec_()) def play(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def volumeChanged(self, volume): volume = self.positionSlider2.value() self.mediaPlayer.setVolume(volume) def forward1(self): self.mediaPlayer.setPlaybackRate(1.5) def forward2(self): self.mediaPlayer.setPlaybackRate(2.0) def forward3(self): self.mediaPlayer.setPlaybackRate(0.25)
class Window(QWidget, Ui_Window): def __init__(self): super().__init__() self.setupUi(self) self.status = False self.player = QMediaPlayer() self.player.setNotifyInterval(100) self.open_button.clicked.connect(self.open_dialog) self.play_pause_button.clicked.connect(self.play_pause) self.stop_button.clicked.connect(self.stop) self.player.durationChanged.connect(self.track_duration) self.player.positionChanged.connect(self.track_position) self.player.mediaStatusChanged.connect(self.track_status) self.position_slider.sliderPressed.connect( self.change_track_position_block) self.position_slider.sliderReleased.connect( self.change_track_position_unblock) self.volume_slider.valueChanged.connect(self.player.setVolume) self.mute_button.clicked.connect(self.mute) self.playback_spinbox.valueChanged.connect(self.change_playback) def play_pause(self): if self.status: self.play_pause_button.setText('Play') self.player.pause() self.status = False else: self.play_pause_button.setText('Pause') self.stop_button.setEnabled(True) self.player.play() self.status = True def stop(self): if self.status: self.play_pause_button.setText('Play') self.stop_button.setEnabled(False) self.player.stop() self.status = False def track_duration(self, duration): self.track_duration_label.setText(ms_to_time(duration)) self.position_slider.setMaximum(duration) def track_position(self, position): self.track_position_label.setText(ms_to_time(position)) self.position_slider.setValue(position) def change_track_position_block(self): self.player.positionChanged.disconnect(self.track_position) self.position_slider.valueChanged.connect( self.change_track_position_label) def change_track_position_label(self, value): self.track_position_label.setText(ms_to_time(value)) def change_track_position_unblock(self): self.player.setPosition(self.position_slider.value()) self.position_slider.valueChanged.disconnect( self.change_track_position_label) self.player.positionChanged.connect(self.track_position) def track_status(self, status): if status == 7: self.stop() self.player.setPosition(0) def change_playback(self, value): self.player.positionChanged.disconnect(self.track_position) position = self.player.position() self.player.stop() self.player.setPlaybackRate(value) self.player.play() self.player.setPosition(position) self.player.positionChanged.connect(self.track_position) def mute(self): if self.player.isMuted(): self.player.setMuted(False) self.volume_slider.setEnabled(True) self.mute_button.setText('🔊') else: self.volume_slider.setEnabled(False) self.player.setMuted(True) self.mute_button.setText('🔈') def open_dialog(self): track = QFileDialog.getOpenFileName( self, dialog, '', 'Music (*.flac *.ogg *.mp3 *.wav *.webm)')[0] if track: self.play_pause_button.setEnabled(True) self.position_slider.setEnabled(True) self.volume_slider.setEnabled(True) self.mute_button.setEnabled(True) self.playback_spinbox.setEnabled(True) self.player.setMedia(QMediaContent(QUrl.fromLocalFile(track))) self.stop()
class MainWindow(qtw.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.show() self.samples = None self.sampling_rate = None self.samples_after = None self.first_turn = True # This Prevents the Spectrogram range variables from being overwritten self.PLOT_DIR = 'Plots' self.PDF_DIR = 'PDFs' self.ui.save_session_data.clicked.connect(lambda: self.save_session()) self.ui.actionSave.triggered.connect(lambda: self.save_session()) self.audio_player_before = QMediaPlayer() self.audio_player_after = QMediaPlayer() self.audio_player_before.setNotifyInterval(1) self.audio_player_after.setNotifyInterval(1) self.bands_powers = [0.0, 0.25, 0.50, 0.75, 1.0, 2.0, 3.0, 4.0, 5.0] self.spectrogram_power_range = { 'min': np.array([]), 'max': np.array([]) } self.ui.min_pixel_intensity.sliderReleased.connect( lambda: self.spectrogram_pixels_intensity('min')) self.ui.max_pixel_intensity.sliderReleased.connect( lambda: self.spectrogram_pixels_intensity('max')) self.spectrogram_time_min, self.spectrogram_time_max = 0, 0 # Sync With Play self.band_slider = {} self.band_label = {} for index in range(10): self.band_slider[index] = getattr(self.ui, 'band_{}'.format(index + 1)) self.band_label[index] = getattr(self.ui, 'band_{}_label'.format(index + 1)) for slider in self.band_slider.values(): slider.setDisabled(True) slider.setStyleSheet('selection-background-color: grey') for index, slider in self.band_slider.items(): slider.sliderReleased.connect( lambda index=index: self.slider_gain_updated(index)) self.available_palettes = [ 'twilight', 'Blues', 'Greys', 'ocean', 'nipy_spectral' ] self.current_color_palette = self.available_palettes[0] self.modified_signal = np.array([]) self.current_slider_gain = [1.0] * 10 self.controlers = {'before': [], 'after': []} for button, function in zip( ['zoom_in', 'zoom_out', 'jump_forward', 'jump_back'], [self.zoomin, self.zoomout, self.forward, self.back]): self.controlers['before'].append( (getattr(self.ui, '{}_btn_before'.format(button)), function)) self.controlers['after'].append( (getattr(self.ui, '{}_btn_after'.format(button)), function)) for channel in self.controlers.values(): for signal in channel: signal[0].clicked.connect(signal[1]) self.plot_widget = { 'before': self.ui.graph_before, 'after': self.ui.graph_after } self.spectrogram_widget = { 'before': self.ui.spectrogram_before, 'after': self.ui.spectrogram_after } self.data_line = {'before': None, 'after': None} self.playback_position = {'before': None, 'after': None} self.time_seeker = { 'before': self.ui.time_seeker_before, 'after': self.ui.time_seeker_after } self.total_time = { 'before': self.ui.total_time_before, 'after': self.ui.total_time_after } self.ui.actionExit.triggered.connect(self.close) self.ui.actionNew.triggered.connect(self.new_instance) self.ui.actionOpen.triggered.connect(self.open_audio_file) self.ui.play_btn_before.clicked.connect(self.audio_player_before.play) self.ui.pause_btn_before.clicked.connect( self.audio_player_before.pause) self.ui.stop_btn_before.clicked.connect(self.audio_player_before.stop) self.ui.play_btn_after.clicked.connect(self.audio_player_after.play) self.ui.pause_btn_after.clicked.connect(self.audio_player_after.pause) self.ui.stop_btn_after.clicked.connect(self.audio_player_after.stop) self.ui.palettes_box.currentTextChanged.connect(self.change_palette) self.ui.playback_speed_before.currentIndexChanged.connect( lambda: self.audio_player_before.setPlaybackRate( float(self.ui.playback_speed_before.currentText()[1:]))) self.audio_player_before.durationChanged.connect( lambda duration: self.update_duration(duration, 'before')) self.ui.playback_speed_after.currentIndexChanged.connect( lambda: self.audio_player_after.setPlaybackRate( float(self.ui.playback_speed_after.currentText()[1:]))) self.audio_player_after.durationChanged.connect( lambda duration: self.update_duration(duration, 'after')) def new_instance(self): self.new_instance = MainWindow() self.new_instance.show() def open_audio_file(self): path = qtw.QFileDialog.getOpenFileName(None, 'Load Audio', './', "Audio File(*.wav)")[0] for slider in self.band_slider.values(): slider.setDisabled(False) slider.setStyleSheet('selection-background-color: blue') self.ui.max_pixel_intensity.setDisabled(False) self.ui.max_pixel_intensity.setStyleSheet( 'selection-background-color: blue') self.ui.min_pixel_intensity.setDisabled(False) self.ui.min_pixel_intensity.setStyleSheet( 'selection-background-color: blue') self.audio_player_before.setMedia( QMediaContent(qtc.QUrl.fromLocalFile(path))) self.audio_player_before.positionChanged.connect( lambda position: self.update_timestamp( position, self.ui.current_time_before, self.ui. time_seeker_before, 'before')) self.ui.time_seeker_before.valueChanged.connect( self.audio_player_before.setPosition) self.sampling_rate, self.samples = scipy.io.wavfile.read(path) self.plot_graph(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.modify_signal() def plot_graph(self, samples, sampling_rate, widget): peak_value = np.amax(samples) normalized_data = samples / peak_value length = samples.shape[0] / sampling_rate time = list(np.linspace(0, length, samples.shape[0])) drawing_pen = pg.mkPen(color=(255, 0, 0), width=0.5) self.plot_widget[widget].removeItem(self.data_line[widget]) self.data_line[widget] = self.plot_widget[widget].plot(time, normalized_data, pen=drawing_pen) self.plot_widget[widget].plotItem.setLabel(axis='left', text='Normalized Amplitude') self.plot_widget[widget].plotItem.setLabel(axis='bottom', text='time [s]') self.plot_widget[widget].plotItem.getViewBox().setLimits( xMin=0, xMax=np.max(time), yMin=-1.1, yMax=1.1) self.spectrogram_time_min, self.spectrogram_time_max = self.plot_widget[ widget].plotItem.getAxis('bottom').range self.playback_position[widget] = pyqtgraph.LinearRegionItem(values=(0, 0)) self.plot_widget[widget].plotItem.getViewBox().addItem( self.playback_position[widget]) def plot_spectrogram(self, samples, sampling_rate, widget): self.spectrogram_widget[widget].getFigure().clear() spectrogram_axes = self.spectrogram_widget[widget].getFigure( ).add_subplot(111) data = samples.astype('float32') frequency_magnitude = np.abs(librosa.stft(data))**2 mel_spectrogram = librosa.feature.melspectrogram(S=frequency_magnitude, y=data, sr=sampling_rate, n_mels=128) decibel_spectrogram = librosa.power_to_db(mel_spectrogram, ref=np.max) if self.first_turn: min_intensity = np.ceil(np.amin(decibel_spectrogram)) max_intensity = np.ceil(np.amax(decibel_spectrogram)) self.spectrogram_power_range['min'] = np.linspace( min_intensity, min_intensity / 2, 10).astype('int') self.spectrogram_power_range['min'] = np.append( self.spectrogram_power_range['min'], np.array([self.spectrogram_power_range['min'][0]])) self.spectrogram_power_range['max'] = np.linspace( (min_intensity + 1) / 2, max_intensity, 10).astype('int') self.spectrogram_power_range['max'] = np.append( self.spectrogram_power_range['max'], np.array([self.spectrogram_power_range['max'][-1]])) self.ui.min_pixel_intensity_lab.setText( str(self.spectrogram_power_range['min'][-1])) self.ui.max_pixel_intensity_lab.setText( str(self.spectrogram_power_range['max'][-1])) self.first_turn = False spectrogram_image = librosa.display.specshow( decibel_spectrogram, x_axis='time', y_axis='mel', sr=sampling_rate, ax=spectrogram_axes, cmap=self.current_color_palette, vmin=self.spectrogram_power_range['min'][-1], vmax=self.spectrogram_power_range['max'][-1]) self.spectrogram_widget[widget].getFigure().colorbar( spectrogram_image, ax=spectrogram_axes, format='%+2.0f dB') spectrogram_axes.set( xlim=[self.spectrogram_time_min, self.spectrogram_time_max]) self.spectrogram_widget[widget].draw() def modify_signal(self): frequency_content = np.fft.rfftfreq(len(self.samples), d=1 / self.sampling_rate) modified_signal = np.fft.rfft(self.samples) for index, slider_gain in enumerate(self.current_slider_gain): frequency_range_min = (index + 0) * self.sampling_rate / (2 * 10) frequency_range_max = (index + 1) * self.sampling_rate / (2 * 10) range_min_frequency = frequency_content > frequency_range_min range_max_frequency = frequency_content <= frequency_range_max slider_min_max = [] for is_in_min_frequency, is_in_max_frequency in zip( range_min_frequency, range_max_frequency): slider_min_max.append(is_in_min_frequency and is_in_max_frequency) modified_signal[slider_min_max] *= slider_gain self.samples_after = np.fft.irfft(modified_signal) self.save_output_wav() self.plot_graph(self.samples_after, self.sampling_rate, 'after') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def spectrogram_pixels_intensity(self, widget): slider = getattr(self.ui, '{}_pixel_intensity'.format(widget)) self.spectrogram_power_range[widget][ -1] = self.spectrogram_power_range[widget][int(slider.value())] label = getattr(self.ui, '{}_pixel_intensity_lab'.format(widget)) label.setText(str(self.spectrogram_power_range[widget][-1])) self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def change_palette(self): self.current_color_palette = self.available_palettes[ self.ui.palettes_box.currentIndex()] self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def slider_gain_updated(self, index): slider_gain = self.bands_powers[self.band_slider[index].value()] self.band_label[index].setText(f'{slider_gain}') self.current_slider_gain[index] = slider_gain self.modify_signal() def update_duration(self, duration, widget): self.time_seeker[widget].setMaximum(duration) if duration >= 0: self.total_time[widget].setText(time_stamp(duration)) def update_timestamp(self, position, currentTimeLabel, timeSlider, widget): if position >= 0: currentTimeLabel.setText(time_stamp(position)) timeSlider.blockSignals(True) timeSlider.setValue(position) timeSlider.blockSignals(False) self.playback_position[widget].setRegion( (position / 1000, position / 1000)) minRange, maxRange = self.plot_widget[widget].plotItem.getAxis( 'bottom').range if (position >= maxRange * 1000): self.plot_widget[widget].plotItem.getViewBox().translateBy( (maxRange - minRange), 0) self.synchronize() if (position <= minRange * 1000): self.plot_widget[widget].plotItem.getViewBox().translateBy( -minRange) self.synchronize() def zoomin(self) -> None: self.ui.graph_before.plotItem.getViewBox().scaleBy((0.75, 1.0)) self.synchronize() def zoomout(self) -> None: self.ui.graph_before.plotItem.getViewBox().scaleBy((1.25, 1.0)) self.synchronize() def back(self): self.ui.graph_before.plotItem.getViewBox().translateBy((-0.5, 0.0)) self.synchronize() def forward(self): self.ui.graph_before.plotItem.getViewBox().translateBy((0.5, 0.0)) self.synchronize() def synchronize(self): self.ui.graph_before.plotItem.getViewBox().setXLink( self.ui.graph_after.plotItem) self.spectrogram_time_min, self.spectrogram_time_max = self.ui.graph_before.plotItem.getAxis( 'bottom').range self.plot_spectrogram(self.samples, self.sampling_rate, 'before') self.plot_spectrogram(self.samples_after, self.sampling_rate, 'after') def save_output_wav(self): try: shutil.rmtree('wav') os.mkdir('wav') except: os.mkdir('wav') self.now = datetime.now() self.now = f'{self.now:%Y-%m-%d %H-%M-%S.%f %p}' scipy.io.wavfile.write(f"wav/SBME{self.now}.wav", self.sampling_rate, self.samples_after.astype(np.int16)) path = os.listdir('wav') self.audio_player_after.setMedia( QMediaContent(qtc.QUrl.fromLocalFile(f'wav/{path[0]}'))) self.audio_player_after.positionChanged.connect( lambda position: self.update_timestamp(position, self.ui. current_time_after, self.ui. time_seeker_after, 'after')) self.ui.time_seeker_after.valueChanged.connect( self.audio_player_after.setPosition) def save_session(self): if not self.sampling_rate: qtw.QMessageBox.information(self, 'failed', 'You have to plot a signal first') return try: shutil.rmtree(self.PLOT_DIR) os.mkdir(self.PLOT_DIR) except FileNotFoundError: os.mkdir(self.PLOT_DIR) for index, channel in enumerate(['before', 'after']): exporter = pg.exporters.ImageExporter( self.plot_widget[channel].scene()) exporter.export(f'{self.PLOT_DIR}/plot-{index}.png') self.spectrogram_widget[channel].fig.savefig( f'{self.PLOT_DIR}/spec-{index}.png') pdf = PDF() plots_per_page = pdf.construct(self.PLOT_DIR) for page_images in plots_per_page: pdf.print_page(page_images, self.PLOT_DIR) outFile = qtw.QFileDialog.getSaveFileName(None, 'Save Session', './', "PDF File(*.pdf)") pdf.output(outFile[0], 'F') try: shutil.rmtree(self.PLOT_DIR) except: pass qtw.QMessageBox.information(self, 'success', 'PDF has been created') sampling_rate, samples = scipy.io.wavfile.read( f"wav/SBME{self.now}.wav") outFile = qtw.QFileDialog.getSaveFileName(None, 'Save Session', './', "Wav File(*.wav)") scipy.io.wavfile.write(outFile[0], sampling_rate, samples.astype(np.int16)) qtw.QMessageBox.information(self, 'success', 'Wav has been saved')
class Ui_MainWindow(object): # for stylizing progress bar progress_styleSheet = """ QSlider::groove:horizontal { background: dark; height: 40px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #07406a, stop: 1 #696969); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #696969, stop: 1 #07406a); height: 40px; } QSlider::add-page:horizontal { background: #696969; height: 40px; } QSlider::handle:horizontal { background: #aaa; border: 0px; width: 5px; margin-top: 0px; margin-bottom: 0px; border-radius: 0px; } """ def setupUi(self, MainWindow): MainWindow.setObjectName("Music Player") MainWindow.resize(640, 480) MainWindow.setAcceptDrops(True) self.playlist = QMediaPlaylist() self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self.player.setVolume(20) self.player.setPlaybackRate(jdata['playback']) self.playlist.setPlaybackMode(jdata['curr_playstyle']) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") self.progress = QtWidgets.QSlider(self.centralwidget) self.progress.setOrientation(QtCore.Qt.Horizontal) self.progress.setStyleSheet(self.progress_styleSheet) self.progress.setObjectName("progress") self.progress.setSingleStep(1) self.progress.setPageStep(1) self.gridLayout_2.addWidget(self.progress, 1, 0, 1, 3) self.stop_but = QtWidgets.QPushButton(self.centralwidget) self.stop_but.setObjectName("stop_but") self.gridLayout_2.addWidget(self.stop_but, 0, 2, 1, 1) self.backward_b = QtWidgets.QPushButton(self.centralwidget) self.backward_b.setObjectName("backward") self.gridLayout_2.addWidget(self.backward_b, 0, 0, 1, 1) self.cont_pau = QtWidgets.QPushButton(self.centralwidget) self.cont_pau.setObjectName("cont_pau") self.gridLayout_2.addWidget(self.cont_pau, 0, 1, 1, 1) self.playstyle = QtWidgets.QPushButton(self.centralwidget) self.playstyle.setObjectName("playstyle") self.playstyle.setText("Loop") self.gridLayout_2.addWidget(self.playstyle, 0, 4, 1, 1) self.forward_b = QtWidgets.QPushButton(self.centralwidget) self.forward_b.setObjectName("forward") self.gridLayout_2.addWidget(self.forward_b, 0, 3, 1, 1) self.time_remain = QtWidgets.QLabel(self.centralwidget) self.time_remain.setObjectName("time_remain") self.gridLayout_2.addWidget(self.time_remain, 1, 3, 1, 1) self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.volume = QtWidgets.QLabel(self.centralwidget) self.volume.setAlignment(QtCore.Qt.AlignCenter) self.volume.setObjectName("volume") self.verticalLayout_2.addWidget(self.volume) self.volume_ctrl = QtWidgets.QSlider(self.centralwidget) self.volume_ctrl.setOrientation(QtCore.Qt.Horizontal) self.volume_ctrl.setObjectName("volume_ctrl") self.volume_ctrl.setValue(jdata["volume"]) self.volume_ctrl.setRange(-1, 101) self.volume_ctrl.setSingleStep(1) self.volume_ctrl.setPageStep(1) self.verticalLayout_2.addWidget(self.volume_ctrl) self.gridLayout_2.addLayout(self.verticalLayout_2, 1, 4, 1, 1) self.gridLayout.addLayout(self.gridLayout_2, 1, 0, 1, 1) self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.playing = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) self.playing.setFont(font) self.playing.setAlignment(QtCore.Qt.AlignCenter) self.playing.setObjectName("playing") self.playing.setScaledContents(True) self.playing.setWordWrap(True) self.verticalLayout.addWidget(self.playing) self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) self.verticalLayout_3 = QtWidgets.QVBoxLayout() self.verticalLayout_3.setObjectName("verticalLayout_3") self.song_list = ListWidget(self.centralwidget) self.song_list.setMinimumSize(QtCore.QSize(183, 0)) self.song_list.setAcceptDrops(True) self.song_list.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.song_list.setObjectName("song_list") self.song_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.song_list.setWordWrap(True) self.verticalLayout_3.addWidget(self.song_list) self.gridLayout.addLayout(self.verticalLayout_3, 0, 1, 2, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 632, 25)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuAbout = QtWidgets.QMenu(self.menubar) self.menuAbout.setObjectName("menuAbout") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionOpen = QtWidgets.QAction(MainWindow) self.actionOpen.setObjectName("actionOpen") self.actionLisence_Information = QtWidgets.QAction(MainWindow) self.actionLisence_Information.setObjectName( "actionLisence_Information") self.menuFile.addAction(self.actionOpen) self.menuAbout.addAction(self.actionLisence_Information) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuAbout.menuAction()) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout_2.addItem(spacerItem, 0, 5, 1, 1) self.gridLayout.addLayout(self.gridLayout_2, 1, 0, 1, 1) self.info = QMessageBox() self.info.setWindowTitle("License Information") self.info.setText("MIT License\n\nCopyright (c) 2021 Marganotvke") self.err = QMessageBox() self.err.setWindowTitle("Error Loading File") self.err.setText("Error Loading File!\n\nPlease check file type!") self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.actionOpen.triggered.connect(lambda: self.open_trig()) self.actionLisence_Information.triggered.connect( lambda: self.info.exec_()) self.cont_pau.clicked.connect(lambda: self.cur_playing()) self.volume_ctrl.sliderMoved.connect(lambda: self.change_vol()) self.stop_but.clicked.connect(lambda: self.stop_playing()) self.forward_b.clicked.connect(lambda: self.forward()) self.backward_b.clicked.connect(lambda: self.backward()) self.playstyle.clicked.connect(lambda: self.playlist_style()) self.song_list.dropped.connect(lambda e: self.start_play(e)) self.song_list.itemDoubleClicked.connect( lambda: self.jump_start(self.song_list.currentRow())) self.song_list.model().rowsAboutToBeMoved.connect( lambda e, f, g, h, i: self.re_arr(f, i)) self.song_list.dele.connect(lambda e: self.delete_q(e)) self.player.metaDataAvailableChanged.connect(lambda: self.set_meta()) self.player.stateChanged.connect(lambda e: self.set_state(e)) self.player.positionChanged.connect(lambda e: self.set_pos(e)) self.progress.sliderMoved.connect(lambda e: self.skip_to(e)) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Music Player")) self.stop_but.setText(_translate("MainWindow", "Stop")) self.backward_b.setText(_translate("MainWindow", "Backward")) self.cont_pau.setText(_translate("MainWindow", "Load Song")) self.playstyle.setText( _translate("MainWindow", f"{playstyles[jdata['curr_playstyle']]}")) self.forward_b.setText(_translate("MainWindow", "Forward")) self.time_remain.setText(_translate("MainWindow", "--/--")) self.volume.setText( _translate("MainWindow", f"Volume: {jdata['volume']}%")) self.playing.setText( _translate("MainWindow", "Currently playing: None")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuAbout.setTitle(_translate("MainWindow", "About")) self.actionOpen.setText(_translate("MainWindow", "Open")) self.actionLisence_Information.setText( _translate("MainWindow", "License Information")) self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O")) def re_arr(self, e=None, f=None): f -= 1 if self.song_list.count() == f else 0 media = self.playlist.media(e) self.playlist.removeMedia(e) self.playlist.insertMedia(f, media) def jump_start(self, index=None): if self.playlist.currentIndex() != index: self.playlist.setCurrentIndex(index) self.player.stop() self.start_play() def start_play(self, url=None): if url: print("Emitted from drop event:", url) threading.Thread(target=self.open_file(url)).start() self.player.play() def stop_playing(self): self.player.stop() def cur_playing(self): if self.playlist.isEmpty(): self.open_trig() else: if self.player.state() == 1: self.player.pause() self.cont_pau.setText("Play") else: self.player.play() self.cont_pau.setText("Pause") def forward(self): self.playlist.next() def backward(self): if round(self.player.position() / 1000) >= 5: self.player.setPosition(0) if not self.player.state(): self.start_play() else: self.playlist.previous() def open_trig(self): filename = QFileDialog.getOpenFileName( None, 'Open File', filter= "MPEG-2 (*.mp3);;WAVE Audio (*.wav,*.aif,*.aiff);;MPEG-1/DD/ACC (*.aac);;MIDI (*.mid,*.midi);;Windows Media Audio (*.wma);;Xiph.Org OGG Vorbis (*.ogg);;NeXT SouND (*.snd);;FLAC (*.flac);;All files(*)" ) threading.Thread(target=self.open_file(filename[0])).start() def open_file(self, file_url): url = QUrl.fromLocalFile(file_url) avai = ('.mp3', '.wav', 'ogg', '.aac', '.aif', '.aiff', '.mid', '.midi', '.wma', '.snd', '.flac') if url.url() != '' and not url.fileName().lower().endswith(avai): self.err.exec_() elif url.fileName().lower().endswith(avai): song_name = url.fileName().split(".")[0] self.song_list.addItem(song_name) if self.playlist.isEmpty(): self.playlist.addMedia(QMediaContent(url)) self.cont_pau.setText("Pause") self.start_play() else: self.playlist.addMedia(QMediaContent(url)) def delete_q(self, i): self.playlist.removeMedia(i) self.song_list.takeItem(i) def playlist_style(self): i = self.playlist.playbackMode() i += 1 i *= (i < 5) self.playlist.setPlaybackMode(i) self.playstyle.setText(f"{playstyles[self.playlist.playbackMode()]}") jdata["curr_playstyle"] = self.playlist.playbackMode() print(playstyles[self.playlist.playbackMode()]) def change_vol(self): vol = self.volume_ctrl.value() self.player.setVolume(vol) self.volume.setText(f"Volume: {vol}%") jdata["volume"] = vol def set_pos(self, e): if self.player.isMetaDataAvailable(): t = self.player.duration() dt = datetime.datetime.fromtimestamp( round(self.player.duration() / 1000)).strftime('%M:%S') dt_ct = datetime.datetime.fromtimestamp(round( e / 1000)).strftime('%M:%S') self.thread = threading.Thread( target=self.progress.setValue(round((e / t) * 100))) self.thread.start() self.time_remain.setText(f"{dt_ct}/{dt}") def set_meta(self): if self.player.isMetaDataAvailable(): self.duraiton = self.player.duration() self.progress.setRange(0, 100) self.playing.setText( f"Currently playing: {self.player.currentMedia().canonicalUrl().fileName().split('.')[0]}" ) else: if self.playlist.isEmpty(): self.cont_pau.setText("Load Song") self.time_remain.setText("--/--") def set_state(self, e): if not e: self.playing.setText("Currently playing: None") if self.playlist.isEmpty(): self.cont_pau.setText("Load Song") else: self.cont_pau.setText("Play") else: if self.player.isMetaDataAvailable(): self.playing.setText( f"Currently playing: {self.player.currentMedia().canonicalUrl().fileName().split('.')[0]}" ) def skip_to(self, e): self.player.setPosition(round((e / 100) * self.player.duration()))