class AudioPlayer: def __init__(self): self._widget = None self._player = None self._timer = None def toggle_playback(self, widget): if self._widget == widget: if self._player.get_pause(): plugins.video.video_player.pause_playback() self._player.set_pause(False) self._widget.audio_state = 'play' self._timer = Clock.schedule_interval(self._playback_update, .1) else: self.pause_playback() else: plugins.video.video_player.pause_playback() if self._widget is not None: self.pause_playback() self._widget = widget self._widget.audio_state = 'play' self._player = MediaPlayer(filename=self._widget.audio_source, ff_opts={ 'paused': True, 'ss': self._widget.audio_pos }) Clock.schedule_interval(self._start_playback, .1) def _start_playback(self, dt): if self._player.get_metadata()['duration'] is not None: self._player.set_pause(False) self._timer = Clock.schedule_interval(self._playback_update, .1) return False def pause_playback(self): if self._timer is not None: self._timer.cancel() if self._player is not None and not self._player.get_pause(): self._player.set_pause(True) if self._widget is not None: self._widget.audio_state = 'pause' def _playback_update(self, dt): pts = self._player.get_pts() if pts >= self._widget.audio_length: self._player.set_pause(True) self._player.seek(pts=0, relative=False, accurate=True) self._widget.audio_state = 'pause' self._widget.audio_pos = 0 return False self._widget.audio_pos = pts def update_audio_pos(self, widget, pts): if self._widget == widget and self._player is not None: self._player.seek(pts=pts, relative=False, accurate=True) widget.audio_pos = pts
class Window(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self.Listadd() self.step = 0 self.loop = 1 self.flag = True def Listadd(self): if os.path.isfile('CPlayerlist.txt'): with open('CPlayerlist.txt') as f: for filelist in f: filelist = filelist.strip() self.list.addItem(filelist) def Add(self): filelists, _ = QFileDialog.getOpenFileNames(self, '添加到播放列表', '.', '媒体文件(*)') self.list.addItems(filelists) self.Listchanged() def Remove(self): self.list.takeItem(self.list.currentRow()) self.Listchanged() def Clear(self): self.list.clear() os.remove('CPlayerlist.txt') def Listchanged(self): with open('CPlayerlist.txt', 'w') as f: for i in range(self.list.count()): f.write(self.list.item(i).text() + '\n') def Loop(self): if self.loop == 0: self.loop = 1 self.bloop.setIcon(QIcon(r'img\withloop.png')) self.bloop.setToolTip('循环播放') else: self.loop = 0 self.bloop.setIcon(QIcon(r'img\withoutloop.png')) self.bloop.setToolTip('取消循环') def Play(self): try: if self.flag: self.playitem = self.list.currentItem().text() self.player = MediaPlayer("%s" % self.playitem) self.timer = QTimer() self.timer.start(50) self.timer.timeout.connect(self.Show) self.steptimer = QTimer() self.steptimer.start(1000) self.steptimer.timeout.connect(self.Step) self.flag = False self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停') else: if self.list.currentItem().text() == self.playitem: self.player.toggle_pause() if self.player.get_pause(): self.timer.stop() self.steptimer.stop() self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放') else: self.timer.start() self.steptimer.start() self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停') else: self.step = 0 self.stime.setValue(0) self.playitem = self.list.currentItem().text() self.player = MediaPlayer("%s" % self.playitem) self.timer.start() self.steptimer.start() except: QMessageBox.warning(self, '错误', '找不到要播放的文件!') def Show(self): frame, self.val = self.player.get_frame() self.lmedia.setPixmap(QPixmap('')) if self.val != 'eof' and frame is not None: img, t = frame data = img.to_bytearray()[0] width, height = img.get_size() qimg = QImage(data, width, height, QImage.Format_RGB888) self.lmedia.setPixmap(QPixmap.fromImage(qimg)) self.mediatime = self.player.get_metadata()['duration'] self.stime.setMaximum(int(self.mediatime)) mediamin, mediasec = divmod(self.mediatime, 60) mediahour, mediamin = divmod(mediamin, 60) playmin, playsec = divmod(self.step, 60) playhour, playmin = divmod(playmin, 60) self.ltime.setText( '%02d:%02d:%02d/%02d:%02d:%02d' % (playhour, playmin, playsec, mediahour, mediamin, mediasec)) def Stop(self): if self.flag == False: self.player.close_player() self.timer.stop() self.steptimer.stop() self.step = 0 self.loop = 1 self.flag = True self.stime.setValue(0) self.ltime.setText('') self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放') self.lmedia.setPixmap(QPixmap('')) def Curvol(self): self.curvol = self.svolume.value() def Mute(self): if self.flag == False: if self.player.get_volume() != 0: self.player.set_volume(0) self.bmute.setIcon(QIcon(r'img\withoutvolume.png')) self.bmute.setToolTip('取消静音') else: if self.svolume.value() != 0: self.player.set_volume(self.svolume.value()) else: self.player.set_volume(self.curvol / 100) self.svolume.setValue(self.curvol) self.bmute.setIcon(QIcon(r'img\withvolume.png')) self.bmute.setToolTip('静音') def Volume(self): if self.flag == False: if self.svolume.value() == 0: self.bmute.setIcon(QIcon(r'img\withoutvolume.png')) self.bmute.setToolTip('取消静音') else: self.bmute.setIcon(QIcon(r'img\withvolume.png')) self.bmute.setToolTip('静音') self.player.set_volume(self.svolume.value() / 100) def Step(self): if self.step >= int(self.mediatime): self.step = int(self.mediatime) if self.loop == 0: self.step = 0 self.flag = True self.Play() else: if self.val == 'eof': self.timer.stop() self.steptimer.stop() self.step = 0 self.loop = 1 self.flag = True self.stime.setValue(0) self.player.close_player() self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放') else: self.step += 1 self.stime.setValue(self.step) def Slidechanged(self): self.step = self.stime.value() def Slidemoved(self): self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停') def Fastforward(self): self.step += 10 if self.step >= int(self.mediatime): self.stime.setValue(int(self.mediatime)) self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停') def Fastback(self): self.step -= 10 if self.step <= 0: self.step = 0 self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停')
class VideoPlayer: def __init__(self): self._widget = None self._player = None self._timer = None self._frame = None self._texture = None self._trigger = Clock.create_trigger(self._redraw) def toggle_playback(self, widget): if self._widget == widget: if self._player.get_pause(): plugins.audio.audio_player.pause_playback() self._player.set_pause(False) self._widget.video_state = 'play' Clock.schedule_once(self._next_frame) else: self.pause_playback() else: plugins.audio.audio_player.pause_playback() if self._widget is not None: self.pause_playback() self._widget = widget self._widget.video_state = 'play' self._texture = None self._player = MediaPlayer(filename=self._widget.video_source, ff_opts={ 'paused': True, 'ss': self._widget.video_pos }) Clock.schedule_interval(self._start_playback, .1) def _start_playback(self, dt): if self._player.get_metadata()['duration'] is None: return if self._player.get_pause(): self._player.set_pause(False) Clock.schedule_once(self._next_frame, 0) return False def pause_playback(self): if self._timer is not None: self._timer.cancel() if self._player is not None: self._player.set_pause(True) self._frame = None self._texture = None if self._widget is not None: self._widget.video_state = 'pause' def update_video_pos(self, widget, pts): if self._widget == widget and self._player is not None: self._player.seek(pts=pts, relative=False, accurate=True) widget.video_pos = pts def _next_frame(self, dt): frame, val = self._player.get_frame() if val == 'eof': self._player.set_pause(True) self._player.seek(pts=0, relative=False, accurate=True) self._widget.video_image.texture = self._widget.video_cover_image_texture self._widget.video_state = 'pause' self._widget.video_pos = 0 elif val == 'paused': return elif frame is None: Clock.schedule_once(self._next_frame, 1 / 100) else: val = val if val else 1 / 30 self._frame = frame self._trigger() Clock.schedule_once(self._next_frame, val) def _redraw(self, dt): if self._player.get_pause() is None or self._frame is None: return img, pts = self._frame if self._texture is None: self._texture = Texture.create(size=img.get_size(), colorfmt='rgb') self._texture.flip_vertical() self._texture.blit_buffer(img.to_memoryview()[0]) self._widget.video_image.texture = None self._widget.video_image.texture = self._texture self._widget.video_pos = pts
class Track: def __init__(self, name=None, track_id=None): # this block of code determines the attribute to be used to construct the object # i.e. wether to construct based on a search term of directly from an ID self.__type = None for attribute in [name, track_id]: if attribute is not None: self.__type = [ key for key, value in locals().items() if value == attribute ][0] if self.__type is None: raise NoAttributesSupplied self.track_id = track_id self.title = name self.fetch_type = None print(':::fetching url') html = requests.get("https://www.youtube.com/results?search_query=" + self.title.replace(' ', '+')) video = pafy.new( re.findall(r"watch\?v=(\S{11})", str(html.content))[0]) best_stream = video.getbestaudio(preftype="wav", ftypestrict=False) self.ext = '.' + best_stream.extension self.title = filter_search_term(video.title).strip() self.url = best_stream.url self.filename = self.title + self.ext print('video title:::', filter_search_term(video.title)) # dont repeat if all the data's been already fetched if not self.fetch_type is None: return if self.__type == 'track_id': track = spotify.track(self.track_id) elif self.__type == 'name': track_search = spotify.search(self.title, type='track', limit=1) if len(track_search['tracks']['items']) <= 0: print( ':::track not available from spotify, doing a minimal fetch' ) if '-' in self.title: self.artists = [self.title.split('-')[0].strip()] else: self.artists = None self.__artists_names = None self.album = None self.track_id = None self.genres = None self.fetch_type = 'minimal' return else: track = track_search['tracks']['items'][0] self.track_id = track['id'] self.artists = [] self.__artists_names = [] for artist in track['artists']: self.artists.append(Artist(artist_id=artist['id'])) self.__artists_names.append(artist['name']) self.genres = [] for artist in self.artists: for genre in artist.genres: self.genres.append(genre) self.album = Album(album_id=track['album']['id']) self.fetch_type = 'full' print(':::fetched') def send_notification(self): print(":::sending notif") # send notification # fetch metadata for the track if it has'nt already been fetched if self.fetch_type is None: self.fetch_metadata() message = '' if not self.__artists_names is None: message = self.__artists_names if len(message) == 1: pass elif len(message) == 2: message.insert(1, ' and ') else: increment = 1 for i in range(len(message)): if not i == len(message) - 1: insert_index = i + increment message.insert(insert_index, ' and ') increment += insert_index + 1 message = ''.join(message) if not self.album is None: message += f'\nfrom album {self.album.name}' notification.notify( title=self.title, message=message, app_icon=r'C:\users\gadit\downloads\music_icon0.ico', app_name='M E L O D I N E', timeout=10, toast=False) def download(self, custom=None, no_part=True): global audio_downloader audio_downloader = YoutubeDL({ #'buffersize': 512, #'http_chunk_size': 256, 'audioformat': 'wav', 'format': 'bestaudio', 'outtmpl': self.title + self.ext, 'extractaudio': True, 'retries': 5, 'continuedl': True, 'nopart': no_part, 'hls_prefer_native': True, 'quiet': True }) audio_downloader.extract_info(self.url) def play(self): self.fetch_metadata() self.download(no_part=True) print('::: downloaded') threading._start_new_thread(self.send_notification, ()) self.player = MediaPlayer(self.filename) time.sleep(0.5) print('::: playing') last_pts = 0 updated_pts = 0 while True: updated_pts = int(float(str(self.player.get_pts())[:3])) - 3 print(':::updated', updated_pts) # print(player.get_pts()) while self.player.get_pause(): time.sleep(0.5) if updated_pts == last_pts: self.player.toggle_pause() print("---buffered out, pausing") time.sleep(1) self.player.toggle_pause() if int(float(str(self.player.get_pts())[:3])) - 3 == int( float(str( self.player.get_metadata()['duration'])[:3])) - 3: print(':::breaking') self.player.toggle_pause() self.player.close_player() last_pts = updated_pts time.sleep(1) print(':::finished playing')
class Window(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self.Listadd() self.step = 0 self.loop = 1 self.tag = self.flag = self.listtag = self.fulltag = True screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move(int((screen.width() - size.width()) / 2), int((screen.height() - size.height()) / 2)) def keyPressEvent(self, event): if event.key() == Qt.Key_P: self.Listhide() if event.key() == Qt.Key_T: self.Fastback() if event.key() == Qt.Key_L: self.Loop() if event.key() == Qt.Key_Space: self.Play() if event.key() == Qt.Key_S: self.Stop() if event.key() == Qt.Key_F: self.Full() if event.key() == Qt.Key_J: self.Fastforward() if event.key() == Qt.Key_M: self.Mute() if event.key() == Qt.Key_A: self.svolume.setValue(self.svolume.value() + 1) if event.key() == Qt.Key_R: self.svolume.setValue(self.svolume.value() - 1) def eventFilter(self, sender, event): if (event.type() == event.ChildRemoved): self.Moved() return False def Listmenu(self, position): lm = QMenu() addact = QAction("添加到播放列表", self, triggered=self.Add) removeact = QAction("从播放列表移除", self, triggered=self.Remove) renameact = QAction('重命名', self, triggered=self.Rename) clearact = QAction('清空播放列表', self, triggered=self.Clear) saveact = QAction('保存当前播放列表', self, triggered=self.Saved) lm.addAction(addact) if self.list.itemAt(position): lm.addAction(removeact) lm.addAction(renameact) lm.addAction(clearact) lm.addAction(saveact) lm.exec_(self.list.mapToGlobal(position)) def Listadd(self): self.l = [] self.list.installEventFilter(self) if os.path.isfile('CPlayerlist.txt'): with open('CPlayerlist.txt') as f: for i in f: i = i.strip() name = i[0:i.find(',')] filelist = i[i.find(',') + 1:len(i)] self.list.addItem(name) self.l.append(filelist) def Add(self): filelists, _ = QFileDialog.getOpenFileNames(self, '添加到播放列表', '.', '媒体文件(*)') for filelist in filelists: name = filelist[filelist.rfind('/') + 1:filelist.rfind('.')] self.list.addItem(name) self.l.append(filelist) def Remove(self): ltmp = [] for i in self.list.selectedIndexes(): ltmp.append(i.row()) ltmp.sort(reverse=True) for j in ltmp: self.list.takeItem(j) self.l.pop(j) def Rename(self): item = self.list.item(self.list.currentRow()) item.setFlags(item.flags() | Qt.ItemIsEditable) self.list.editItem(item) def Clear(self): self.l = [] self.list.clear() if os.path.isfile('CPlayerlist.txt'): os.remove('CPlayerlist.txt') def Drag(self): self.tmp1 = [] self.tmp2 = self.l[:] for i in range(self.list.count()): self.tmp1.append(self.list.item(i).text()) def Moved(self): for i in range(self.list.count()): if self.list.item(i).text() == self.tmp1[i]: continue else: self.l[i] = self.tmp2[self.tmp1.index( self.list.item(i).text())] def Saved(self): with open('CPlayerlist.txt', 'w') as f: for i in range(self.list.count()): f.write('%s,%s\n' % (self.list.item(i).text(), self.l[i])) QMessageBox.information(self, '保存', '播放列表保存成功!') def Listhide(self): if self.listtag: self.frame.hide() self.listtag = False else: self.frame.show() self.listtag = True def Loop(self): if self.loop == 0: self.loop = 1 self.bloop.setIcon(QIcon(r'img\withloop.png')) self.bloop.setToolTip('循环播放,快捷键“l”') else: self.loop = 0 self.bloop.setIcon(QIcon(r'img\withoutloop.png')) self.bloop.setToolTip('取消循环,快捷键“l”') def Play(self): if self.flag: try: self.playitem = self.l[self.list.currentRow()] if os.path.isfile("%s" % self.playitem): self.player = MediaPlayer("%s" % self.playitem) self.timer = QTimer() self.timer.start(50) self.timer.timeout.connect(self.Show) self.steptimer = QTimer() self.steptimer.start(1000) self.steptimer.timeout.connect(self.Step) self.flag = False self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') else: QMessageBox.warning(self, '错误', '找不到要播放的文件!') except: QMessageBox.warning(self, '错误', '找不到要播放的文件!') else: if self.l[self.list.currentRow()] == self.playitem: self.player.toggle_pause() if self.player.get_pause(): self.timer.stop() self.steptimer.stop() self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放,快捷键“Space”') else: self.timer.start() self.steptimer.start() self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') else: self.playitem = self.l[self.list.currentRow()] if os.path.isfile("%s" % self.playitem): self.step = 0 self.stime.setValue(0) self.player = MediaPlayer("%s" % self.playitem) self.timer.start() self.steptimer.start() self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') else: QMessageBox.warning(self, '错误', '找不到要播放的文件!') def Show(self): if self.tag: self.player.set_volume(self.svolume.value() / 100) else: self.player.set_volume(0) frame, self.val = self.player.get_frame() self.lmedia.setPixmap(QPixmap('')) if self.val != 'eof' and frame is not None: img, t = frame data = img.to_bytearray()[0] width, height = img.get_size() qimg = QImage(data, width, height, QImage.Format_RGB888) self.lmedia.setPixmap(QPixmap.fromImage(qimg)) self.mediatime = self.player.get_metadata()['duration'] if self.mediatime: self.stime.setMaximum(int(self.mediatime)) mediamin, mediasec = divmod(self.mediatime, 60) mediahour, mediamin = divmod(mediamin, 60) playmin, playsec = divmod(self.step, 60) playhour, playmin = divmod(playmin, 60) self.ltime.setText( '%02d:%02d:%02d/%02d:%02d:%02d' % (playhour, playmin, playsec, mediahour, mediamin, mediasec)) def Stop(self): if self.flag == False: self.player.close_player() self.timer.stop() self.steptimer.stop() self.step = 0 self.loop = 1 self.flag = True self.stime.setValue(0) self.ltime.setText('') self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放,快捷键“Space”') self.lmedia.setPixmap(QPixmap('')) def Full(self): if self.fulltag: self.frame.hide() self.frame_2.hide() self.showFullScreen() self.bfull.setIcon(QIcon(r'img\exitfullscreen.png')) self.bfull.setToolTip('退出全屏,快捷键“f”') self.fulltag = False else: self.frame.show() self.frame_2.show() self.showNormal() self.bfull.setIcon(QIcon(r'img\expandfullscreen.png')) self.bfull.setToolTip('全屏,快捷键“f”') self.fulltag = True def Curvol(self): self.curvol = self.svolume.value() def Mute(self): if self.flag == False: if self.player.get_volume() != 0: self.player.set_volume(0) self.bmute.setIcon(QIcon(r'img\withoutvolume.png')) self.bmute.setToolTip('取消静音,快捷键“m”') self.tag = False else: if self.svolume.value() != 0: self.player.set_volume(self.svolume.value() / 100) else: self.player.set_volume(self.curvol / 100) self.svolume.setValue(self.curvol) self.bmute.setIcon(QIcon(r'img\withvolume.png')) self.bmute.setToolTip('静音,快捷键“m”') self.tag = True def Volume(self): if self.flag == False: if self.svolume.value() == 0: self.bmute.setIcon(QIcon(r'img\withoutvolume.png')) self.bmute.setToolTip('取消静音,快捷键“m”') else: self.bmute.setIcon(QIcon(r'img\withvolume.png')) self.bmute.setToolTip('静音,快捷键“m”') self.player.set_volume(self.svolume.value() / 100) def Step(self): if self.step >= int(self.mediatime): self.step = int(self.mediatime) if self.loop == 0: self.step = 0 self.stime.setValue(0) self.flag = True self.Play() else: if self.val == 'eof': self.Stop() else: self.step += 1 self.stime.setValue(self.step) def Slidechanged(self): self.step = self.stime.value() def Slidemoved(self): if self.flag == False: self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') def Fastforward(self): if self.flag == False: self.step += 10 if self.step >= int(self.mediatime): self.stime.setValue(int(self.mediatime)) self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') def Fastback(self): if self.flag == False: self.step -= 10 if self.step <= 0: self.step = 0 self.stime.setValue(0) self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”')
class Window(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self.Listadd() self.step = 0 self.loop = 1 self.tag = True self.flag = True self.hidetag = True screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move(int((screen.width() - size.width()) / 2), int((screen.height() - size.height()) / 2)) def keyPressEvent(self, event): if event.key() == Qt.Key_P: self.Listhide() if event.key() == Qt.Key_T: self.Fastback() if event.key() == Qt.Key_L: self.Loop() if event.key() == Qt.Key_Space: self.Play() if event.key() == Qt.Key_S: self.Stop() if event.key() == Qt.Key_F: self.Full() if event.key() == Qt.Key_J: self.Fastforward() if event.key() == Qt.Key_M: self.Mute() if event.key() == Qt.Key_A: self.svolume.setValue(self.svolume.value() + 1) if event.key() == Qt.Key_R: self.svolume.setValue(self.svolume.value() - 1) def Listadd(self): if os.path.isfile('CPlayerlist.txt'): with open('CPlayerlist.txt') as f: for filelist in f: filelist = filelist.strip() self.list.addItem(filelist) def Add(self): filelists, _ = QFileDialog.getOpenFileNames(self, '添加到播放列表', '.', '媒体文件(*)') self.list.addItems(filelists) self.Listchanged() def Remove(self): self.list.takeItem(self.list.currentRow()) self.Listchanged() def Clear(self): self.list.clear() os.remove('CPlayerlist.txt') def Listchanged(self): with open('CPlayerlist.txt', 'w') as f: for i in range(self.list.count()): f.write(self.list.item(i).text() + '\n') def Listhide(self): if self.hidetag: self.frame.hide() self.hidetag = False else: self.frame.show() self.hidetag = True def Loop(self): if self.loop == 0: self.loop = 1 self.bloop.setIcon(QIcon(r'img\withloop.png')) self.bloop.setToolTip('循环播放,快捷键“l”') else: self.loop = 0 self.bloop.setIcon(QIcon(r'img\withoutloop.png')) self.bloop.setToolTip('取消循环,快捷键“l”') def Play(self): if self.flag: try: self.playitem = self.list.currentItem().text() if os.path.isfile("%s" % self.playitem): self.player = MediaPlayer("%s" % self.playitem) self.timer = QTimer() self.timer.start(50) self.timer.timeout.connect(self.Show) self.steptimer = QTimer() self.steptimer.start(1000) self.steptimer.timeout.connect(self.Step) self.flag = False self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') else: QMessageBox.warning(self, '错误', '找不到要播放的文件!') except: QMessageBox.warning(self, '错误', '找不到要播放的文件!') else: if self.list.currentItem().text() == self.playitem: self.player.toggle_pause() if self.player.get_pause(): self.timer.stop() self.steptimer.stop() self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放,快捷键“Space”') else: self.timer.start() self.steptimer.start() self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') else: self.playitem = self.list.currentItem().text() if os.path.isfile("%s" % self.playitem): self.step = 0 self.stime.setValue(0) self.player = MediaPlayer("%s" % self.playitem) self.timer.start() self.steptimer.start() else: QMessageBox.warning(self, '错误', '找不到要播放的文件!') def Show(self): if self.tag: self.player.set_volume(self.svolume.value() / 100) else: self.player.set_volume(0) frame, self.val = self.player.get_frame() self.lmedia.setPixmap(QPixmap('')) if self.val != 'eof' and frame is not None: img, t = frame data = img.to_bytearray()[0] width, height = img.get_size() qimg = QImage(data, width, height, QImage.Format_RGB888) self.lmedia.setPixmap(QPixmap.fromImage(qimg)) self.mediatime = self.player.get_metadata()['duration'] if self.mediatime: self.stime.setMaximum(int(self.mediatime)) mediamin, mediasec = divmod(self.mediatime, 60) mediahour, mediamin = divmod(mediamin, 60) playmin, playsec = divmod(self.step, 60) playhour, playmin = divmod(playmin, 60) self.ltime.setText( '%02d:%02d:%02d/%02d:%02d:%02d' % (playhour, playmin, playsec, mediahour, mediamin, mediasec)) def Stop(self): if self.flag == False: self.player.close_player() self.timer.stop() self.steptimer.stop() self.step = 0 self.loop = 1 self.flag = True self.stime.setValue(0) self.ltime.setText('') self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放,快捷键“Space”') self.lmedia.setPixmap(QPixmap('')) def Full(self): if self.hidetag: self.setWindowFlags(Qt.FramelessWindowHint) rect = QApplication.desktop().geometry() self.setGeometry(rect) self.frame.hide() self.frame_2.hide() self.show() self.bfull.setIcon(QIcon(r'img\exitfullscreen.png')) self.bfull.setToolTip('退出全屏,快捷键“f”') self.hidetag = False else: self.setWindowFlags(Qt.Widget) self.setGeometry(0, 0, 1144, 705) self.frame.show() self.frame_2.show() screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move(int((screen.width() - size.width()) / 2), int((screen.height() - size.height()) / 2)) self.show() self.bfull.setIcon(QIcon(r'img\expandfullscreen.png')) self.bfull.setToolTip('全屏,快捷键“f”') self.hidetag = True def Curvol(self): self.curvol = self.svolume.value() def Mute(self): if self.flag == False: if self.player.get_volume() != 0: self.player.set_volume(0) self.bmute.setIcon(QIcon(r'img\withoutvolume.png')) self.bmute.setToolTip('取消静音,快捷键“m”') self.tag = False else: if self.svolume.value() != 0: self.player.set_volume(self.svolume.value() / 100) else: self.player.set_volume(self.curvol / 100) self.svolume.setValue(self.curvol) self.bmute.setIcon(QIcon(r'img\withvolume.png')) self.bmute.setToolTip('静音,快捷键“m”') self.tag = True def Volume(self): if self.flag == False: if self.svolume.value() == 0: self.bmute.setIcon(QIcon(r'img\withoutvolume.png')) self.bmute.setToolTip('取消静音,快捷键“m”') else: self.bmute.setIcon(QIcon(r'img\withvolume.png')) self.bmute.setToolTip('静音,快捷键“m”') self.player.set_volume(self.svolume.value() / 100) def Step(self): if self.step >= int(self.mediatime): self.step = int(self.mediatime) if self.loop == 0: self.step = 0 self.flag = True self.Play() else: if self.val == 'eof': self.timer.stop() self.steptimer.stop() self.step = 0 self.loop = 1 self.flag = True self.stime.setValue(0) self.player.close_player() self.bplay.setIcon(QIcon(r'img\play.png')) self.bplay.setToolTip('播放,快捷键“Space”') else: self.step += 1 self.stime.setValue(self.step) def Slidechanged(self): self.step = self.stime.value() def Slidemoved(self): self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') def Fastforward(self): if self.flag == False: self.step += 10 if self.step >= int(self.mediatime): self.stime.setValue(int(self.mediatime)) self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”') def Fastback(self): if self.flag == False: self.step -= 10 if self.step <= 0: self.step = 0 self.timer.start() self.steptimer.start() self.player = MediaPlayer("%s" % self.playitem, ff_opts={'ss': self.step}) self.bplay.setIcon(QIcon(r'img\pause.png')) self.bplay.setToolTip('暂停,快捷键“Space”')
class PlayerThread(QThread): image_sig = pyqtSignal(QtGui.QImage) status_sig = pyqtSignal(bool) progress_sig = pyqtSignal(float) def __init__(self, parent): super().__init__(parent) self.label = parent.label self.image_sig.connect(parent.set_image) self.status_sig.connect(parent.set_status) self.progress_sig.connect(parent.set_progress) self.player = None self.duration = None self.progress = 0 self.ratio_mode = Qt.KeepAspectRatio self.config = {} def set_video_name(self, video_name): if self.player is not None: self.player.close_player() self.player = MediaPlayer(video_name) self.status_sig.emit(self.player.get_pause()) self.start() def set_config(self, config): self.config = config def close(self): if self.player is not None: self.player.close_player() self.quit() def pause(self): if self.player is not None: self.player.set_pause(True) self.status_sig.emit(True) def toggle_pause(self): if self.player is not None: self.player.toggle_pause() self.status_sig.emit(self.player.get_pause()) def next_prev(self, is_forward): if self.player is not None: chunk_position = self.find_chunk(self.progress) if is_forward: if chunk_position < self.config['total'] - 1: chunk_position += 1 self.player.seek(self.config['chunks'][chunk_position][0] / 1000, relative=False, accurate=False) else: if chunk_position > 0: chunk_position -= 1 self.player.seek(self.config['chunks'][chunk_position][0] / 1000, relative=False, accurate=False) def find_chunk(self, pts): if self.config: pts_ms = int(1000 * pts) front = 0 rear = self.config['total'] - 1 chunks = self.config['chunks'] while front != rear: middle = (front + rear) // 2 if pts_ms > chunks[middle][0]: if pts_ms < chunks[middle + 1][0]: break else: front = middle + 1 else: rear = middle return (front + rear) // 2 else: return 0 def seek(self, ratio): if self.duration is not None: pts = ratio * self.duration self.player.seek(pts, relative=False, accurate=False) def image_stretch(self, is_stretch): if is_stretch: self.ratio_mode = Qt.IgnoreAspectRatio else: self.ratio_mode = Qt.KeepAspectRatio def run(self): val = '' while val != 'eof': frame, val = self.player.get_frame() if self.duration is None: self.duration = self.player.get_metadata()['duration'] if val != 'eof' and frame is not None: img, t = frame if img is not None: byte = img.to_bytearray()[0] width, height = img.get_size() convert_to_qt_format = QtGui.QImage(byte, width, height, QImage.Format_RGB888) p = convert_to_qt_format.scaled(self.label.width(), self.label.height(), self.ratio_mode) self.image_sig.emit(p) self.progress = t if self.duration is not None: self.progress_sig.emit(t / self.duration) time.sleep(val)
class FFPyPlayer(BaseMoviePlayer): """Interface class for the FFPyPlayer library for use with `MovieStim`. This class also serves as the reference implementation for classes which interface with movie codec libraries for use with `MovieStim`. Creating new player classes which closely replicate the behaviour of this one should allow them to smoothly plug into `MovieStim`. """ _movieLib = 'ffpyplayer' def __init__(self, parent): self._filename = u"" self.parent = parent # handle to `ffpyplayer` self._handle = None # thread for reading frames asynchronously self._tStream = None # data from stream thread self._lastFrame = NULL_MOVIE_FRAME_INFO self._frameIndex = -1 self._loopCount = 0 self._metadata = None # metadata from the stream self._lastPlayerOpts = DEFAULT_FF_OPTS.copy() # options from the parent if self.parent.loop: # infinite loop self._lastPlayerOpts['loop'] = 0 else: self._lastPlayerOpts['loop'] = 1 # play once if hasattr(self.parent, '_noAudio'): self._lastPlayerOpts['an'] = self.parent._noAudio # status flags self._status = NOT_STARTED def start(self, log=True): """Initialize and start the decoder. This method will return when a valid frame is made available. """ # clear queued data from previous streams self._lastFrame = None self._frameIndex = -1 # open the media player self._handle = MediaPlayer(self._filename, ff_opts=self._lastPlayerOpts) self._handle.set_pause(True) # Pull the first frame to get metadata. NB - `_enqueueFrame` should be # able to do this but the logic in there depends on having access to # metadata first. That may be rewritten at some point to reduce all of # this to just a single `_enqeueFrame` call. # self._status = NOT_STARTED # hand off the player interface to the thread self._tStream = MovieStreamThreadFFPyPlayer(self._handle) self._tStream.begin() # make sure we have metadata self.update() def load(self, pathToMovie): """Load a movie file from disk. Parameters ---------- pathToMovie : str Path to movie file, stream (URI) or camera. Must be a format that FFMPEG supports. """ # set the file path self._filename = pathToString(pathToMovie) # Check if the player is already started. Close it and load a new # instance if so. if self._handle is not None: # player already started # make sure it's the correct type if not isinstance(self._handle, MediaPlayer): raise TypeError( 'Incorrect type for `FFMovieStim._player`, expected ' '`ffpyplayer.player.MediaPlayer`. Got type `{}` ' 'instead.'.format(type(self._handle).__name__)) # close the player and reset self.unload() # self._selectWindow(self.win) # free buffers here !!! self.start() self._status = NOT_STARTED def unload(self): """Unload the video stream and reset. """ self._handle.close_player() self._filename = u"" self._frameIndex = -1 self._handle = None # reset @property def handle(self): """Handle to the `MediaPlayer` object exposed by FFPyPlayer. If `None`, no media player object has yet been initialized. """ return self._handle @property def isLoaded(self): return self._handle is not None @property def metadata(self): """Most recent metadata (`MovieMetadata`). """ return self.getMetadata() def getMetadata(self): """Get metadata from the movie stream. Returns ------- MovieMetadata Movie metadata object. If no movie is loaded, `NULL_MOVIE_METADATA` is returned. At a minimum, fields `duration`, `size`, and `frameRate` are populated if a valid movie has been previously loaded. """ self._assertMediaPlayer() metadata = self._metadata # write metadata to the fields of a `MovieMetadata` object toReturn = MovieMetadata(mediaPath=self._filename, title=metadata['title'], duration=metadata['duration'], frameRate=metadata['frame_rate'], size=metadata['src_vid_size'], pixelFormat=metadata['src_pix_fmt'], movieLib=self._movieLib, userData=None) return toReturn def _assertMediaPlayer(self): """Ensure the media player instance is available. Raises a `RuntimeError` if no movie is loaded. """ if isinstance(self._handle, MediaPlayer): return # nop if we're good raise RuntimeError( "Calling this class method requires a successful call to " "`load` first.") @property def status(self): """Player status flag (`int`). """ return self._status @property def isPlaying(self): """`True` if the video is presently playing (`bool`).""" # Status flags as properties are pretty useful for users since they are # self documenting and prevent the user from touching the status flag # attribute directly. # return self.status == PLAYING @property def isNotStarted(self): """`True` if the video has not be started yet (`bool`). This status is given after a video is loaded and play has yet to be called. """ return self.status == NOT_STARTED @property def isStopped(self): """`True` if the movie has been stopped. """ return self.status == STOPPED @property def isPaused(self): """`True` if the movie has been paused. """ self._assertMediaPlayer() return self._handle.get_pause() @property def isFinished(self): """`True` if the video is finished (`bool`). """ # why is this the same as STOPPED? return self.status == FINISHED def play(self, log=False): """Start or continue a paused movie from current position. Parameters ---------- log : bool Log the play event. Returns ------- int or None Frame index playback started at. Should always be `0` if starting at the beginning of the video. Returns `None` if the player has not been initialized. """ self._assertMediaPlayer() self._tStream.play() self._status = PLAYING def stop(self, log=False): """Stop the current point in the movie (sound will stop, current frame will not advance). Once stopped the movie cannot be restarted - it must be loaded again. Use `pause()` instead if you may need to restart the movie. Parameters ---------- log : bool Log the stop event. """ if self._tStream is None: raise RuntimeError("Cannot close stream, not opened yet.") # close the thread if not self._tStream.isDone(): self._tStream.shutdown() self._tStream.join() # wait until thread exits self._tStream = None if self._handle is not None: self._handle.close_player() self._handle = None # reset def pause(self, log=False): """Pause the current point in the movie. The image of the last frame will persist on-screen until `play()` or `stop()` are called. Parameters ---------- log : bool Log this event. """ self._assertMediaPlayer() self._tStream.pause() return False def seek(self, timestamp, log=False): """Seek to a particular timestamp in the movie. Parameters ---------- timestamp : float Time in seconds. log : bool Log the seek event. """ raise NotImplementedError( "This feature is not available for the current backend.") def rewind(self, seconds=5, log=False): """Rewind the video. Parameters ---------- seconds : float Time in seconds to rewind from the current position. Default is 5 seconds. log : bool Log this event. Returns ------- float Timestamp after rewinding the video. """ raise NotImplementedError( "This feature is not available for the current backend.") def fastForward(self, seconds=5, log=False): """Fast-forward the video. Parameters ---------- seconds : float Time in seconds to fast forward from the current position. Default is 5 seconds. log : bool Log this event. Returns ------- float Timestamp at new position after fast forwarding the video. """ raise NotImplementedError( "This feature is not available for the current backend.") def replay(self, autoStart=True, log=False): """Replay the movie from the beginning. Parameters ---------- autoStart : bool Start playback immediately. If `False`, you must call `play()` afterwards to initiate playback. log : bool Log this event. Notes ----- * This tears down the current media player instance and creates a new one. Similar to calling `stop()` and `loadMovie()`. Use `seek(0.0)` if you would like to restart the movie without reloading. """ lastMovieFile = self._filename self.stop() # stop the movie # self._autoStart = autoStart self.load(lastMovieFile) # will play if auto start # -------------------------------------------------------------------------- # Audio stream control methods # @property def muted(self): """`True` if the stream audio is muted (`bool`). """ return self._handle.get_mute() # thread-safe? @muted.setter def muted(self, value): self._tStream.setMute(value) def volumeUp(self, amount): """Increase the volume by a fixed amount. Parameters ---------- amount : float or int Amount to increase the volume relative to the current volume. """ self._assertMediaPlayer() # get the current volume from the player self.volume = self.volume + amount return self.volume def volumeDown(self, amount): """Decrease the volume by a fixed amount. Parameters ---------- amount : float or int Amount to decrease the volume relative to the current volume. """ self._assertMediaPlayer() # get the current volume from the player self.volume = self.volume - amount return self.volume @property def volume(self): """Volume for the audio track for this movie (`int` or `float`). """ self._assertMediaPlayer() return self._handle.get_volume() # thread-safe? @volume.setter def volume(self, value): self._assertMediaPlayer() self._tStream.setVolume(max(min(value, 1.0), 0.0)) @property def loopCount(self): """Number of loops completed since playback started (`int`). This value is reset when either `stop` or `loadMovie` is called. """ return self._loopCount # -------------------------------------------------------------------------- # Timing related methods # # The methods here are used to handle timing, such as converting between # movie and experiment timestamps. # @property def pts(self): """Presentation timestamp for the current movie frame in seconds (`float`). The value for this either comes from the decoder or some other time source. This should be synchronized to the start of the audio track. A value of `-1.0` is invalid. """ if self._handle is None: return -1.0 return self._lastFrame.absTime def getStartAbsTime(self): """Get the absolute experiment time in seconds the movie starts at (`float`). This value reflects the time which the movie would have started if played continuously from the start. Seeking and pausing the movie causes this value to change. Returns ------- float Start time of the movie in absolute experiment time. """ self._assertMediaPlayer() return getTime() - self._lastFrame.absTime def movieToAbsTime(self, movieTime): """Convert a movie timestamp to absolute experiment timestamp. Parameters ---------- movieTime : float Movie timestamp to convert to absolute experiment time. Returns ------- float Timestamp in experiment time which is coincident with the provided `movieTime` timestamp. The returned value should usually be precise down to about five decimal places. """ self._assertMediaPlayer() # type checks on parameters if not isinstance(movieTime, float): raise TypeError( "Value for parameter `movieTime` must have type `float` or " "`int`.") return self.getStartAbsTime() + movieTime def absToMovieTime(self, absTime): """Convert absolute experiment timestamp to a movie timestamp. Parameters ---------- absTime : float Absolute experiment time to convert to movie time. Returns ------- float Movie time referenced to absolute experiment time. If the value is negative then provided `absTime` happens before the beginning of the movie from the current time stamp. The returned value should usually be precise down to about five decimal places. """ self._assertMediaPlayer() # type checks on parameters if not isinstance(absTime, float): raise TypeError( "Value for parameter `absTime` must have type `float` or " "`int`.") return absTime - self.getStartAbsTime() def movieTimeFromFrameIndex(self, frameIdx): """Get the movie time a specific a frame with a given index is scheduled to be presented. This is used to handle logic for seeking through a video feed (if permitted by the player). Parameters ---------- frameIdx : int Frame index. Negative values are accepted but they will return negative timestamps. """ self._assertMediaPlayer() return frameIdx * self._metadata.frameInterval def frameIndexFromMovieTime(self, movieTime): """Get the frame index of a given movie time. Parameters ---------- movieTime : float Timestamp in movie time to convert to a frame index. Returns ------- int Frame index that should be presented at the specified movie time. """ self._assertMediaPlayer() return math.floor(movieTime / self._metadata.frameInterval) @property def isSeekable(self): """Is seeking allowed for the video stream (`bool`)? If `False` then `frameIndex` will increase monotonically. """ return False # fixed for now @property def frameInterval(self): """Duration a single frame is to be presented in seconds (`float`). This is derived from the framerate information in the metadata. If not movie is loaded, the returned value will be invalid. """ return self.metadata.frameInterval @property def frameIndex(self): """Current frame index (`int`). Index of the current frame in the stream. If playing from a file or any other seekable source, this value may not increase monotonically with time. A value of `-1` is invalid, meaning either the video is not started or there is some issue with the stream. """ return self._lastFrame.frameIndex def getPercentageComplete(self): """Provides a value between 0.0 and 100.0, indicating the amount of the movie that has been already played (`float`). """ duration = self.metadata.duration return (self.pts / duration) * 100.0 # -------------------------------------------------------------------------- # Methods for getting video frames from the encoder # def _enqueueFrame(self): """Grab the latest frame from the stream. Returns ------- bool `True` if a frame has been enqueued. Returns `False` if the camera is not ready or if the stream was closed. """ self._assertMediaPlayer() # If the queue is empty, the decoder thread has not yielded a new frame # since the last call. enqueuedFrame = self._tStream.getRecentFrame() if enqueuedFrame is None: return False # Unpack the data we got back ... # Note - Bit messy here, we should just hold onto the `enqueuedFrame` # instance and reference its fields from properties. Keeping like this # for now. frameImage = enqueuedFrame.frameImage streamStatus = enqueuedFrame.streamStatus self._metadata = enqueuedFrame.metadata self.parent.status = self._status = streamStatus.status self._frameIndex = streamStatus.frameIndex self._loopCount = streamStatus.loopCount # status information self._streamTime = streamStatus.streamTime # stream time for the camera # if we have a new frame, update the frame information videoBuffer = frameImage.to_bytearray()[0] videoFrameArray = np.frombuffer(videoBuffer, dtype=np.uint8) # provide the last frame self._lastFrame = MovieFrame( frameIndex=self._frameIndex, absTime=self._streamTime, displayTime=self.metadata.frameInterval, size=frameImage.get_size(), colorData=videoFrameArray, audioChannels=0, # not populated yet ... audioSamples=None, metadata=self.metadata, movieLib=u'ffpyplayer', userData=None) return True def update(self): """Update this player. This get the latest data from the video stream and updates the player accordingly. This should be called at a higher frequency than the frame rate of the movie to avoid frame skips. """ self._assertMediaPlayer() # check if the stream reader thread is present and alive, if not the # movie is finished if not self._tStream.isDone(): self._enqueueFrame() else: self.parent.status = self._status = FINISHED def getMovieFrame(self): """Get the movie frame scheduled to be displayed at the current time. Returns ------- `~psychopy.visual.movies.frame.MovieFrame` Current movie frame. """ self.update() return self._lastFrame def __del__(self): """Cleanup when unloading. """ if hasattr(self, '_tStream'): if self._tStream is not None: if not self._tStream.isDone(): self._tStream.shutdown() self._tStream.join() if hasattr(self, '_handle'): if self._handle is not None: self._handle.close_player()
class VideoStream: def __init__(self, video_source=None): ff_opts = {'paused': True, 'autoexit': False} # Audio options self.video_surce = video_source # Open the video source self.player = MediaPlayer(video_source, ff_opts=ff_opts) # TODO: colocar pausa de tiempo para cargas mediaplayer y obtener los datos # conseguir el frame rate para la sincronizacion self.dalay while self.player.get_metadata()['src_vid_size'] == (0, 0): time.sleep(0.01) data = self.player.get_metadata() print('data -->', data) self.f_rate = data['frame_rate'] print('delay -> ', self.f_rate) self.w, self.h = data['src_vid_size'] print('WxH -> ', self.w, self.h) self.pts = self.player.get_pts( ) # Returns the elapsed play time. float print('pts ->', self.pts) self.duration = data['duration'] print('duration', self.duration) self.pause = self.player.get_pause( ) # Returns whether the player is paused. print('pause ->', self.pause) self.volume = self.player.get_volume( ) # Returns the volume of the audio. loat: A value between 0.0 - 1.0 print('volume ->', self.volume) self.player.toggle_pause( ) # Toggles -alterna- the player’s pause state # self.player.set_pause(False) # auses or un-pauses the file. state: bool cond = True while cond: self.l_frame, self.val = self.player.get_frame() if self.val == 'eof': print('can not open source: ', video_source) break elif self.l_frame is None: time.sleep(0.01) else: self._imagen, self.pts = self.l_frame print('pts ->', self.pts) # arr = self._imagen.to_memoryview()[0] # array image # self.imagen = Image.frombytes("RGB", self.original_size, arr.memview) # self.imagen.show() cond = False # propierties. @property def f_rate(self): return self.__f_rate @f_rate.setter def f_rate(self, val): import math vn = val[0] vd = val[1] if vd <= 1: self.__f_rate = vn elif vd > 1: self.__f_rate = int(round(vn / vd)) else: self.__f_rate = 30 # end properties. def get_frame(self): ''' Return valores: val : 'eof' or 'pause' pts : time location aduio imagen. imagen : frame image Return (val, t, imagen) ''' self.l_frame, self.val = self.player.get_frame() if self.val == 'eof': # condicion final fichero, salimos if and while # self.player.toggle_pause() # ponemos en pause return self.val, None, None elif self.l_frame is None: time.sleep(0.01) return self.val, None, None else: # import math self._imagen, self.pts = self.l_frame return self.val, self.pts, self._imagen # w, h = self._imagen.get_size() # linesize = [int(math.ceil(w * 3 / 32.) * 32)] # self._imagen = pic.Image(plane_buffers=[bytes(b' ') * (h * linesize[0])], # pix_fmt=self._imagen.get_pixel_format(), size=(w, h), linesize=linesize) # self._imagen.get_linesizes(keep_align=True) # if self.new_size is not None: # sws = None # n_w , n_h = self.new_size # if n_w > n_h: # sws = pic.SWScale(w, h, self._imagen.get_pixel_format(), oh=n_h) # else: # sws = pic.SWScale(w, h, self._imagen.get_pixel_format(), ow=n_w) # self._imagen = sws.scale(self._imagen) # size = self._imagen.get_size() # arr = self._imagen.to_memoryview()[0] # array image # self.imagen = Image.frombytes("RGB", size, arr.memview) # print('>>> videostream::get_frame()::self.pts ->', self.pts) def toggle_pause(self): ''' Function: toggle_pause ''' try: # Stopping audio self.player.toggle_pause() # self.player = None except: pass def seek(self, pts=None, relative=False, accurate=False): if not pts: return self.player.seek(pts, relative=False, accurate=False) def snapshot(self, road=None): ''' get current frame ''' img = self.l_frame[0] if img is not None: size = img.get_size() arr = img.to_memoryview()[0] # array image img = Image.frombytes("RGB", size, arr.memview) # vamos a guardar esto. time_str = time.strftime("%d-%m-%Y-%H-%M-%S") frame_name = f"frame-{time_str}.jpg" if not road: ruta = os.path.dirname(self.video_surce) name_out = os.path.join(ruta, frame_name) else: name_out = os.path.join(road, frame_name) img.save(name_out) # Release the video source when the object is destroyed def __del__(self): self.player.close_player() print('__del__')