본문 바로가기

python

Python Video Player 파이썬 비디오 플레이어

728x90

Python Video Player 파이썬 비디오 플레이어

 

Python Video Player

 

videoPlayer.py
0.01MB

 

다음 두가지를 설치합니다.

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