728x90
Python Video Player 파이썬 비디오 플레이어
다음 두가지를 설치합니다.
pip install PyQt5
pip install opencv-python
그 후 파일을 만듭니다.
videoPlayer.py
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QPushButton, QSlider, QStyle, QStyleOptionSlider
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QImage, QPixmap
class ClickableSlider(QSlider):
def mousePressEvent(self, event):
super(ClickableSlider, self).mousePressEvent(event)
if event.button() == Qt.LeftButton:
val = self.pixelPosToRangeValue(event.pos())
self.setValue(val)
self.sliderMoved.emit(val)
def pixelPosToRangeValue(self, pos):
opt = QStyleOptionSlider()
self.initStyleOption(opt)
gr = self.style().subControlRect(QStyle.CC_Slider, opt, QStyle.SC_SliderGroove, self)
sr = self.style().subControlRect(QStyle.CC_Slider, opt, QStyle.SC_SliderHandle, self)
if self.orientation() == Qt.Horizontal:
sliderLength = sr.width()
sliderMin = gr.x()
sliderMax = gr.right() - sliderLength + 1
else:
sliderLength = sr.height()
sliderMin = gr.y()
sliderMax = gr.bottom() - sliderLength + 1
pr = pos - sr.center() + sr.topLeft()
p = pr.x() if self.orientation() == Qt.Horizontal else pr.y()
return QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), p - sliderMin, sliderMax - sliderMin, opt.upsideDown)
class VideoPlayer(QWidget):
def __init__(self):
super().__init__()
self.setAcceptDrops(True)
self.initUI()
def initUI(self):
self.setWindowTitle('드래그 앤 드롭 비디오 플레이어')
self.setGeometry(100, 100, 800, 600)
self.label = QLabel(self)
self.label.setAlignment(Qt.AlignCenter)
self.label.setText('비디오 파일을 여기에 드래그 앤 드롭하세요')
self.play_pause_button = QPushButton('재생', self)
self.play_pause_button.clicked.connect(self.toggle_play_pause)
self.play_pause_button.setEnabled(False)
self.slider = ClickableSlider(Qt.Horizontal)
self.slider.sliderMoved.connect(self.set_position)
self.slider.sliderPressed.connect(self.slider_pressed)
self.slider.sliderReleased.connect(self.slider_released)
self.slider.setEnabled(False)
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.play_pause_button)
layout.addWidget(self.slider)
self.setLayout(layout)
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_frame)
self.cap = None
self.is_playing = False
self.total_frames = 0
self.current_frame = 0
self.video_path = ""
self.slider_is_pressed = False
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
files = [u.toLocalFile() for u in event.mimeData().urls()]
if files:
self.video_path = files[0]
self.play_video()
def play_video(self):
self.cap = cv2.VideoCapture(self.video_path)
if not self.cap.isOpened():
self.label.setText('비디오 파일 열기 오류')
return
self.total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
self.slider.setRange(0, self.total_frames)
self.play_pause_button.setEnabled(True)
self.slider.setEnabled(True)
self.current_frame = 0
self.toggle_play_pause()
def update_frame(self):
if self.cap is None:
return
ret, frame = self.cap.read()
if ret:
self.current_frame += 1
if not self.slider_is_pressed:
self.slider.setValue(self.current_frame)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = frame.shape
bytes_per_line = ch * w
q_image = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(q_image)
self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
else:
self.timer.stop()
self.is_playing = False
self.play_pause_button.setText('재생')
self.current_frame = self.total_frames
self.slider.setValue(self.total_frames)
self.label.setText('비디오 재생 완료')
def toggle_play_pause(self):
if self.is_playing:
self.timer.stop()
self.play_pause_button.setText('재생')
self.is_playing = False
else:
if self.current_frame >= self.total_frames:
self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
self.current_frame = 0
self.slider.setValue(0)
self.timer.start(33) # ~33ms마다 업데이트 (30 fps)
self.play_pause_button.setText('일시정지')
self.is_playing = True
def set_position(self, position):
if self.cap is not None:
self.cap.set(cv2.CAP_PROP_POS_FRAMES, position)
self.current_frame = position
ret, frame = self.cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = frame.shape
bytes_per_line = ch * w
q_image = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(q_image)
self.label.setPixmap(pixmap.scaled(self.label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
def slider_pressed(self):
self.slider_is_pressed = True
if self.is_playing:
self.timer.stop()
def slider_released(self):
self.slider_is_pressed = False
if self.is_playing:
self.timer.start(33)
if __name__ == '__main__':
app = QApplication(sys.argv)
player = VideoPlayer()
player.show()
sys.exit(app.exec_())
==========
728x90
'python' 카테고리의 다른 글
Cloudflare R2 API 파이썬으로 파일 업로드하기 (0) | 2025.04.25 |
---|---|
Python 파이썬으로 파일이름 00001 + 1로 변환하기 (0) | 2024.09.23 |
Python WebP 파일 변환 + 16:9 비율로 사이즈 변환 (0) | 2024.09.23 |
Python Image Viewer 파이썬 이미지 뷰어 tkinter / PyQt5 (0) | 2024.09.20 |
Python quick Click 파이썬으로 빠르게 클릭하는 프로그램 만들기 (1) | 2024.09.20 |