目录
随窗口改变,拖拽打开mp4:
n加载下一个视频,l加载上一个视频:
固定大小,不能随窗口改变:
随窗口改变,拖拽打开mp4:
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QTimer
from collections import deque
from pynput import keyboardclass VideoPlayer(QMainWindow):def __init__(self):super().__init__()# 设置窗口self.setWindowTitle('Drag and Drop MP4 Player')self.setGeometry(100, 100, 800, 600)self.setAcceptDrops(True)# 主窗口部件和布局self.widget = QWidget(self)self.layout = QVBoxLayout(self.widget)self.setCentralWidget(self.widget)# 创建QGraphicsView和QGraphicsSceneself.graphics_view = QGraphicsView(self)self.layout.addWidget(self.graphics_view)# 设置 QGraphicsView 的样式表,以去除边框和滚动条self.graphics_view.setStyleSheet("border: none; background: transparent;")self.graphics_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.graphics_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.scene = QGraphicsScene(self)self.graphics_view.setScene(self.scene)self.pixmap_item = QGraphicsPixmapItem()self.scene.addItem(self.pixmap_item)# 创建显示文件路径的QLabelself.file_info_label = QLabel("Drag MP4 file here", self)self.file_info_label.setAlignment(Qt.AlignCenter)self.file_info_label.setStyleSheet("border-top: 1px solid black; border-left: none; border-right: none; border-bottom: none; padding: 10px;") # 只显示上边框self.layout.addWidget(self.file_info_label)# 视频相关变量self.cap = Noneself.frame_buffer = deque(maxlen=300)self.queue_index = -1self.load_new_frame = Trueself.frame_index = -1# 定时器self.timer = QTimer(self)self.timer.timeout.connect(self.display_frame)# 启动键盘监听listener = keyboard.Listener(on_press=self.on_press)listener.start()# 初始化视频文件(确保文件路径可用)self.file_path = Nonedef on_press(self, key):if key == keyboard.Key.right or key == keyboard.Key.space:if self.queue_index < len(self.frame_buffer) - 1:self.queue_index += 1else:self.load_new_frame = Trueelif key == keyboard.Key.left:if self.queue_index > 0:self.queue_index -= 1self.load_new_frame = Falseelif str(key) == "'q'":self.close()def dragEnterEvent(self, event):if event.mimeData().hasUrls():event.accept()else:event.ignore()def dropEvent(self, event):for url in event.mimeData().urls():file_path = url.toLocalFile()if file_path.lower().endswith(".mp4"):self.file_path = file_pathself.file_info_label.setText(f"Loading: {file_path}")self.load_video(file_path)self.setWindowTitle(file_path)def load_video(self, file_path):if self.cap:self.cap.release()self.cap = cv2.VideoCapture(file_path)self.frame_buffer.clear()self.queue_index = -1self.frame_index = -1self.load_new_frame = True# 开始播放视频self.timer.start(30)def display_frame(self):if self.load_new_frame and self.cap:ret, frame = self.cap.read()if not ret:self.load_new_frame = Falsecv2.putText(self.frame_buffer[self.queue_index], str(self.frame_index) + ":end", (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)else:self.frame_index += 1cv2.putText(frame, str(self.frame_index), (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)self.frame_buffer.append(frame)self.queue_index = len(self.frame_buffer) - 1self.load_new_frame = Falseif len(self.frame_buffer) > 0:imshow = self.frame_buffer[self.queue_index]self.show_frame(imshow)def show_frame(self, frame):rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)h, w, ch = rgb_frame.shapebytes_per_line = ch * wq_img = QImage(rgb_frame.data, w, h, bytes_per_line, QImage.Format_RGB888)pixmap = QPixmap.fromImage(q_img)self.pixmap_item.setPixmap(pixmap)# 调整视图以适应图像self.fit_image_to_view()def fit_image_to_view(self):if self.pixmap_item.pixmap().isNull():returnself.graphics_view.resetTransform()# 调整视图以适应图像self.graphics_view.fitInView(self.pixmap_item, Qt.KeepAspectRatio)def resizeEvent(self, event):super().resizeEvent(event)self.fit_image_to_view() # 窗口调整大小时调整图片的缩放比例def closeEvent(self, event):if self.cap:self.cap.release()self.timer.stop()event.accept()if __name__ == '__main__':app = QApplication(sys.argv)player = VideoPlayer()player.show() # 显示窗口,使用默认大小,不最大化sys.exit(app.exec_())
n加载下一个视频,l加载上一个视频:
import glob
import os.path
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QTimer
from collections import deque
from pynput import keyboardfrom natsort import natsorted
class VideoPlayer(QMainWindow):def __init__(self):super().__init__()# 设置窗口self.setWindowTitle('Drag and Drop MP4 Player')self.setGeometry(100, 100, 800, 600)self.setAcceptDrops(True)# 主窗口部件和布局self.widget = QWidget(self)self.layout = QVBoxLayout(self.widget)self.setCentralWidget(self.widget)# 创建QGraphicsView和QGraphicsSceneself.graphics_view = QGraphicsView(self)self.layout.addWidget(self.graphics_view)# 设置 QGraphicsView 的样式表,以去除边框和滚动条self.graphics_view.setStyleSheet("border: none; background: transparent;")self.graphics_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.graphics_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.scene = QGraphicsScene(self)self.graphics_view.setScene(self.scene)self.pixmap_item = QGraphicsPixmapItem()self.scene.addItem(self.pixmap_item)# 创建显示文件路径的QLabelself.file_info_label = QLabel("Drag MP4 file here", self)self.file_info_label.setAlignment(Qt.AlignCenter)self.file_info_label.setStyleSheet("border-top: 1px solid black; border-left: none; border-right: none; border-bottom: none; padding: 10px;") # 只显示上边框self.layout.addWidget(self.file_info_label)# 视频相关变量self.cap = Noneself.frame_buffer = deque(maxlen=300)self.queue_index = -1self.load_new_frame = Trueself.frame_index = -1# 定时器self.timer = QTimer(self)self.timer.timeout.connect(self.display_frame)# 启动键盘监听listener = keyboard.Listener(on_press=self.on_press)listener.start()# 初始化视频文件(确保文件路径可用)self.file_path = Nonedef on_press(self, key):if key == keyboard.Key.right or key == keyboard.Key.space:if self.queue_index < len(self.frame_buffer) - 1:self.queue_index += 1else:self.load_new_frame = Trueelif key == keyboard.Key.left:if self.queue_index > 0:self.queue_index -= 1self.load_new_frame = Falseelif str(key) == "'n'":self.file_i += 1if self.file_i < len(self.frame_buffer):self.load_video(self.file_list[self.file_i])elif str(key) == "'l'":self.file_i -= 1if self.file_i>=0:self.load_video(self.file_list[self.file_i])elif str(key) == "'q'":self.close()def dragEnterEvent(self, event):if event.mimeData().hasUrls():event.accept()else:event.ignore()def dropEvent(self, event):for url in event.mimeData().urls():file_path = url.toLocalFile()if file_path.lower().endswith(".mp4"):self.file_path = file_pathself.file_info_label.setText(f"Loading: {file_path}")self.load_video(file_path)self.file_list=glob.glob(f"{os.path.dirname(file_path)}/*.mp4")self.file_list=natsorted(self.file_list)self.file_i=0self.setWindowTitle(file_path)def load_video(self, file_path):if self.cap:self.cap.release()self.cap = cv2.VideoCapture(file_path)self.frame_buffer.clear()self.queue_index = -1self.frame_index = -1self.load_new_frame = True# 开始播放视频self.timer.start(30)def display_frame(self):if self.load_new_frame and self.cap:ret, frame = self.cap.read()if not ret:self.load_new_frame = Falseself.end_count+=1if self.end_count > 3:self.load_video(self.file_path)cv2.putText(self.frame_buffer[self.queue_index], str(self.frame_index) + ":end", (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)else:self.frame_index += 1cv2.putText(frame, str(self.frame_index), (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)self.frame_buffer.append(frame)self.queue_index = len(self.frame_buffer) - 1self.load_new_frame = Falseif len(self.frame_buffer) > 0:imshow = self.frame_buffer[self.queue_index]self.show_frame(imshow)def show_frame(self, frame):rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)h, w, ch = rgb_frame.shapebytes_per_line = ch * wq_img = QImage(rgb_frame.data, w, h, bytes_per_line, QImage.Format_RGB888)pixmap = QPixmap.fromImage(q_img)self.pixmap_item.setPixmap(pixmap)# 调整视图以适应图像self.fit_image_to_view()def fit_image_to_view(self):if self.pixmap_item.pixmap().isNull():returnself.graphics_view.resetTransform()# 调整视图以适应图像self.graphics_view.fitInView(self.pixmap_item, Qt.KeepAspectRatio)def resizeEvent(self, event):super().resizeEvent(event)self.fit_image_to_view() # 窗口调整大小时调整图片的缩放比例def closeEvent(self, event):if self.cap:self.cap.release()self.timer.stop()event.accept()if __name__ == '__main__':app = QApplication(sys.argv)player = VideoPlayer()player.show() # 显示窗口,使用默认大小,不最大化sys.exit(app.exec_())
固定大小,不能随窗口改变:
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QFileDialog, QVBoxLayout, QWidget
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QTimer
from collections import deque
from pynput import keyboard
import numpy as npclass VideoPlayer(QMainWindow):def __init__(self):super().__init__()# Set up the windowself.setWindowTitle('Drag and Drop MP4 Player')self.setGeometry(100, 100, 800, 600)self.setAcceptDrops(True)# Main widget and layoutself.widget = QWidget(self)self.layout = QVBoxLayout(self.widget)self.setCentralWidget(self.widget)# Label to display video framesself.video_label = QLabel(self)self.video_label.setAlignment(Qt.AlignCenter)self.layout.addWidget(self.video_label)# Instructions labelself.label = QLabel("Drag and drop an MP4 file here to play", self)self.label.setAlignment(Qt.AlignCenter)self.layout.addWidget(self.label)# Video variablesself.cap = Noneself.frame_buffer = deque(maxlen=300)self.queue_index = -1self.load_new_frame = Trueself.frame_index = -1# Timer for video playbackself.timer = QTimer(self)self.timer.timeout.connect(self.display_frame)# Start keyboard listenerlistener = keyboard.Listener(on_press=self.on_press)listener.start()def on_press(self, key):if key == keyboard.Key.right or key == keyboard.Key.space: # Right arrow keyif self.queue_index < len(self.frame_buffer) - 1:self.queue_index += 1else:self.load_new_frame = Trueelif key == keyboard.Key.left: # Left arrow keyif self.queue_index > 0:self.queue_index -= 1self.load_new_frame = Falseelif str(key) == "'q'": # Press 'q' to exitself.close()def dragEnterEvent(self, event):if event.mimeData().hasUrls():event.accept()else:event.ignore()def dropEvent(self, event):for url in event.mimeData().urls():file_path = url.toLocalFile()if file_path.lower().endswith(".mp4"):self.load_video(file_path)def load_video(self, file_path):if self.cap:self.cap.release()self.cap = cv2.VideoCapture(file_path)self.frame_buffer.clear()self.queue_index = -1self.frame_index = -1self.load_new_frame = True# Start playing videoself.timer.start(30) # Start timer to update frames every 30msdef display_frame(self):if self.load_new_frame and self.cap:ret, frame = self.cap.read()if not ret:self.timer.stop()print('Video ended')returnself.frame_index += 1cv2.putText(frame, str(self.frame_index), (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)self.frame_buffer.append(frame)self.queue_index = len(self.frame_buffer) - 1self.load_new_frame = False# Show the current frameif len(self.frame_buffer) > 0:imshow = self.frame_buffer[self.queue_index]self.show_frame(imshow)def show_frame(self, frame):# Convert the frame from OpenCV (BGR) format to RGB formatrgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)h, w, ch = rgb_frame.shapebytes_per_line = ch * wq_img = QImage(rgb_frame.data, w, h, bytes_per_line, QImage.Format_RGB888)# Set the QPixmap to the QLabelself.video_label.setPixmap(QPixmap.fromImage(q_img).scaled(self.video_label.width(), self.video_label.height(), Qt.KeepAspectRatio))def closeEvent(self, event):if self.cap:self.cap.release()self.timer.stop()event.accept()if __name__ == '__main__':app = QApplication(sys.argv)player = VideoPlayer()player.show()sys.exit(app.exec_())