-
Notifications
You must be signed in to change notification settings - Fork 4
/
video_remixer_reports.py
210 lines (188 loc) · 7.7 KB
/
video_remixer_reports.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
"""Video Remixer Reporting"""
from typing import Callable, TYPE_CHECKING
from webui_utils.simple_icons import SimpleIcons
from webui_utils.simple_utils import seconds_to_hmsf, format_table
from webui_utils.video_utils import details_from_group_name
from webui_utils.jot import Jot
if TYPE_CHECKING:
from video_remixer import VideoRemixerState
class VideoRemixerReports():
def __init__(self, state : "VideoRemixerState", log_fn : Callable):
self.state = state
self.log_fn = log_fn
def log(self, message):
if self.log_fn:
self.log_fn(message)
## Exports -----------------------
def ingested_video_report(self):
title = f"Ingested Video Report: {self.state.source_video}"
header_row = [
"Frame Rate",
"Duration",
"Display Size",
"Aspect Ratio",
"Content Size",
"Frame Count",
"File Size",
"Has Audio"]
data_rows = [[
self.state.video_details['frame_rate'],
self.state.video_details['duration'],
self.state.video_details['display_dimensions'],
self.state.video_details['display_aspect_ratio'],
self.state.video_details['content_dimensions'],
self.state.video_details['frame_count_show'],
self.state.video_details['file_size'],
SimpleIcons.YES_SYMBOL if self.state.video_details['has_audio'] else SimpleIcons.NO_SYMBOL]]
return format_table(header_row, data_rows, color="more", title=title)
def project_settings_report(self):
title = f"Project Path: {self.state.project_path}"
if self.state.split_type == "Scene":
header_row, data_rows = self._project_settings_report_scene()
elif self.state.split_type == "Break":
header_row, data_rows = self._project_settings_report_break()
elif self.state.split_type == "Time":
header_row, data_rows = self._project_settings_report_time()
else: # "None"
header_row, data_rows = self._project_settings_report_none()
return format_table(header_row, data_rows, color="more", title=title)
def chosen_scenes_report(self):
header_row = [
"Scene Choices",
"Scenes",
"Frames",
"Time"]
all_scenes = len(self.state.scene_names)
all_frames = self.scene_frames("all")
all_time = self.scene_frames_time(all_frames)
keep_scenes = len(self.state.kept_scenes())
keep_frames = self.scene_frames("keep")
keep_time = self.scene_frames_time(keep_frames)
drop_scenes = len(self.state.dropped_scenes())
drop_frames = self.scene_frames("drop")
drop_time = self.scene_frames_time(drop_frames)
data_rows = [
[
"Keep " + SimpleIcons.HEART,
f"{keep_scenes:,d}",
f"{keep_frames:,d}",
f"+{keep_time}"],
[
"Drop",
f"{drop_scenes:,d}",
f"{drop_frames:,d}",
f"+{drop_time}"],
[
"Total",
f"{all_scenes:,d}",
f"{all_frames:,d}",
f"+{all_time}"]]
return format_table(header_row, data_rows, color="more")
def generate_remix_report(self, resize, resynthesize, inflate, effects, upscale):
report = Jot()
if not resize \
and not resynthesize \
and not inflate \
and not upscale:
report.add(f"Original source scenes in {self.state.scenes_path}")
if resize:
report.add(f"Resized/cropped scenes in {self.state.resize_path}")
if resynthesize:
report.add(f"Resynthesized scenes in {self.state.resynthesis_path}")
if inflate:
report.add(f"Inflated scenes in {self.state.inflation_path}")
if effects:
report.add(f"Effects scenes in {self.state.effects_path}")
if upscale:
report.add(f"Upscaled scenes in {self.state.upscale_path}")
return report.lines
## Internal ----------------------
def _project_settings_report_scene(self):
header_row = [
"Frame Rate",
"Deinterlace",
"Resize To",
"Crop To",
"Crop Offset",
"Split Type",
"Scene Detection Threshold"]
data_rows = [[
f"{float(self.state.project_fps):.2f}",
SimpleIcons.YES_SYMBOL if self.state.deinterlace else SimpleIcons.NO_SYMBOL,
f"{self.state.resize_w} x {self.state.resize_h}",
f"{self.state.crop_w} x {self.state.crop_h}",
f"{self.state.crop_offset_x} x {self.state.crop_offset_y}",
self.state.split_type,
self.state.scene_threshold]]
return header_row, data_rows
def _project_settings_report_break(self):
header_row = [
"Frame Rate",
"Deinterlace",
"Resize To",
"Crop To",
"Crop Offset",
"Split Type",
"Minimum Duration",
"Black Ratio"]
data_rows = [[
f"{float(self.state.project_fps):.2f}",
SimpleIcons.YES_SYMBOL if self.state.deinterlace else SimpleIcons.NO_SYMBOL,
f"{self.state.resize_w} x {self.state.resize_h}",
f"{self.state.crop_w} x {self.state.crop_h}",
f"{self.state.crop_offset_x} x {self.state.crop_offset_y}",
self.state.split_type,
f"{self.state.break_duration}s",
self.state.break_ratio]]
return header_row, data_rows
def _project_settings_report_time(self):
header_row = [
"Frame Rate",
"Deinterlace",
"Resize To",
"Crop To",
"Crop Offset",
"Split Type",
"Split Time",
"Split Frames"]
self.state.split_frames = self.state.calc_split_frames(self.state.project_fps, self.state.split_time)
data_rows = [[
f"{float(self.state.project_fps):.2f}",
SimpleIcons.YES_SYMBOL if self.state.deinterlace else SimpleIcons.NO_SYMBOL,
f"{self.state.resize_w} x {self.state.resize_h}",
f"{self.state.crop_w} x {self.state.crop_h}",
f"{self.state.crop_offset_x} x {self.state.crop_offset_y}",
self.state.split_type,
f"{self.state.split_time}s",
self.state.split_frames]]
return header_row, data_rows
def _project_settings_report_none(self):
header_row = [
"Frame Rate",
"Deinterlace",
"Resize To",
"Crop To",
"Crop Offset",
"Split Type"]
data_rows = [[
f"{float(self.state.project_fps):.2f}",
SimpleIcons.YES_SYMBOL if self.state.deinterlace else SimpleIcons.NO_SYMBOL,
f"{self.state.resize_w} x {self.state.resize_h}",
f"{self.state.crop_w} x {self.state.crop_h}",
f"{self.state.crop_offset_x} x {self.state.crop_offset_y}",
self.state.split_type]]
return header_row, data_rows
def scene_frames(self, type : str="all") -> int:
if type.lower() == "keep":
scenes = self.state.kept_scenes()
elif type.lower() == "drop":
scenes = self.state.dropped_scenes()
else:
scenes = self.state.scene_names
accum = 0
for scene in scenes:
first, last, _ = details_from_group_name(scene)
accum += (last - first) + 1
return accum
def scene_frames_time(self, frames : int) -> str:
return seconds_to_hmsf(frames / self.state.project_fps, self.state.project_fps)