-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpreview.py
113 lines (95 loc) · 3.93 KB
/
preview.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from PySide6.QtCore import QThread, Signal, QTimer, QTime
from PySide6.QtWidgets import QWidget
from PySide6.QtGui import QImage, QPixmap
from numpy import ndarray
class VideoPreviewWidget(QWidget):
def __init__(self, video_input, preview, video_time_text):
super().__init__()
video_clip = video_input
self.preview = preview
# Start the frame grabbing threa
self.frame_grab = FrameGrab(video_clip, video_time_text)
self.frame_grab.frameReady.connect(self.update_frame)
self.frame_grab.start()
self.slider_timer = QTimer(self)
self.slider_timer.setSingleShot(True)
self.slider_timer.timeout.connect(self.apply_update)
self.update_type = None
self.new_time_value = 0
def set_time(self, value, update_type, play_pause=None, play_stop=None):
self.new_time_value = value
self.update_type = update_type
self.play_pause = play_pause
self.play_stop = play_stop
self.slider_timer.start(300)
def apply_update(self):
if self.update_type == "start":
self.frame_grab.update_start(self.new_time_value, self.play_pause, self.play_stop)
elif self.update_type == "end":
self.frame_grab.update_end(self.new_time_value)
def update_frame(self, frame):
height, width, channels = frame.shape
bytes_per_line = channels * width
q_image = QImage(frame.data, width, height, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(q_image)
self.preview_label = self.preview.setPixmap(pixmap)
def closeEvent(self, event):
self.frame_fetcher.stop() # Stop the thread when the widget is closed
self.frame_fetcher.wait()
super().closeEvent(event)
class FrameGrab(QThread):
frameReady = Signal(ndarray)
def __init__(self, video_clip, video_time_text):
super().__init__()
self.video_clip = video_clip
self.running = True
self.start_time = 0
self.timer = 0
self.video_time_text = video_time_text
self.duration = self.video_clip.duration
self.end_time = self.duration
def update_start(self, time, play_pause, play_stop):
self.stop()
self.start_time = time
self.timer = time
frame = self.video_clip.get_frame(self.timer) # Get frame at current time
self.frameReady.emit(frame) # Send frame via signal
if play_pause == "pause":
return
if play_stop == "stop":
return
self.play()
def update_end(self, time):
self.duration = time
self.end_time = time
def run(self):
fps = self.video_clip.fps
frame_interval = 1 / fps
while self.timer < self.duration:
if self.running:
frame = self.video_clip.get_frame(self.timer) # Get frame at current time
self.frameReady.emit(frame) # Send frame via signal
self.msleep(int(frame_interval * 1000)) # Sleep until the next frame
self.timer += frame_interval
self.video_time_text.setTime(self.seconds_to_time(self.timer))
if self.timer >= self.duration:
self.timer = self.start_time
def play(self):
self.running = True
if self.timer >= self.duration:
self.timer = self.start_time
def pause(self):
self.running = False
if self.timer >= self.duration:
self.timer = self.start_time
def stop(self):
self.running = False
self.timer = self.start_time
self.video_time_text.setTime(self.seconds_to_time(self.timer))
def seconds_to_time(self, time):
# Calculate maximum time from video duration (in seconds)
hours = time // 3600
minutes = (time % 3600) // 60
seconds = time % 60
formatted_time = QTime(hours, minutes, seconds)
return formatted_time