Source code for simba.ui.pop_ups.video_processing_pop_up
__author__ = "Simon Nilsson"
import glob
import os
import subprocess
import sys
import threading
from copy import deepcopy
from datetime import datetime
from tkinter import *
from typing import Optional, Union
import numpy as np
from PIL import Image, ImageTk
import simba
from simba.labelling.extract_labelled_frames import AnnotationFrameExtractor
from simba.mixins.config_reader import ConfigReader
from simba.mixins.pop_up_mixin import PopUpMixin
from simba.plotting.frame_mergerer_ffmpeg import FrameMergererFFmpeg
from simba.ui.px_to_mm_ui import GetPixelsPerMillimeterInterface
from simba.ui.tkinter_functions import (CreateLabelFrameWithIcon,
CreateToolTip, DropDownMenu, Entry_Box,
FileSelect, FolderSelect, SimbaButton,
SimbaCheckbox, SimBADropDown,
SimBALabel, SimBARadioButton,
SimBAScaleBar, SimBASeperator)
from simba.ui.video_timelaps import TimelapseSlider
from simba.utils.checks import (check_ffmpeg_available,
check_file_exist_and_readable,
check_if_dir_exists,
check_if_string_value_is_valid_video_timestamp,
check_int, check_nvidea_gpu_available,
check_str,
check_that_hhmmss_start_is_before_end)
from simba.utils.data import (convert_roi_definitions, get_cpu_pool,
terminate_cpu_pool)
from simba.utils.enums import (Dtypes, Formats, Keys, Links, Options, Paths,
TkBinds)
from simba.utils.errors import (CountError, DuplicationError,
FFMPEGCodecGPUError, FrameRangeError,
InvalidInputError, MixedMosaicError,
NoChoosenClassifierError, NoDataError,
NoFilesFoundError, NotDirectoryError,
ResolutionError)
from simba.utils.lookups import (get_color_dict, get_ffmpeg_crossfade_methods,
get_fonts, get_monitor_info,
percent_to_crf_lookup, quality_pct_to_crf)
from simba.utils.printing import SimbaTimer, stdout_information, stdout_success
from simba.utils.read_write import (
check_if_hhmmss_timestamp_is_valid_part_of_video,
concatenate_videos_in_folder, find_all_videos_in_directory, find_core_cnt,
find_files_of_filetypes_in_directory, find_video_of_file, get_fn_ext,
get_video_meta_data, read_frm_of_video, seconds_to_timestamp, str_2_bool,
timestamp_to_seconds)
from simba.utils.warnings import FrameRangeWarning
from simba.video_processors.brightness_contrast_ui import BrightnessContrastUI
from simba.video_processors.clahe_ui import interactive_clahe_ui
from simba.video_processors.extract_seqframes import extract_seq_frames
from simba.video_processors.multi_cropper import MultiCropper
from simba.video_processors.video_processing import (
VideoRotator, batch_convert_video_format, batch_create_frames,
batch_video_to_greyscale, change_fps_of_multiple_videos, change_img_format,
change_single_video_fps, clahe_enhance_video, clahe_enhance_video_mp,
clip_video_in_range, clip_videos_by_frame_ids, convert_to_avi,
convert_to_bmp, convert_to_jpeg, convert_to_mov, convert_to_mp4,
convert_to_png, convert_to_tiff, convert_to_webm, convert_to_webp,
convert_video_powerpoint_compatible_format, copy_img_folder,
create_average_frm, crop_multiple_videos, crop_multiple_videos_polygons,
crop_single_video, crop_single_video_circle, crop_single_video_polygon,
crossfade_two_videos, downsample_video, extract_frame_range,
extract_frames_single_video, flip_videos, frames_to_movie, gif_creator,
multi_split_video, remove_beginning_of_video, remove_end_of_video,
resize_videos_by_height, resize_videos_by_width, reverse_videos,
roi_blurbox, rotate_video, superimpose_elapsed_time,
superimpose_frame_count, superimpose_freetext, superimpose_overlay_video,
superimpose_video_names, superimpose_video_progressbar,
temporal_concatenation, upsample_fps, video_bg_subtraction,
video_bg_subtraction_mp, video_concatenator, video_to_bw,
video_to_greyscale, watermark_video)
sys.setrecursionlimit(10**7)
[docs]class CLAHEPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CLAHE VIDEO CONVERSION", icon='clahe')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name='settings', icon_link=Links.VIDEO_TOOLS.value)
lbl = SimBALabel(parent=settings_frm, txt='For more control over CLAHE conversion, try "Interactively CLAHE enhance videos" \n in SimBA Tools->Remove color from videos.', font=Formats.FONT_REGULAR_ITALICS.value)
self.core_cnt_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, find_core_cnt()[0]+1)), label='CORE COUNT:', label_width=25, dropdown_width=20, value=1, img='cpu_small', tooltip_key='CORE_COUNT')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU:', label_width=25, dropdown_width=20, value='FALSE', img='gpu_3', tooltip_key='USE_GPU')
self.clip_limit_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(2, 62, 2)), label='CLIP LIMIT:', label_width=25, dropdown_width=20, value=2, img='clip', tooltip_key='CLAHE_CLIP_LIMIT')
self.tile_height_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(2, 62, 1)), label='TILE SIZE (HEIGHT):', label_width=25, dropdown_width=20, value=16, img='height', tooltip_key='CLAHE_TILE_HEIGHT')
self.tile_width_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(2, 62, 1)), label='TILE SIZE (WIDTH):', label_width=25, dropdown_width=20, value=16, img='width', tooltip_key='CLAHE_TILE_WIDTH')
if not check_nvidea_gpu_available(): self.gpu_dropdown.disable()
settings_frm.grid(row=0, column=0, sticky=NW)
lbl.grid(row=0, column=0, sticky=NW)
self.core_cnt_dropdown.grid(row=1, column=0, sticky=NW)
self.gpu_dropdown.grid(row=2, column=0, sticky=NW)
self.clip_limit_dropdown.grid(row=3, column=0, sticky=NW)
self.tile_height_dropdown.grid(row=4, column=0, sticky=NW)
self.tile_width_dropdown.grid(row=5, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - Contrast Limited Adaptive Histogram Equalization", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=25, lbl_icon='video_2')
run_single_video_btn = SimbaButton(parent=single_video_frm, txt="Apply CLAHE on VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_single_video, width=160)
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOs - Contrast Limited Adaptive Histogram Equalization", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", lblwidth=25, lbl_icon='folder')
run_multiple_btn = SimbaButton(parent=multiple_videos_frm, txt="Apply CLAHE on DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_directory, width=160)
single_video_frm.grid(row=1, column=0, sticky=NW)
self.selected_video.grid(row=0, column=0, sticky=NW)
run_single_video_btn.grid(row=1, column=0, sticky=NW)
multiple_videos_frm.grid(row=2, column=0, sticky=NW)
self.selected_dir.grid(row=0, column=0, sticky=NW)
run_multiple_btn.grid(row=1, column=0, sticky=NW)
def _get_settings(self):
self.core_cnt = int(self.core_cnt_dropdown.get_value())
self.gpu = str_2_bool(self.gpu_dropdown.get_value())
height = int(self.tile_height_dropdown.get_value())
width = int(self.tile_width_dropdown.get_value())
self.tile_size = (height, width)
self.clip_limit = int(self.clip_limit_dropdown.get_value())
[docs] def run_single_video(self):
selected_video = self.selected_video.file_path
check_file_exist_and_readable(file_path=selected_video)
self._get_settings()
if self.core_cnt > 1: pool = get_cpu_pool(core_cnt=self.core_cnt, source=self.__class__.__name__)
else: pool = None
stdout_information(msg=f'Applying CLAHE conversion on video {selected_video}...')
if self.core_cnt == 1:
threading.Thread(target=clahe_enhance_video(file_path=selected_video, clip_limit=self.clip_limit, tile_grid_size=self.tile_size)).start()
else:
threading.Thread(target=clahe_enhance_video_mp(file_path=selected_video, clip_limit=self.clip_limit, tile_grid_size=self.tile_size, core_cnt=self.core_cnt, pool=pool)).start()
[docs] def run_directory(self):
timer = SimbaTimer(start=True)
video_dir = self.selected_dir.folder_path
check_if_dir_exists(in_dir=video_dir, source=self.__class__.__name__)
self.video_paths = find_files_of_filetypes_in_directory(directory=video_dir, extensions=Options.ALL_VIDEO_FORMAT_OPTIONS.value, raise_error=True)
self._get_settings()
stdout_information(msg=f'Applying CLAHE conversion on {len(self.video_paths)} videos...')
if self.core_cnt > 1:
pool = get_cpu_pool(core_cnt=self.core_cnt, source=self.__class__.__name__)
else:
pool = None
for file_path in self.video_paths:
if self.core_cnt == 1:
threading.Thread(target=clahe_enhance_video(file_path=file_path, clip_limit=self.clip_limit, tile_grid_size=self.tile_size)).start()
else:
clahe_enhance_video_mp(file_path=file_path, gpu=self.gpu, clip_limit=self.clip_limit, tile_grid_size=self.tile_size, pool=pool)
if pool is not None: terminate_cpu_pool(pool=pool, source=self.__class__.__name__)
timer.stop_timer()
stdout_success(msg=f'CLAHE enhanced {len(self.video_paths)} video(s)', elapsed_time=timer.elapsed_time_str)
[docs]class CropVideoPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CROP VIDEO(S)", icon='crop')
crop_video_lbl_frm = LabelFrame( self.main_frm, text="CROP SINGLE VIDEO", font=Formats.FONT_HEADER.value)
gpu_state = NORMAL if check_nvidea_gpu_available() else DISABLED
selected_video = FileSelect(crop_video_lbl_frm, "VIDEO PATH: ", title="Select a video file", lblwidth=20, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='browse')
self.single_video_gpu_dropdown = SimBADropDown(parent=crop_video_lbl_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=20, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
self.single_quality_dropdown = SimBADropDown(parent=crop_video_lbl_frm, dropdown_options=list(range(1, 101, 1)), label='OUTPUT VIDEO QUALITY: ',label_width=20, dropdown_width=20, value=60, img='pct_2', tooltip_key="OUPUT_VIDEO_QUALITY")
button_crop_video_single = SimbaButton(parent=crop_video_lbl_frm, txt="CROP SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=crop_single_video, cmd_kwargs={'file_path': lambda: selected_video.file_path, 'gpu': lambda: str_2_bool(self.single_video_gpu_dropdown.get_value()), 'quality': lambda: int(self.single_quality_dropdown.get_value())})
crop_video_lbl_frm_multiple = LabelFrame(self.main_frm, text="CROP MULTIPLE VIDEOS", font=Formats.FONT_HEADER.value, padx=5, pady=5)
instructions_1 = SimBALabel(parent=crop_video_lbl_frm_multiple, txt="The crop coordinates you draw in the first video,\n will be applied on all videos in directory.", font=Formats.FONT_REGULAR_ITALICS.value)
instructions_2 = SimBALabel(parent=crop_video_lbl_frm_multiple, txt="To draw crop coordinates on each individual video,\n instead use SimBA batch processing.", font=Formats.FONT_REGULAR_ITALICS.value)
input_folder = FolderSelect(crop_video_lbl_frm_multiple, "VIDEO DIRECTORY:", title="Select Folder with videos", lblwidth=20, lbl_icon='browse')
output_folder = FolderSelect(crop_video_lbl_frm_multiple,"OUTPUT DIRECTORY:",title="Select a folder for your output videos",lblwidth=20, lbl_icon='browse')
self.multiple_video_gpu_dropdown = SimBADropDown(parent=crop_video_lbl_frm_multiple, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=20, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
self.multiple_quality_dropdown = SimBADropDown(parent=crop_video_lbl_frm_multiple, dropdown_options=list(range(1, 101, 1)), label='OUTPUT VIDEO QUALITY: ',label_width=20, dropdown_width=20, value=60, img='pct_2', tooltip_key="OUPUT_VIDEO_QUALITY")
button_crop_video_multiple = SimbaButton(parent=crop_video_lbl_frm_multiple, txt="CROP VIDEO DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=crop_multiple_videos, cmd_kwargs={'directory_path': lambda:input_folder.folder_path, 'output_path': lambda:output_folder.folder_path, 'quality': lambda: int(self.multiple_quality_dropdown.get_value()), 'gpu': str_2_bool(self.multiple_video_gpu_dropdown.get_value())})
crop_video_lbl_frm.grid(row=0, sticky=NW)
selected_video.grid(row=0, sticky=NW)
self.single_video_gpu_dropdown.grid(row=1, column=0, sticky=NW)
self.single_quality_dropdown.grid(row=2, column=0, sticky=NW)
button_crop_video_single.grid(row=3, sticky=NW)
crop_video_lbl_frm_multiple.grid(row=1, sticky=NW)
instructions_1.grid(row=0, sticky=NW)
instructions_2.grid(row=1, sticky=NW)
input_folder.grid(row=2, sticky=NW)
output_folder.grid(row=3, sticky=NW)
self.multiple_video_gpu_dropdown.grid(row=4, sticky=NW)
self.multiple_quality_dropdown.grid(row=5, column=0, sticky=NW)
button_crop_video_multiple.grid(row=6, sticky=NW)
self.main_frm.mainloop()
#_ = CropVideoPopUp()
[docs]class ClipVideoPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CLIP VIDEO", icon='clip')
selected_video_frm = CreateLabelFrameWithIcon( parent=self.main_frm, header="Video path", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(selected_video_frm, "FILE PATH: ", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2', lblwidth=35)
self.selected_video.grid(row=0, column=0, sticky="NW")
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name='settings', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5)
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=35, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_available, tooltip_key='USE_GPU')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, 101, 1)), label='OUTPUT VIDEO QUALITY: ', label_width=35, dropdown_width=20, value=60, img='pct_2', tooltip_key='OUPUT_VIDEO_QUALITY')
self.gpu_dropdown.grid(row=0, column=0, sticky=NW)
self.quality_dropdown.grid(row=1, column=0, sticky=NW)
method_1_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="METHOD 1", icon_name='circle_black', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5)
label_set_time_1 = SimBALabel(parent=method_1_frm, txt="Please enter the time frame in HH:MM:SS format", font=Formats.FONT_REGULAR_ITALICS.value)
self.start_time = Entry_Box(method_1_frm, fileDescription="START AT (HH:MM:SS):", labelwidth=35, img='play', justify='center', trace=self._check_valid_timestamp)
self.end_time = Entry_Box(method_1_frm, fileDescription="END AT (HH:MM:SS):", labelwidth=35, img='stop', justify='center', trace=self._check_valid_timestamp)
CreateToolTip(method_1_frm, "Method 1 will retrieve the specified time input. (eg: input of Start at: 00:00:00, End at: 00:01:00, will create a new video from the chosen video from the very start till it reaches the first minute of the video)")
button_cutvideo_method_1 = SimbaButton(parent=method_1_frm, txt="CUT VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=clip_video_in_range, cmd_kwargs={'file_path': lambda: self.selected_video.file_path, 'quality': lambda: self.quality_dropdown.get_value(), 'start_time': lambda:self.start_time.entry_get.strip(), 'end_time': lambda:self.end_time.entry_get.strip(), 'gpu': lambda: str_2_bool(self.gpu_dropdown.get_value())})
button_cutvideo_method_1.grid(row=3, column=0, sticky=NW)
clipper_ui_btn = SimbaButton(parent=method_1_frm, txt="TIMELAPSE VIEWER", img='monitor', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.initiate_clipper)
clipper_ui_btn.grid(row=4, column=0, sticky=NW)
method_2_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="METHOD 2", icon_name='circle_black', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5)
method_2_time = Entry_Box(method_2_frm, "SECONDS:", labelwidth=35, validation="numeric", img='timer', justify='center')
label_method_2 = SimBALabel(parent=method_2_frm, txt="Retrieve from the END of the video (e.g.,: an input of 3 will get rid of the FIRST 3 seconds of the video).", font=Formats.FONT_REGULAR_ITALICS.value)
button_cutvideo_method_2 = SimbaButton(parent=method_2_frm, txt="CUT VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=remove_beginning_of_video, cmd_kwargs={'file_path': lambda:self.selected_video.file_path, 'time': lambda:method_2_time.entry_get, 'gpu': lambda: str_2_bool(self.gpu_dropdown.get_value()), 'quality': lambda: self.quality_dropdown.get_value()})
selected_video_frm.grid(row=0, sticky=NW)
settings_frm.grid(row=1, column=0, sticky=NW)
method_1_frm.grid(row=2, sticky=NW, pady=5)
label_set_time_1.grid(row=0, sticky=NW)
self.start_time.grid(row=1, sticky=NW)
self.end_time.grid(row=2, sticky=NW)
method_2_frm.grid(row=3, sticky=NW, pady=5)
label_method_2.grid(row=0, sticky=NW)
method_2_time.grid(row=2, sticky=NW)
button_cutvideo_method_2.grid(row=3, sticky=NW)
method_3_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="METHOD 3", icon_name='circle_black', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5)
method_3_time = Entry_Box(method_3_frm, "SECONDS:", labelwidth=35, validation="numeric", img='timer_2', justify='center')
label_method_3 = SimBALabel(parent=method_3_frm, txt="Retrieve from the BEGINNING of the video (e.g.,: an input of 3 will get rid of the LAST 3 seconds of the video).", font=Formats.FONT_REGULAR_ITALICS.value)
button_cutvideo_method_3 = SimbaButton(parent=method_3_frm, txt="CUT VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=remove_end_of_video, cmd_kwargs={'file_path': lambda:self.selected_video.file_path, 'time': lambda:method_3_time.entry_get, 'gpu': lambda: str_2_bool(self.gpu_dropdown.get_value()), 'quality': lambda: self.quality_dropdown.get_value()})
method_3_frm.grid(row=4, column=0, sticky=NW)
label_method_3.grid(row=0, column=0, sticky=NW)
method_3_time.grid(row=1, column=0, sticky=NW)
button_cutvideo_method_3.grid(row=2, column=0, sticky=NW)
#self.main_frm.mainloop()
def _check_valid_timestamp(self, entry_box: Entry_Box, valid_clr: str = 'lightgreen', invalid_clr: str = 'white'):
valid_time_stamp = check_if_string_value_is_valid_video_timestamp(value=entry_box.entry_get, raise_error=False, name='')
clr = valid_clr if valid_time_stamp else invalid_clr
entry_box.set_bg_clr(clr=clr)
[docs] def initiate_clipper(self):
check_file_exist_and_readable(file_path=self.selected_video.file_path, raise_error=True)
_ = get_video_meta_data(video_path=self.selected_video.file_path)
def exit_click(event):
self.click_event.set(True)
interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
interactive_ui.close()
def window_closed():
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
if interactive_ui.img_window.winfo_exists(): interactive_ui.close()
self.click_event.set(True)
interactive_ui = TimelapseSlider(video_path=self.selected_video.file_path)
interactive_ui.run()
self.click_event = BooleanVar(value=False)
interactive_ui.img_window.protocol("WM_DELETE_WINDOW", window_closed)
interactive_ui.img_window.bind(TkBinds.ESCAPE.value, exit_click); self.main_frm.bind(TkBinds.ESCAPE.value, exit_click)
self.main_frm.wait_variable(self.click_event)
try:
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
except: pass
try:
self.main_frm.unbind(TkBinds.ESCAPE.value)
except:
pass
if not interactive_ui.img_window.winfo_exists(): pass
start_time, end_time = interactive_ui.get_start_time_str(), interactive_ui.get_end_time_str()
self.start_time.entry_set(start_time)
self.end_time.entry_set(end_time)
#ClipVideoPopUp()
[docs]class GreyscaleSingleVideoPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="GREYSCALE VIDEO", icon='grey')
video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="GREYSCALE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect( video_frm, "VIDEO FILE PATH", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='browse')
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.quality_dropdown_video = SimBADropDown(parent=video_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY: ", label_width=25, dropdown_width=20, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=video_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=25, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_available, tooltip_key='USE_GPU')
run_video_btn = SimbaButton(parent=video_frm, txt="RUN ON SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_video)
dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="GREYSCALE VIDEO DIRECTORY", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.dir_selected = FolderSelect(dir_frm, "VIDEO DIRECTORY PATH", title="Select folder with videos", lblwidth=25, lbl_icon='browse')
self.quality_dropdown_dir = SimBADropDown(parent=dir_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY: ", label_width=25, dropdown_width=20, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown_multiple = SimBADropDown(parent=dir_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=25, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_available, tooltip_key='USE_GPU')
run_dir_btn = SimbaButton(parent=dir_frm, txt="RUN ON DIRECTORY OF VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_dir)
video_frm.grid(row=0, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
self.quality_dropdown_video.grid(row=1, column=0, sticky="NW")
self.gpu_dropdown.grid(row=2, column=0, sticky="NW")
run_video_btn.grid(row=3, column=0, sticky="NW")
dir_frm.grid(row=1, column=0, sticky="NW")
self.dir_selected.grid(row=0, column=0, sticky="NW")
self.quality_dropdown_dir.grid(row=1, column=0, sticky="NW")
self.gpu_dropdown_multiple.grid(row=2, column=0, sticky="NW")
run_dir_btn.grid(row=3, column=0, sticky="NW")
[docs] def run_video(self):
check_file_exist_and_readable(file_path=self.selected_video.file_path)
quality_crf = quality_pct_to_crf(pct=int(self.quality_dropdown_video.get_value()))
video_to_greyscale(file_path=self.selected_video.file_path, gpu=str_2_bool(self.gpu_dropdown.get_value()), quality=quality_crf)
[docs] def run_dir(self):
check_if_dir_exists(in_dir=self.dir_selected.folder_path)
quality_crf = quality_pct_to_crf(pct=int(self.quality_dropdown_dir.get_value()))
batch_video_to_greyscale(path=self.dir_selected.folder_path, gpu=str_2_bool(self.gpu_dropdown_multiple.get_value()), quality=quality_crf)
#_ = GreyscaleSingleVideoPopUp()
[docs]class SuperImposeFrameCountPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="SUPERIMPOSE FRAME COUNT", icon='number_black')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
color_dict = list(get_color_dict().keys())
font_dict = get_fonts()
self.LOCS = {'TOP LEFT': 'top_left', 'TOP MIDDLE': 'top_middle', 'TOP RIGHT': 'top_right', 'BOTTOM LEFT': 'bottom_left', 'BOTTOM MIDDLE': 'bottom_middle', 'BOTTOM RIGHT': 'bottom_right'}
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=25, dropdown_width=35, value='FALSE', img='gpu_3', state=gpu_available, tooltip_key='USE_GPU')
self.font_size_dropdown = SimBADropDown(parent=settings_frm, dropdown_width=35, dropdown_options=list(range(1, 101, 2)), label="FONT SIZE:", label_width=25, value=20, img='font_size', tooltip_key='SUPERIMPOSE_FRAME_COUNT_FONT_SIZE')
self.font_color_dropdown = SimBADropDown(parent=settings_frm, dropdown_width=35, dropdown_options=color_dict, label="FONT COLOR:", label_width=25, value='Black', img='text_color', tooltip_key='SUPERIMPOSE_FRAME_COUNT_FONT_COLOR')
self.font_bg_color_dropdown = SimBADropDown(parent=settings_frm, dropdown_width=35, dropdown_options=color_dict, label="FONT BACKGROUND COLOR:", label_width=25, value='White', img='fill', tooltip_key='SUPERIMPOSE_FRAME_COUNT_FONT_BACKGROUND_COLOR')
self.font_dropdown = SimBADropDown(parent=settings_frm, dropdown_width=35, dropdown_options=list(font_dict.keys()), label="FONT:", label_width=25, value='Arial', img='font', tooltip_key='SUPERIMPOSE_FRAME_COUNT_FONT')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY: ", label_width=25, dropdown_width=35, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.loc_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.LOCS.keys()), label="FRAME COUNT POSITION: ", label_width=25, dropdown_width=35, value='BOTTOM MIDDLE', img='location', tooltip_key='LOCATION_FRAME_COUNT')
settings_frm.grid(row=0, column=0, sticky="NW")
self.font_size_dropdown.grid(row=0, column=0, sticky="NW")
self.font_color_dropdown.grid(row=1, column=0, sticky="NW")
self.font_bg_color_dropdown.grid(row=2, column=0, sticky="NW")
self.font_dropdown.grid(row=3, column=0, sticky="NW")
self.quality_dropdown.grid(row=4, column=0, sticky="NW")
self.loc_dropdown.grid(row=5, column=0, sticky="NW")
self.gpu_dropdown.grid(row=6, column=0, sticky="NW")
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - SUPERIMPOSE FRAME COUNT", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)])
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_single_video)
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - SUPERIMPOSE FRAME COUNT", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25)
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_multiple_videos)
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
self.main_frm.mainloop()
[docs] def run_single_video(self):
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=self.selected_video.file_path)
self.video_paths = [video_path]
self.apply()
[docs] def run_multiple_videos(self):
video_dir = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=video_dir, source=self.__class__.__name__)
self.video_paths = find_files_of_filetypes_in_directory(directory=video_dir, extensions=Options.ALL_VIDEO_FORMAT_OPTIONS.value, raise_error=True)
self.apply()
[docs] def apply(self):
check_ffmpeg_available(raise_error=True)
timer = SimbaTimer(start=True)
use_gpu = str_2_bool(self.gpu_dropdown.get_value())
font = self.font_dropdown.getChoices()
font_clr = self.font_color_dropdown.getChoices()
font_bg_clr = self.font_bg_color_dropdown.getChoices()
font_size = int(self.font_size_dropdown.getChoices())
quality_crf = quality_pct_to_crf(pct=int(self.quality_dropdown.get_value()))
location = self.LOCS[self.loc_dropdown.get_value()]
for file_cnt, file_path in enumerate(self.video_paths):
check_file_exist_and_readable(file_path=file_path)
superimpose_frame_count(file_path=file_path,
gpu=use_gpu,
quality=quality_crf,
fontsize=font_size,
font_color=font_clr,
font=font,
loc=location,
bg_color=font_bg_clr)
timer.stop_timer()
stdout_success(msg=f'Frame counts superimposed on {len(self.video_paths)} video(s)', elapsed_time=timer.elapsed_time_str)
#_ = SuperImposeFrameCountPopUp()
[docs]class MultiShortenPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CLIP VIDEO INTO MULTIPLE VIDEOS", size=(800, 200), icon='clip')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm,header="SETTINGS",icon_name=Keys.DOCUMENTATION.value,icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(settings_frm, "VIDEO PATH", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2')
self.clip_cnt = Entry_Box(settings_frm, "# OF CLIPS", labelwidth=25, validation="numeric", img='abacus_2', justify='center')
gpu_available = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU', label_width=25, dropdown_width=25, value='FALSE', state=gpu_available, img='gpu_3')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT QUALITY: ", label_width=25, dropdown_width=25, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
confirm_settings_btn = SimbaButton(parent=settings_frm, txt="CONFIRM", img='tick', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.show_start_stop)
settings_frm.grid(row=0, sticky=NW)
self.selected_video.grid(row=1, sticky=NW, columnspan=2)
self.quality_dropdown.grid(row=2, column=0, sticky=W)
self.gpu_dropdown.grid(row=3, column=0, sticky=W)
self.clip_cnt.grid(row=4, column=0, sticky=NW)
confirm_settings_btn.grid(row=4, column=1, sticky=W)
batch_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="BATCH CHANGE TIME", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.batch_start_entry = Entry_Box(batch_frm, "START:", labelwidth=10, entry_box_width=10, justify='center', value="00:00:00")
self.batch_end_entry = Entry_Box(batch_frm, "END", labelwidth=10, entry_box_width=10, justify='center', value="00:00:00")
batch_start_apply = SimbaButton(parent=batch_frm, txt="APPLY", font=Formats.FONT_REGULAR.value, cmd=self.batch_change, cmd_kwargs={'value': "start"})
batch_end_apply = SimbaButton(parent=batch_frm, txt="APPLY", font=Formats.FONT_REGULAR.value, cmd=self.batch_change, cmd_kwargs={'value': "end"})
batch_frm.grid(row=0, column=1, sticky=NW)
self.batch_start_entry.grid(row=0, column=0, sticky=NW)
batch_start_apply.grid(row=0, column=1, sticky=NW)
self.batch_end_entry.grid(row=1, column=0, sticky=NW)
batch_end_apply.grid(row=1, column=1, sticky=NW)
self.main_frm.mainloop()
[docs] def show_start_stop(self):
check_int(name="Number of clips", value=self.clip_cnt.entry_get)
if hasattr(self, "table"):
self.table.destroy()
self.table = CreateLabelFrameWithIcon(parent=self.main_frm, header="SET TIMES", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.table.grid(row=2, column=0, sticky=NW)
instructions = SimBALabel(parent=self.table, txt="Enter clip start and stop times in HH:MM:SS format", font=Formats.FONT_REGULAR_ITALICS.value, txt_clr='blue')
instructions.grid(row=0, column=0, columnspan=3)
SimBALabel(parent=self.table, txt="CLIP #", font=Formats.FONT_REGULAR.value).grid(row=1, column=0)
SimBALabel(parent=self.table, txt="START TIME", font=Formats.FONT_REGULAR.value).grid(row=1, column=1, sticky=NW)
SimBALabel(parent=self.table, txt="STOP TIME", font=Formats.FONT_REGULAR.value).grid(row=1, column=2, sticky=NW)
self.clip_names, self.start_times, self.end_times = [], [], []
for i in range(int(self.clip_cnt.entry_get)):
SimBALabel(parent=self.table, txt=f"CLIP {i + 1}", font=Formats.FONT_REGULAR.value).grid(row=i + 2, sticky=W)
self.start_times.append(Entry(self.table))
self.start_times[i].grid(row=i + 2, column=1, sticky=NW)
self.end_times.append(Entry(self.table))
self.end_times[i].grid(row=i + 2, column=2, sticky=NW)
run_button = SimbaButton(parent=self.table, txt='CLIP VIDEO', cmd=self.run_clipping, img='rocket')
run_button.grid(row=int(self.clip_cnt.entry_get) + 2, column=2, sticky=W)
[docs] def batch_change(self, value: str):
if not hasattr(self, "table"):
raise CountError(
msg="Select the number of video clippings first",
source=self.__class__.__name__,
)
for start_time_entry, end_time_entry in zip(self.start_times, self.end_times):
if value == "start":
start_time_entry.delete(0, END)
start_time_entry.insert(0, self.batch_start_entry.entry_get)
else:
end_time_entry.delete(0, END)
end_time_entry.insert(0, self.batch_end_entry.entry_get)
[docs] def run_clipping(self):
start_times, end_times = [], []
check_file_exist_and_readable(self.selected_video.file_path)
gpu = str_2_bool(self.gpu_dropdown.get_value())
quality = quality_pct_to_crf(pct=int(self.quality_dropdown.get_value()))
for start_time, end_time in zip(self.start_times, self.end_times):
start_times.append(start_time.get())
end_times.append(end_time.get())
multi_split_video(
file_path=self.selected_video.file_path,
start_times=start_times,
end_times=end_times,
gpu=gpu,
quality=quality,
)
#_ = MultiShortenPopUp()
[docs]class ChangeImageFormatPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CHANGE IMAGE FORMAT")
self.input_folder_selected = FolderSelect(self.main_frm, "Image directory", title="Select folder with images:")
set_input_format_frm = LabelFrame(self.main_frm, text="Original image format", font=Formats.FONT_HEADER.value, padx=15, pady=5)
set_output_format_frm = LabelFrame(self.main_frm, text="Output image format", font=Formats.FONT_HEADER.value, padx=15, pady=5)
self.input_file_type, self.out_file_type = StringVar(), StringVar()
input_png_rb = Radiobutton(set_input_format_frm, text=".png", variable=self.input_file_type, value="png", font=Formats.FONT_REGULAR.value)
input_jpeg_rb = Radiobutton(
set_input_format_frm,
text=".jpg",
variable=self.input_file_type,
value="jpg",
font=Formats.FONT_REGULAR.value,
)
input_bmp_rb = Radiobutton(
set_input_format_frm,
text=".bmp",
variable=self.input_file_type,
value="bmp",
font=Formats.FONT_REGULAR.value,
)
output_png_rb = Radiobutton(
set_output_format_frm, text=".png", font=Formats.FONT_REGULAR.value, variable=self.out_file_type, value="png"
)
output_jpeg_rb = Radiobutton(
set_output_format_frm, text=".jpg", font=Formats.FONT_REGULAR.value, variable=self.out_file_type, value="jpg"
)
output_bmp_rb = Radiobutton(
set_output_format_frm, text=".bmp", font=Formats.FONT_REGULAR.value, variable=self.out_file_type, value="bmp"
)
run_btn = Button(
self.main_frm,
text="Convert image file format",
font=Formats.FONT_REGULAR.value,
command=lambda: self.run_img_conversion(),
)
self.input_folder_selected.grid(row=0, column=0)
set_input_format_frm.grid(row=1, column=0, pady=5)
set_output_format_frm.grid(row=2, column=0, pady=5)
input_png_rb.grid(row=0, column=0)
input_jpeg_rb.grid(row=1, column=0)
input_bmp_rb.grid(row=2, column=0)
output_png_rb.grid(row=0, column=0)
output_jpeg_rb.grid(row=1, column=0)
output_bmp_rb.grid(row=2, column=0)
run_btn.grid(row=3, pady=5)
[docs] def run_img_conversion(self):
if len(os.listdir(self.input_folder_selected.folder_path)) == 0:
raise NoFilesFoundError(
msg="SIMBA ERROR: The input folder {} contains ZERO files.".format(
self.input_folder_selected.folder_path
),
source=self.__class__.__name__,
)
change_img_format(
directory=self.input_folder_selected.folder_path,
file_type_in=self.input_file_type.get(),
file_type_out=self.out_file_type.get(),
)
#_ = ChangeImageFormatPopUp()
[docs]class ConvertVideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CONVERT VIDEO FORMAT", size=(200, 200))
convert_multiple_videos_frm = CreateLabelFrameWithIcon(
parent=self.main_frm,
header="Convert multiple videos",
icon_name=Keys.DOCUMENTATION.value,
icon_link=Links.VIDEO_TOOLS.value,
)
video_dir = FolderSelect(
convert_multiple_videos_frm,
"Video directory",
title="Select folder with videos",
lblwidth=15,
)
video_format_options = ["mp4", "avi", "mov", "flv", "m4v"]
original_format_dropdown = DropDownMenu(
convert_multiple_videos_frm,
"Input format",
video_format_options,
labelwidth=15,
)
output_format_dropdown = DropDownMenu(
convert_multiple_videos_frm,
"Input format",
video_format_options,
labelwidth=15,
)
original_format_dropdown.setChoices("avi")
output_format_dropdown.setChoices("mp4")
gpu_multiple_var = BooleanVar(value=False)
gpu_multiple_cb = Checkbutton(
convert_multiple_videos_frm,
text="Use GPU (reduced runtime)",
font=Formats.FONT_REGULAR.value,
variable=gpu_multiple_var,
)
convert_multiple_btn = Button(
convert_multiple_videos_frm,
text="Convert multiple videos",
font=Formats.FONT_REGULAR.value,
command=lambda: batch_convert_video_format(
directory=video_dir.folder_path,
input_format=original_format_dropdown.getChoices(),
output_format=output_format_dropdown.getChoices(),
gpu=gpu_multiple_var.get(),
),
)
convert_single_video_frm = LabelFrame(
self.main_frm,
text="Convert single video",
font=Formats.FONT_HEADER.value,
padx=5,
pady=5,
)
self.selected_video = FileSelect(
convert_single_video_frm,
"Video path",
title="Select a video file",
file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)],
)
self.output_format = StringVar()
checkbox_v1 = Radiobutton(
convert_single_video_frm,
text="Convert to .mp4",
font=Formats.FONT_REGULAR.value,
variable=self.output_format,
value="mp4",
)
checkbox_v2 = Radiobutton(
convert_single_video_frm,
text="Convert mp4 into PowerPoint supported format",
font=Formats.FONT_REGULAR.value,
variable=self.output_format,
value="pptx",
)
self.gpu_single_var = BooleanVar(value=False)
gpu_single_cb = Checkbutton(
convert_single_video_frm,
text="Use GPU (reduced runtime)",
font=Formats.FONT_REGULAR.value,
variable=self.gpu_single_var,
)
convert_single_btn = Button(
convert_single_video_frm,
text="Convert video format",
font=Formats.FONT_REGULAR.value,
command=lambda: self.convert_single(),
)
convert_multiple_videos_frm.grid(row=0, sticky=NW)
video_dir.grid(row=0, sticky=NW)
original_format_dropdown.grid(row=1, sticky=NW)
output_format_dropdown.grid(row=2, sticky=NW)
gpu_multiple_cb.grid(row=3, sticky=NW)
convert_multiple_btn.grid(row=4, pady=10, sticky=NW)
convert_single_video_frm.grid(row=1, sticky=NW)
self.selected_video.grid(row=0, sticky=NW)
checkbox_v1.grid(row=1, column=0, sticky=NW)
checkbox_v2.grid(row=2, column=0, sticky=NW)
gpu_single_cb.grid(row=3, column=0, sticky=NW)
convert_single_btn.grid(row=4, column=0, pady=10, sticky=NW)
[docs] def convert_single(self):
if self.output_format.get() == "mp4":
convert_to_mp4(
file_path=self.selected_video.file_path, gpu=self.gpu_single_var.get()
)
if self.output_format.get() == "pptx":
convert_video_powerpoint_compatible_format(
file_path=self.selected_video.file_path, gpu=self.gpu_single_var.get()
)
[docs]class ExtractSpecificFramesPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="EXTRACT DEFINED FRAME RANGE FROM SINGLE VIDEO", icon='frames')
self.settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm,header="SETTINGS", icon_name=Keys.DOCUMENTATION.value,icon_link=Links.VIDEO_TOOLS.value)
self.video_file_selected = FileSelect(self.settings_frm , "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=40, lbl_icon='video_2')
self.save_dir = FolderSelect(self.settings_frm, "SAVE DIRECTORY: ", lblwidth=40, tooltip_txt='Optional directory where to save the images. \n If None, images are saved in a folder with the suffix `_frames` \n within the same directory as the video file', lbl_icon='folder')
self.format_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=['jpeg', 'png', 'webp'], label="SAVE FORMAT: ", label_width=40, dropdown_width=25, value='png', img='file_type')
self.grey_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=['TRUE', 'FALSE'], label="GREYSCALE: ", label_width=40, dropdown_width=25, value='FALSE', img='grey')
self.clahe_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=['TRUE', 'FALSE'], label="CLAHE: ", label_width=40, dropdown_width=25, value='FALSE', img='clahe')
self.include_fn_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=['TRUE', 'FALSE'], label="INCLUDE VIDEO NAME IN IMAGE NAME: ", label_width=40, dropdown_width=25, value='FALSE', img='id_card_2')
self.start_frm = Entry_Box(parent=self.settings_frm, fileDescription="START FRAME NUMBER:", labelwidth=40, validation='numeric', width=25, img='play')
self.end_frm = Entry_Box(parent=self.settings_frm, fileDescription="END FRAME NUMBER:", labelwidth=40, validation='numeric', width=25, img='stop')
self.settings_frm.grid(row=0, column=0, sticky=NW)
self.video_file_selected.grid(row=0, column=0, sticky=NW)
self.save_dir.grid(row=1, column=0, sticky=NW)
self.format_dropdown.grid(row=2, column=0, sticky=NW)
self.grey_dropdown.grid(row=3, column=0, sticky=NW)
self.clahe_dropdown.grid(row=4, column=0, sticky=NW)
self.include_fn_dropdown.grid(row=5, column=0, sticky=NW)
self.start_frm.grid(row=6, column=0, sticky=NW)
self.end_frm.grid(row=7, column=0, sticky=NW)
run_btn = SimbaButton(parent=self.main_frm, txt="RUN", img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.start_frm_extraction)
run_btn.grid(row=1, column=0, pady=5, sticky=NW)
self.main_frm.mainloop()
[docs] def start_frm_extraction(self):
start_frame = self.start_frm.entry_get
end_frame = self.end_frm.entry_get
video_path = self.video_file_selected.file_path
check_file_exist_and_readable(file_path=video_path)
check_int(name="Start frame", value=start_frame)
check_int(name="End frame", value=end_frame)
if int(end_frame) < int(start_frame):
raise FrameRangeError(msg=f"SIMBA ERROR: The end frame ({end_frame}) cannot come before the start frame ({start_frame})", source=self.__class__.__name__)
video_meta_data = get_video_meta_data(video_path=self.video_file_selected.file_path)
if int(start_frame) > video_meta_data["frame_count"]:
raise FrameRangeError(msg=f"SIMBA ERROR: The start frame ({start_frame}) is larger than the number of frames in the video ({video_meta_data['frame_count']})", source=self.__class__.__name__)
if int(end_frame) > video_meta_data["frame_count"]:
raise FrameRangeError(msg=f"SIMBA ERROR: The end frame ({end_frame}) is larger than the number of frames in the video ({video_meta_data['frame_count']})", source=self.__class__.__name__)
grey = str_2_bool(self.grey_dropdown.get_value())
clahe = str_2_bool(self.clahe_dropdown.get_value())
include_fn = str_2_bool(self.include_fn_dropdown.get_value())
save_dir = self.save_dir.folder_path
save_dir = save_dir if os.path.isdir(save_dir) else None
img_format = self.format_dropdown.get_value()
extract_frame_range(file_path=video_path,
start_frame=int(start_frame),
end_frame=int(end_frame),
save_dir=save_dir,
greyscale=grey,
clahe=clahe,
img_format=img_format,
include_fn=include_fn)
#ExtractSpecificFramesPopUp()
[docs]class ExtractAllFramesPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="EXTRACT ALL FRAMES", icon='frames')
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm,header="SINGLE VIDEO",icon_name=Keys.DOCUMENTATION.value,icon_link=Links.VIDEO_TOOLS.value)
video_path = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)])
single_video_btn = SimbaButton(parent=single_video_frm, txt="Extract Frames (Single video)", img='rocket', font=Formats.FONT_REGULAR.value, cmd=extract_frames_single_video, cmd_kwargs={'file_path': lambda:video_path.file_path, 'save_dir': None})
multiple_videos_frm = CreateLabelFrameWithIcon( parent=self.main_frm, header="MULTIPLE VIDEOS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
folder_path = FolderSelect(multiple_videos_frm, "DIRECTORY PATH:", title=" Select video folder")
multiple_video_btn = SimbaButton(parent=multiple_videos_frm, txt="Extract Frames (Multiple videos)", img='rocket', font=Formats.FONT_REGULAR.value, cmd=batch_create_frames, cmd_kwargs={'directory': lambda:folder_path.folder_path})
single_video_frm.grid(row=0, sticky=NW, pady=10)
video_path.grid(row=0, sticky=NW)
single_video_btn.grid(row=1, sticky=W, pady=10)
multiple_videos_frm.grid(row=1, sticky=W, pady=10)
folder_path.grid(row=0, sticky=W)
multiple_video_btn.grid(row=1, sticky=W, pady=10)
[docs]class MultiCropPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="MULTI-CROP", size=(500, 300), icon='crop')
self.input_folder = FolderSelect(self.main_frm, "INPUT VIDEO FOLDER: ", lblwidth=25, lbl_icon='browse', tooltip_key='MULTICROP_INPUT_FOLDER')
self.output_folder = FolderSelect(self.main_frm, "OUTPUT FOLDER: ", lblwidth=25, lbl_icon='browse', tooltip_key='MULTICROP_OUTPUT_FOLDER')
video_options = Options.ALL_VIDEO_FORMAT_OPTIONS_2.value
self.video_type_dropdown = SimBADropDown(parent=self.main_frm, dropdown_options=video_options, label="INPUT VIDEO FORMAT: ", label_width=25, dropdown_width=25, value='mp4', img='file_type', tooltip_key='MULTICROP_INPUT_VIDEO_FORMAT')
self.crop_cnt_dropdown = SimBADropDown(parent=self.main_frm, dropdown_options=list(range(2, 31)), label="CROPS PER VIDEO: ", label_width=25, dropdown_width=25, value=2, img='abacus', tooltip_key='MULTICROP_CROPS_PER_VIDEO')
quality_options = list(percent_to_crf_lookup().keys())
self.quality_dropdown = SimBADropDown(parent=self.main_frm, dropdown_options=quality_options, label="CROP OUTPUT QUALITY: ", label_width=25, dropdown_width=25, value=60, img='pct', tooltip_key='MULTICROP_OUTPUT_QUALITY')
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=self.main_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ',label_width=25, dropdown_width=25, value='FALSE', img='gpu_3', state=gpu_available, tooltip_key='USE_GPU')
self.create_run_frm(run_function=self.run)
self.input_folder.grid(row=0, sticky=NW)
self.output_folder.grid(row=1, sticky=NW)
self.video_type_dropdown.grid(row=2, sticky=NW)
self.crop_cnt_dropdown.grid(row=3, sticky=NW)
self.quality_dropdown.grid(row=4, sticky=NW)
self.gpu_dropdown.grid(row=5, sticky=NW)
self.create_run_frm(run_function=self.run)
[docs] def run(self):
check_if_dir_exists(in_dir=self.input_folder.folder_path)
check_if_dir_exists(in_dir=self.output_folder.folder_path)
cropper = MultiCropper(file_type=self.video_type_dropdown.getChoices(),
input_folder=self.input_folder.folder_path,
output_folder=self.output_folder.folder_path,
crop_cnt=int(self.crop_cnt_dropdown.getChoices()),
gpu=str_2_bool(self.gpu_dropdown.get_value()),
quality=int(self.quality_dropdown.getChoices()))
cropper.run()
#_ = MultiCropPopUp()
[docs]class ChangeFpsSingleVideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CHANGE FRAME RATE: SINGLE VIDEO", size=(500, 300), icon='fps')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header='SETTINGS', icon_name='settings')
gpu_state = DISABLED if not check_nvidea_gpu_available() else NORMAL
self.video_path = FileSelect(settings_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='browse')
self.new_fps_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, 101, 1)), label='NEW FPS: ', label_width=25, dropdown_width=20, value=15, img='fps')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ', label_width=25, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label='OUTPUT VIDEO QUALITY: ', label_width=25, dropdown_width=20, value=60, img='pct_2', tooltip_key='OUPUT_VIDEO_QUALITY')
settings_frm.grid(row=0, column=0, sticky=NW)
self.video_path.grid(row=0, sticky=NW)
self.new_fps_dropdown.grid(row=1, sticky=NW)
self.quality_dropdown.grid(row=2, sticky=NW)
self.gpu_dropdown.grid(row=3, sticky=NW)
self.create_run_frm(run_function=self.run)
[docs] def run(self):
video_path = self.video_path.file_path
video_meta_data = get_video_meta_data(video_path=video_path)
_, video_name, _ = get_fn_ext(filepath=video_path)
new_fps = int(self.new_fps_dropdown.getChoices())
gpu = str_2_bool(self.gpu_dropdown.get_value())
if video_meta_data['fps'] <= new_fps:
FrameRangeWarning(msg=f'For video {video_name}, the new FPS ({new_fps}) is higher or the same as the original FPS ({video_meta_data["fps"]})', source=self.__class__.__name__)
quality = quality_pct_to_crf(pct=int(self.quality_dropdown.get_value()))
threading.Thread(change_single_video_fps(file_path=video_path, fps=new_fps, gpu=gpu, quality=quality)).start()
#_ = ChangeFpsSingleVideoPopUp()
[docs]class ChangeFpsMultipleVideosPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CHANGE FRAME RATE: MULTIPLE VIDEO", size=(500, 300), icon='fps')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header='SETTINGS', icon_name='settings')
gpu_state = DISABLED if not check_nvidea_gpu_available() else NORMAL
self.directory_path = FolderSelect(settings_frm, "VIDEO DIRECTORY PATH:", title="Select folder with videos: ", lblwidth=25, lbl_icon='browse')
self.new_fps_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, 101, 1)), label='NEW FPS: ', label_width=25, dropdown_width=20, value=15, img='fps')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU: ', label_width=25, dropdown_width=20, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label='OUTPUT VIDEO QUALITY: ', label_width=25, dropdown_width=20, value=60, img='pct_2', tooltip_key='OUPUT_VIDEO_QUALITY')
settings_frm.grid(row=0, column=0, sticky=NW)
self.directory_path.grid(row=0, sticky=NW)
self.new_fps_dropdown.grid(row=1, sticky=NW)
self.quality_dropdown.grid(row=2, sticky=NW)
self.gpu_dropdown.grid(row=3, sticky=NW)
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
video_dir = self.directory_path.folder_path
check_if_dir_exists(in_dir=video_dir)
_ = find_all_videos_in_directory(directory=video_dir, raise_error=True)
new_fps = int(self.new_fps_dropdown.getChoices())
gpu = str_2_bool(self.gpu_dropdown.get_value())
quality = quality_pct_to_crf(pct=int(self.quality_dropdown.get_value()))
threading.Thread(change_fps_of_multiple_videos(path=video_dir, fps=new_fps, gpu=gpu, quality=quality)).start()
#_ = ChangeFpsMultipleVideosPopUp()
[docs]class ExtractSEQFramesPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(
self, title="EXTRACT ALL FRAMES FROM SEQ FILE", size=(200, 200)
)
video_path = FileSelect(
self.main_frm,
"Video Path",
title="Select a video file: ",
file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)],
)
run_btn = Button(
self.main_frm,
text="Extract All Frames",
font=Formats.FONT_REGULAR.value,
command=lambda: extract_seq_frames(video_path.file_path),
)
video_path.grid(row=0)
run_btn.grid(row=1)
[docs]class MergeFrames2VideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="MERGE IMAGE DIRECTORY INTO VIDEO", icon='video')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.folder_path = FolderSelect(settings_frm, "IMAGE DIRECTORY: ", title="Select directory with frames: ", lblwidth=25)
self.video_fps_dropdown = DropDownMenu(settings_frm, "VIDEO FPS:", list(range(1, 101, 1)), labelwidth=25)
self.video_quality_dropdown = DropDownMenu(settings_frm, "VIDEO QUALITY:", list(range(10, 110, 10)), labelwidth=25)
self.video_format_dropdown = DropDownMenu(settings_frm, "VIDEO FORMAT:", ['mp4', 'avi', 'webm'], labelwidth=25)
gpu_cb, self.gpu_var = SimbaCheckbox(parent=settings_frm, txt="Use GPU (reduced runtime)", txt_img='gpu_2')
self.video_quality_dropdown.setChoices(60)
self.video_format_dropdown.setChoices('mp4')
self.video_fps_dropdown.setChoices(30)
settings_frm.grid(row=0, column=0, sticky=NW)
self.folder_path.grid(row=0, column=0, sticky=NW)
self.video_fps_dropdown.grid(row=1, column=0, sticky=NW)
self.video_quality_dropdown.grid(row=2, column=0, sticky=NW)
self.video_format_dropdown.grid(row=3, column=0, sticky=NW)
gpu_cb.grid(row=4, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
directory = self.folder_path.folder_path
_ = find_files_of_filetypes_in_directory(directory=directory, extensions=Options.ALL_IMAGE_FORMAT_OPTIONS.value, raise_error=True, raise_warning=False)
fps = int(self.video_fps_dropdown.getChoices())
quality = int(self.video_quality_dropdown.getChoices())
gpu = self.gpu_var.get()
format = self.video_format_dropdown.getChoices()
threading.Thread(frames_to_movie(directory=self.folder_path.folder_path,
fps=fps,
quality=quality,
out_format=format,
gpu=gpu)).start()
[docs]class CreateGIFPopUP(PopUpMixin):
def __init__(self):
resolution_widths = Options.RESOLUTION_OPTIONS_2.value
fps_lst = list(range(1, 101, 1))
fps_lst.insert(0, 'AUTO')
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
PopUpMixin.__init__(self, title="CREATE GIF FROM VIDEO", size=(600, 400), icon='gif')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
info_lbl = SimBALabel(parent=self.main_frm, txt='Consider creating WEBM videos instead of creating GIFs.\n WEBM is optimized for web publish at \nconsiderbly smaller sizes than GIFs.', txt_clr='blue', font=Formats.FONT_REGULAR_ITALICS.value, justify='center')
self.selected_video = FileSelect(settings_frm, "VIDEO PATH: ", title="Select a video file", file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=40, lbl_icon='video_2')
self.start_time_entry_box = Entry_Box(parent=settings_frm, fileDescription="START TIME (s):", labelwidth=40, validation="numeric", img='play', width=25)
self.duration_entry_box = Entry_Box(parent=settings_frm, fileDescription="DURATION (s):", labelwidth=40, validation="numeric", img='stop', width=25)
self.resolution_dropdown = SimBADropDown(parent=settings_frm, label="GIF WIDTH (ASPECT RATIO RETAINED):", dropdown_options=resolution_widths, label_width=40, dropdown_width=25, value='AUTO', img='monitor')
self.quality_dropdown = SimBADropDown(parent=settings_frm, label="GIF QUALITY (%):", dropdown_options=list(range(1, 101, 1)), label_width=40, dropdown_width=25, value=100, img='pct_2')
self.fps_dropdown = SimBADropDown(parent=settings_frm, label="GIF FPS:", dropdown_options=fps_lst, label_width=40, dropdown_width=25, value='AUTO', img='fps')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], label_width=40, dropdown_width=25, value='FALSE', img='gpu_3', state=gpu_state)
info_lbl.grid(row=0, sticky=NW)
settings_frm.grid(row=1, sticky=NW)
self.selected_video.grid(row=0, sticky=NW, pady=5)
self.start_time_entry_box.grid(row=1, sticky=NW)
self.duration_entry_box.grid(row=2, sticky=NW)
self.resolution_dropdown.grid(row=3, sticky=NW)
self.quality_dropdown.grid(row=4, sticky=NW)
self.fps_dropdown.grid(row=5, sticky=NW)
self.gpu_dropdown.grid(row=6, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
video_path = self.selected_video.file_path
width = self.resolution_dropdown.getChoices()
start_time = self.start_time_entry_box.entry_get
duration = self.duration_entry_box.entry_get
fps = self.fps_dropdown.getChoices()
quality = int(self.quality_dropdown.getChoices())
gpu = self.gpu_dropdown.get_value()
check_ffmpeg_available()
if gpu: check_nvidea_gpu_available()
check_file_exist_and_readable(file_path=video_path)
video_meta_data = get_video_meta_data(video_path=video_path)
if width == 'AUTO': width = video_meta_data['width']
else: width = int(width)
if fps == 'AUTO': fps = int(video_meta_data['fps'])
else: fps = int(fps)
if fps > int(video_meta_data['fps']):
FrameRangeWarning(msg=f'The chosen FPS ({fps}) is higher than the video FPS ({video_meta_data["fps"]}). The video FPS will be used ({video_meta_data["fps"]})', source=self.__class__.__name__)
fps = int(video_meta_data['fps'])
max_duration = video_meta_data['video_length_s'] - int(start_time)
check_int(name='start_time', value=start_time, max_value=video_meta_data['video_length_s'], min_value=0)
check_int(name='duration', value=duration, max_value=max_duration, min_value=1)
threading.Thread(target=gif_creator(file_path=video_path,
start_time=int(start_time),
duration=int(duration),
width=width,
gpu=gpu,
fps=fps,
quality=int(quality))).start()
[docs]class CalculatePixelsPerMMInVideoPopUp(PopUpMixin):
"""
.. video:: _static/img/GetPixelsPerMillimeterInterface.webm
:width: 800
:autoplay:
:loop:
:muted:
:align: center
"""
def __init__(self):
PopUpMixin.__init__(self, title="CALCULATE PIXELS PER MILLIMETER IN VIDEO", size=(550, 550), icon='distance')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.video_path = FileSelect(settings_frm, "SELECT VIDEO FILE: ", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=40, lbl_icon='browse')
self.known_distance = Entry_Box(settings_frm, "KNOWN REAL LIFE METRIC DISTANCE (mm): ", labelwidth=40, validation="numeric", img='distance')
run_btn = SimbaButton(parent=settings_frm, txt="GET PIXELS PER MILLIMETER", img='rocket', font=Formats.FONT_REGULAR.value, cmd=self.run)
settings_frm.grid(row=0, column=0, sticky=NW)
self.video_path.grid(row=0, column=0, sticky=NW)
self.known_distance.grid(row=1, column=0, sticky=NW)
run_btn.grid(row=2, column=0, sticky=NW)
self.main_frm.mainloop()
[docs] def run(self):
check_file_exist_and_readable(file_path=self.video_path.file_path)
check_int(name="Distance", value=self.known_distance.entry_get, min_value=1)
_ = get_video_meta_data(video_path=self.video_path.file_path)
px_per_mm_interface = GetPixelsPerMillimeterInterface(video_path=self.video_path.file_path, known_metric_mm=float(self.known_distance.entry_get))
px_per_mm_interface.run()
print(f"ONE (1) PIXEL REPRESENTS {round(px_per_mm_interface.ppm, 4)} MILLIMETERS IN VIDEO {os.path.basename(self.video_path.file_path)}.")
#_ = CalculatePixelsPerMMInVideoPopUp()
[docs]class ConcatenatingVideosPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CONCATENATE TWO VIDEOS", size=(600, 300), icon='concat_videos')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.video_path_1 = FileSelect(settings_frm, "FIRST VIDEO PATH: ", title="Select a video file", lblwidth=35, file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='one', tooltip_key='CONCAT_VIDEO_PATH_1')
self.video_path_2 = FileSelect(settings_frm, "SECOND VIDEO PATH: ", title="Select a video file", lblwidth=35, file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='two', tooltip_key='CONCAT_VIDEO_PATH_2')
resolutions = ["VIDEO 1", "VIDEO 2", 240, 320, 480, 640, 720, 800, 960, 1120, 1080, 1980]
self.resolution_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=resolutions, label="RESOLUTION (ASPECT RATIO RETAINED):", label_width=35, dropdown_width=35, value=resolutions[0], img='monitor', tooltip_key='RESOLUTION_CONCAT')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=35, dropdown_width=35, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU (REDUCED RUN-TIME):", label_width=35, dropdown_width=35, value='FALSE', img='gpu_3', state=self.gpu_available, tooltip_key='CONCAT_VIDEOS_USE_GPU')
self.horizontal = BooleanVar(value=False)
horizontal_radio_btn = SimBARadioButton(parent=settings_frm, txt="HORIZONTAL concatenation", variable=self.horizontal, img='horizontal', value=True, compound='left')
vertical_radio_btn = SimBARadioButton(parent=settings_frm, txt="VERTICAL concatenation", variable=self.horizontal, img='vertical', value=False, compound='left')
settings_frm.grid(row=0, column=0, sticky=NW)
self.video_path_1.grid(row=0, column=0, sticky=NW)
self.video_path_2.grid(row=1, column=0, sticky=NW)
self.resolution_dropdown.grid(row=2, column=0, sticky=NW)
self.quality_dropdown.grid(row=3, column=0, sticky=NW)
self.gpu_dropdown.grid(row=4, column=0, sticky=NW)
horizontal_radio_btn.grid(row=5, column=0, sticky=NW)
vertical_radio_btn.grid(row=6, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
video_1_path = self.video_path_1.file_path
video_2_path = self.video_path_2.file_path
resolution = self.resolution_dropdown.getChoices()
int_res, _ = check_int(name='resolution', value=resolution, raise_error=False)
if int_res: resolution = int(resolution)
else: resolution = resolution.lower()
horizontal_bool = self.horizontal.get()
gpu_bool = str_2_bool(self.gpu_dropdown.getChoices())
check_file_exist_and_readable(file_path=video_1_path)
check_file_exist_and_readable(file_path=video_2_path)
video_1_meta = get_video_meta_data(video_path=video_1_path)
video_2_meta = get_video_meta_data(video_path=video_2_path)
quality = int(self.quality_dropdown.get_value())
if horizontal_bool and not int_res:
if not video_1_meta['height'] == video_2_meta['height']:
if resolution == 'video 1': resolution = video_1_meta['height']
else: resolution = video_2_meta['height']
else:
resolution = video_1_meta['height']
# if not video_1_meta['height'] == video_2_meta['height']:
# raise ResolutionError(f'For HORIZONTAL concatenation, the videos has to be the same height. Got Video 1 height: {video_1_meta["height"]}, Video 2 height: {video_2_meta["height"]}. Select a specific resolution or convert the video resolution heights of the two videos first to be the same.', source=self.__class__.__name__)
elif not horizontal_bool and not int_res:
if not video_1_meta['width'] == video_2_meta['width']:
if not video_1_meta['width'] == video_2_meta['width']:
if resolution == 'video 1':
resolution = video_1_meta['width']
else: resolution = video_2_meta['width']
else: resolution = video_1_meta['width']
#raise ResolutionError(f'For VERTICAL concatenation, the videos has to be the same width. Got Video 1 width: {video_1_meta["width"]}, Video 2 width: {video_2_meta["width"]}. Select a specific resolution or convert the video resolution widths of the two videos first to be the same.', source=self.__class__.__name__)
threading.Thread(video_concatenator(video_one_path=video_1_path, video_two_path=video_2_path, resolution=resolution, horizontal=horizontal_bool, gpu=gpu_bool, quality=quality)).start()
#_ = ConcatenatingVideosPopUp()
[docs]class ConcatenatorPopUp(PopUpMixin, ConfigReader):
def __init__(self, config_path: Optional[Union[str, os.PathLike]] = None):
self.RESOLUTIONS = ["480", "640", "1280", "1920", "2560"]
self.CONCAT_TYPES_1 = {'HORIZONTAL': 'horizontal', 'MIXED MOSAIC': 'mixed_mosaic', 'MOSAIC': 'mosaic', 'VERTICAL': 'vertical'}
self.CONCAT_TYPES_2 = {'horizontal': 'HORIZONTAL', 'mixed_mosaic': 'MIXED MOSAIC', 'mosaic': 'MOSAIC', 'vertical': 'VERTICAL'}
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
PopUpMixin.__init__(self, title="MERGE (CONCATENATE) VIDEOS", icon='concat_videos')
self.config_path = config_path
self.select_video_cnt_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="NUMBER OF VIDEOS TO CONCATENATE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.CONCAT_VIDEOS.value)
self.select_video_cnt_dropdown = SimBADropDown(parent=self.select_video_cnt_frm, dropdown_options=list(range(2, 21)), label="VIDEOS #", label_width=30, dropdown_width=25, value=2, command=lambda value: self.populate_table(int(value)), img='stack')
self.select_video_cnt_frm.grid(row=0, column=0, sticky=NW)
self.select_video_cnt_dropdown.grid(row=0, column=0, sticky=NW)
self.populate_table(video_cnt=int(self.select_video_cnt_dropdown.get_value()))
# self.main_frm.mainloop()
[docs] def populate_table(self, video_cnt):
if hasattr(self, "video_table_frm"): self.video_table_frm.destroy()
if hasattr(self, "join_type_frm"): self.join_type_frm.destroy()
self.video_table_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO PATHS", icon_name='video_2', icon_link=Links.CONCAT_VIDEOS.value, pady=5, padx=5)
self.video_table_frm.grid(row=1, sticky=NW)
self.videos_dict = {}
for cnt in range(int(video_cnt)):
self.videos_dict[cnt] = FileSelect(self.video_table_frm, f"VIDEO {cnt+1}: ", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=30, lbl_icon='video_2')
self.videos_dict[cnt].grid(row=cnt, column=0, sticky=NW)
self.join_type_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="JOIN TYPE", icon_name='category', icon_link=Links.CONCAT_VIDEOS.value, pady=5, padx=5)
self.join_type_frm.grid(row=2, sticky=NW)
self.join_type_var = StringVar()
self.icons_dict = {}
simba_dir = os.path.dirname(simba.__file__)
icon_assets_dir = os.path.join(simba_dir, Paths.ICON_ASSETS.value)
concat_icon_dir = os.path.join(icon_assets_dir, "concat_icons")
for file_cnt, file_path in enumerate(glob.glob(concat_icon_dir + "/*.png")):
_, file_name, _ = get_fn_ext(file_path)
self.icons_dict[file_name] = {}
self.icons_dict[file_name]["img"] = ImageTk.PhotoImage(Image.open(file_path))
self.icons_dict[file_name]["btn"] = SimBARadioButton(parent=self.join_type_frm, txt=self.CONCAT_TYPES_2[file_name], variable=self.join_type_var, img=self.icons_dict[file_name]["img"], value=self.CONCAT_TYPES_2[file_name], compound='bottom', font=Formats.FONT_REGULAR_BOLD.value)
self.icons_dict[file_name]["btn"].grid(row=0, column=file_cnt, sticky=NW)
self.join_type_var.set(value="mosaic")
self.resolution_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="RESOLUTION", icon_name='monitor', icon_link=Links.CONCAT_VIDEOS.value, pady=5, padx=5, tooltip_key='CONCAT_RES_HEADER')
self.resolution_width = SimBADropDown(parent=self.resolution_frm, dropdown_options=self.RESOLUTIONS, label='WIDTH:', label_width=30, dropdown_width=25, value="480", img='width', tooltip_key="CONCAT_WIDTH")
self.resolution_height = SimBADropDown(parent=self.resolution_frm, dropdown_options=self.RESOLUTIONS, label='HEIGHT:', label_width=30, dropdown_width=25, value="640", img='height', tooltip_key="CONCAT_HEIGHT")
self.settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name='settings', icon_link=Links.CONCAT_VIDEOS.value, pady=5, padx=5)
self.gpu_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU:", label_width=30, dropdown_width=25, value='FALSE', img='gpu_3', state=self.gpu_available, tooltip_key='USE_GPU')
self.quality_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUT VIDEO QUALITY:", label_width=30, dropdown_width=25, value=60, img='pct_2', state=self.gpu_available, tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown.grid(row=0, column=0, sticky="NW")
self.quality_dropdown.grid(row=1, column=0, sticky="NW")
self.resolution_frm.grid(row=3, column=0, sticky=NW)
self.settings_frm.grid(row=4, column=0, sticky="NW")
self.resolution_width.grid(row=0, column=0, sticky=NW)
self.resolution_height.grid(row=1, column=0, sticky=NW)
run_btn = SimbaButton(parent=self.main_frm, txt='RUN', img='rocket', cmd=self.run)
run_btn.grid(row=5, column=0, sticky=NW)
[docs] def run(self):
file_paths = []
for cnt, (video_name, video_data) in enumerate(self.videos_dict.items()):
_ = get_video_meta_data(video_path=video_data.file_path)
file_paths.append(video_data.file_path)
if (len(file_paths) < 3) & (self.join_type_var.get() == "mixed_mosaic"):
raise MixedMosaicError(msg="If using the mixed mosaic join type, please use at least 3 videos.", source=self.__class__.__name__ )
if (len(file_paths) < 3) & (self.join_type_var.get() == "mosaic"):
self.join_type_var.set(value="vertical")
gpu = str_2_bool(self.gpu_dropdown.get_value())
quality = int(self.quality_dropdown.get_value())
quality_crf = quality_pct_to_crf(pct=quality)
join_type = self.CONCAT_TYPES_1[self.join_type_var.get()]
video_merger = FrameMergererFFmpeg(config_path=self.config_path,
video_paths=file_paths,
video_height=int(self.resolution_height.getChoices()),
video_width=int(self.resolution_width.getChoices()),
concat_type=join_type,
gpu=gpu,
quality=quality_crf)
threading.Thread(target=video_merger.run())
#_ = ConcatenatorPopUp()
#ConcatenatorPopUp(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/two_black_animals_14bp/project_folder/project_config.ini')
#ConcatenatorPopUp(config_path=None)
[docs]class VideoRotatorPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="ROTATE VIDEOS", icon='rotate')
self.save_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SAVE LOCATION", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.save_dir = FolderSelect(self.save_dir_frm, "SAVE DIRECTORY:", lblwidth=20, lbl_icon='browse')
self.setting_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=self.setting_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU (REDUCED RUN-TIME):", label_width=35, dropdown_width=35, value='FALSE', img='gpu_3', state=self.gpu_available, tooltip_key='VIDEO_ROTATOR_USE_GPU')
self.ffmpeg_dropdown = SimBADropDown(parent=self.setting_frm, dropdown_options=['TRUE', 'FALSE'], label="USE FFMPEG:", label_width=35, dropdown_width=35, value='FALSE', img='ffmpeg', tooltip_key='VIDEO_ROTATOR_USE_FFMPEG')
self.gpu_dropdown.grid(row=0, column=0, sticky=NW)
self.ffmpeg_dropdown.grid(row=1, column=0, sticky=NW)
self.rotate_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="ROTATE VIDEOS IN DIRECTORY", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.input_dir = FolderSelect(self.rotate_dir_frm, "VIDEO DIRECTORY:", lblwidth=20, lbl_icon='browse')
self.run_dir = SimbaButton(parent=self.rotate_dir_frm, txt="RUN", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run, cmd_kwargs={'input_path': lambda:self.input_dir.folder_path, 'output_path': lambda:self.save_dir.folder_path})
self.rotate_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="ROTATE SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.input_file = FileSelect( self.rotate_video_frm, "VIDEO PATH:", lblwidth=20, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2')
self.run_file = SimbaButton(parent=self.rotate_video_frm, txt="RUN", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run, cmd_kwargs={'input_path': lambda:self.input_file.file_path, 'output_path': lambda:self.save_dir.folder_path})
self.save_dir_frm.grid(row=0, column=0, sticky=NW)
self.save_dir.grid(row=0, column=0, sticky=NW)
self.setting_frm.grid(row=1, column=0, sticky=NW)
self.rotate_dir_frm.grid(row=2, column=0, sticky=NW)
self.input_dir.grid(row=0, column=0, sticky=NW)
self.run_dir.grid(row=1, column=0, sticky=NW)
self.rotate_video_frm.grid(row=3, column=0, sticky=NW)
self.input_file.grid(row=0, column=0, sticky=NW)
self.run_file.grid(row=1, column=0, sticky=NW)
self.main_frm.mainloop()
[docs] def run(self, input_path: str, output_path: str):
check_if_dir_exists(in_dir=output_path)
ffmpeg = str_2_bool(self.ffmpeg_dropdown.get_value())
gpu = str_2_bool(self.gpu_dropdown.get_value())
rotator = VideoRotator(input_path=input_path, output_dir=output_path, ffmpeg=ffmpeg, gpu=gpu)
rotator.run()
#_ = VideoRotatorPopUp()
[docs]class VideoTemporalJoinPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="TEMPORAL JOIN VIDEOS", icon='time')
self.settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
FPS_OPTIONS = list(range(2, 102, 2))
FPS_OPTIONS.insert(0, 'SAME AS THE FIRST INPUT VIDEO IN INPUT DIRECTORY')
FPS_OPTIONS.insert(0, 'KEEP INPUT VIDEO FPS')
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.input_dir = FolderSelect( self.settings_frm, "INPUT DIRECTORY:", lblwidth=30, lbl_icon='browse')
self.file_format = SimBADropDown(parent=self.settings_frm, label="INPUT VIDEO FORMAT:", dropdown_options=Options.VIDEO_FORMAT_OPTIONS.value, label_width=30, dropdown_width=30, value=Options.VIDEO_FORMAT_OPTIONS.value[0], img='file_type')
self.out_fps = SimBADropDown(parent=self.settings_frm, label="OUTPUT FPS:", dropdown_options=FPS_OPTIONS, label_width=30, dropdown_width=30, value='SAME AS INPUT VIDEOS', img='fps')
self.gpu_dropdown = SimBADropDown(parent=self.settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU (REDUCED RUN-TIME):", label_width=30, dropdown_width=30, value='FALSE', img='gpu_3', state=self.gpu_available)
self.settings_frm.grid(row=0, column=0, sticky=NW)
self.input_dir.grid(row=0, column=0, sticky=NW)
self.file_format.grid(row=1, column=0, sticky=NW)
self.out_fps.grid(row=2, column=0, sticky=NW)
self.gpu_dropdown.grid(row=3, column=0, sticky="NW")
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
check_if_dir_exists(in_dir=self.input_dir.folder_path)
_ = find_files_of_filetypes_in_directory(directory=self.input_dir.folder_path, extensions=[f'.{self.file_format.getChoices()}'], raise_error=True)
fps_setting = self.out_fps.getChoices()
if fps_setting == 'KEEP INPUT VIDEO FPS':
fps = None
elif fps_setting == 'SAME AS THE FIRST INPUT VIDEO IN INPUT DIRECTORY':
fps = '0'
else:
fps = int(fps_setting)
gpu = str_2_bool(self.gpu_dropdown.get_value())
print(f"Concatenating videos in {self.input_dir.folder_path} directory...")
save_path = os.path.join(self.input_dir.folder_path, f"concatenated.mp4")
concatenate_videos_in_folder(in_folder=self.input_dir.folder_path,
save_path=save_path,
remove_splits=False,
fps=fps,
video_format=self.file_format.getChoices(),
gpu=gpu)
#VideoTemporalJoinPopUp()
[docs]class ImportFrameDirectoryPopUp(PopUpMixin, ConfigReader):
def __init__(self, config_path: str):
PopUpMixin.__init__(self, title="IMPORT FRAME DIRECTORY", icon='import')
ConfigReader.__init__(self, config_path=config_path)
self.frame_folder = FolderSelect(self.main_frm, "FRAME DIRECTORY:", title="Select the main directory with frame folders")
import_btn = SimbaButton(parent=self.main_frm, txt="IMPORT FRAMES", img='import', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run)
self.frame_folder.grid(row=0, column=0, sticky=NW)
import_btn.grid(row=1, column=0, sticky=NW)
self.main_frm.mainloop()
[docs] def run(self):
if not os.path.isdir(self.frame_folder.folder_path):
raise NotDirectoryError(
msg=f"SIMBA ERROR: {self.frame_folder.folder_path} is not a valid directory.",
source=self.__class__.__name__,
)
copy_img_folder(
config_path=self.config_path, source=self.frame_folder.folder_path
)
#ImportFrameDirectoryPopUp(config_path=r"C:\troubleshooting\mitra\project_folder\project_config.ini")
[docs]class ExtractAnnotationFramesPopUp(PopUpMixin, ConfigReader):
"""
:example:
>>> ExtractAnnotationFramesPopUp(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/two_black_animals_14bp/project_folder/project_config.ini')
"""
def __init__(self,
config_path: Union[str, os.PathLike]):
ConfigReader.__init__(self, config_path=config_path)
if len(self.target_file_paths) == 0:
raise NoFilesFoundError(msg=f'Cannot extract annotation images: No data files found in {self.targets_folder}.')
self.video_dict = {}
for file_path in self.target_file_paths:
self.video_dict[get_fn_ext(filepath=file_path)[1]] = file_path
PopUpMixin.__init__(self, config_path=config_path, title="EXTRACT ANNOTATED FRAMES", icon='frames')
self.clf_frame = LabelFrame(self.main_frm, text="CHOOSE CLASSIFIERS", font=Formats.FONT_HEADER.value, pady=5, padx=5)
self.create_clf_checkboxes(main_frm=self.clf_frame, clfs=self.clf_names)
self.choose_video_frm = LabelFrame(self.main_frm, text="CHOOSE VIDEOS", font=Formats.FONT_HEADER.value, pady=5, padx=5)
video_options = ["ALL"] + list(self.video_dict.keys())
self.video_dropdown = SimBADropDown(parent=self.choose_video_frm, dropdown_options=video_options, label='VIDEO', label_width=25, value='ALL', img='video')
self.settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="STYLE SETTINGS", font=Formats.FONT_HEADER.value, pady=5, padx=5, icon_name='style')
self.settings_frm = LabelFrame(self.main_frm, text="STYLE SETTINGS", font=Formats.FONT_HEADER.value, pady=5, padx=5)
down_sample_resolution_options = ["None", "2x", "3x", "4x", "5x"]
img_format_options = ['png', 'jpg', 'webp']
self.resolution_downsample_dropdown = SimBADropDown(parent=self.settings_frm, label="Down-sample images:", label_width=25, dropdown_width=25, value=down_sample_resolution_options[0], img='monitor', dropdown_options=down_sample_resolution_options)
self.img_format_dropdown = SimBADropDown(parent=self.settings_frm, label="Image format:", label_width=25, dropdown_width=25, value=img_format_options[0], img='file_type', dropdown_options=img_format_options)
self.greyscale_dropdown = SimBADropDown(parent=self.settings_frm, label="Image grayscale:", label_width=25, dropdown_width=25, value='FALSE', img='grey', dropdown_options=['TRUE', 'FALSE'])
self.choose_video_frm.grid(row=self.children_cnt_main()+2, column=0, sticky=NW)
self.video_dropdown.grid(row=0, column=0, sticky=NW)
self.settings_frm.grid(row=self.children_cnt_main()+1, column=0, sticky=NW)
self.resolution_downsample_dropdown.grid(row=0, column=0, sticky=NW)
self.img_format_dropdown.grid(row=1, column=0, sticky=NW)
self.greyscale_dropdown.grid(row=2, column=0, sticky=NW)
self.run_btn = SimbaButton(parent=self.main_frm, txt="RUN", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.run)
self.run_btn.grid(row=self.children_cnt_main()+3, column=0, sticky=NW)
self.main_frm.mainloop()
[docs] def run(self):
downsample = self.resolution_downsample_dropdown.getChoices()
if downsample != Dtypes.NONE.value: downsample = int("".join(filter(str.isdigit, downsample)))
else: downsample = None
greyscale = str_2_bool(input_str=self.greyscale_dropdown.getChoices())
img_format = self.img_format_dropdown.getChoices()
clfs = []
for clf_name, selection in self.clf_selections.items():
if selection.get():
clfs.append(clf_name)
if len(clfs) == 0:
raise NoChoosenClassifierError(source=self.__class__.__name__)
video_selection = self.video_dropdown.getChoices()
if video_selection == 'ALL':
data_paths = list(self.video_dict.values())
else:
data_paths = [self.video_dict[video_selection]]
for data_path in data_paths:
_ = find_video_of_file(video_dir=self.video_dir, filename=get_fn_ext(filepath=data_path)[1], raise_error=True)
frame_extractor = AnnotationFrameExtractor(config_path=self.config_path,
clfs=clfs,
img_downsample_factor=downsample,
img_format=img_format,
img_greyscale=greyscale,
data_paths=data_paths)
frame_extractor.run()
#ExtractAnnotationFramesPopUp(config_path=r"C:\troubleshooting\sleap_two_animals_open_field\project_folder\project_config.ini")
[docs]class DownsampleVideoPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="DOWN-SAMPLE VIDEO RESOLUTION")
choose_video_frm = CreateLabelFrameWithIcon( parent=self.main_frm, header="SELECT VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.DOWNSAMPLE.value)
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.video_path_selected = FileSelect(choose_video_frm, "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='browse')
gpu_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="GPU", icon_name='gpu_3', icon_link=Links.DOWNSAMPLE.value, padx=5, pady=5)
self.gpu_dropdown = SimBADropDown(parent=gpu_frm, label="Use GPU (reduced runtime)", img='gpu_3', dropdown_options=['TRUE', 'FALSE'], dropdown_width=30, label_width=30, value='FALSE', state=self.gpu_available)
self.gpu_dropdown.grid(row=0, column=0, sticky="NW")
quality_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="OUTPUT QUALITY", icon_name='pct_2', icon_link=Links.DOWNSAMPLE.value, padx=5, pady=5)
self.quality_dropdown = SimBADropDown(parent=quality_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=35, dropdown_width=35, value=60, img='pct_2', tooltip_key='OUPUT_VIDEO_QUALITY')
quality_frm.grid(row=2, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
custom_frm = CreateLabelFrameWithIcon( parent=self.main_frm, header="CUSTOM RESOLUTION", icon_name='monitor', icon_link=Links.DOWNSAMPLE.value, padx=5, pady=5)
self.entry_width = Entry_Box(custom_frm, "Width", "10", validation="numeric", img='width')
self.entry_height = Entry_Box(custom_frm, "Height", "10", validation="numeric", img='height')
self.custom_downsample_btn = SimbaButton(parent=custom_frm, txt="Downsample to custom resolution", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.custom_downsample)
default_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="DEFAULT RESOLUTION", icon_name='monitor', icon_link=Links.DOWNSAMPLE.value, padx=5, pady=5)
self.radio_btns = {}
self.var = StringVar()
for custom_cnt, resolution_radiobtn in enumerate(self.resolutions):
self.radio_btns[resolution_radiobtn] = SimBARadioButton(parent=default_frm, txt=resolution_radiobtn, variable=self.var, font=Formats.FONT_REGULAR.value, value=resolution_radiobtn)
self.radio_btns[resolution_radiobtn].grid(row=custom_cnt, sticky=NW)
self.default_downsample_btn = SimbaButton(parent=default_frm, txt="Downsample to default resolution", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.default_downsample)
choose_video_frm.grid(row=1, column=0, sticky=NW)
gpu_frm.grid(row=2, column=0, sticky=NW)
self.video_path_selected.grid(row=0, column=0, sticky=NW)
custom_frm.grid(row=4, column=0, sticky=NW)
self.entry_width.grid(row=0, column=0, sticky=NW)
self.entry_height.grid(row=1, column=0, sticky=NW)
self.custom_downsample_btn.grid(row=3, column=0, sticky=NW)
default_frm.grid(row=6, column=0, sticky=NW)
self.default_downsample_btn.grid(row=len(self.resolutions) + 1, column=0, sticky=NW)
self.main_frm.mainloop()
[docs] def custom_downsample(self):
width = self.entry_width.entry_get
height = self.entry_height.entry_get
check_int(name="Video width", value=width)
check_int(name="Video height", value=height)
check_file_exist_and_readable(self.video_path_selected.file_path)
quality = int(self.quality_dropdown.get_value())
quality_crf = quality_pct_to_crf(pct=quality)
downsample_video(
file_path=self.video_path_selected.file_path,
video_width=int(width),
video_height=int(height),
gpu=str_2_bool(self.gpu_dropdown.get_value()),
quality=quality_crf,
)
[docs] def default_downsample(self):
resolution = self.var.get()
width, height = (
resolution.split("×", 2)[0].strip(),
resolution.split("×", 2)[1].strip(),
)
check_file_exist_and_readable(self.video_path_selected.file_path)
quality = int(self.quality_dropdown.get_value())
quality_crf = quality_pct_to_crf(pct=quality)
downsample_video(
file_path=self.video_path_selected.file_path,
video_width=int(width),
video_height=int(height),
gpu=str_2_bool(self.gpu_dropdown.get_value()),
quality=quality_crf,
)
#DownsampleVideoPopUp()
[docs]class ConvertROIDefinitionsPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CONVERT ROI DEFINITIONS", icon='roi')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header='SETTINGS', icon_name='settings', font=Formats.FONT_HEADER.value)
self.roi_definitions_file_select = FileSelect(settings_frm, "ROI DEFINITIONS PATH (H5)", title="SELECT H5 FILE", lblwidth=30, file_types=[("H5 FILE", (".h5", ".H5"))], lbl_icon='roi')
self.save_dir = FolderSelect(settings_frm, "SAVE DIRECTORY", title="SELECT H5 FILE", lblwidth=30, lbl_icon='browse')
settings_frm.grid(row=0, column=0, sticky=NW)
self.roi_definitions_file_select.grid(row=0, column=0, sticky=NW)
self.save_dir.grid(row=1, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
[docs] def run(self):
check_file_exist_and_readable(file_path=self.roi_definitions_file_select.file_path)
check_if_dir_exists(in_dir=self.save_dir.folder_path)
convert_roi_definitions(roi_definitions_path=self.roi_definitions_file_select.file_path, save_dir=self.save_dir.folder_path)
#ConvertROIDefinitionsPopUp()
[docs]class CropVideoCirclesPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CROP SINGLE VIDEO (CIRCLES)", icon='circle_small')
crop_video_lbl_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="Crop Video (CIRCLES)", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.CIRCLE_CROP.value)
selected_video = FileSelect(crop_video_lbl_frm, "VIDEO PATH", title="Select a video file", lblwidth=20, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2')
button_crop_video_single = SimbaButton(parent=crop_video_lbl_frm, txt="CROP VIDEO", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=crop_single_video_circle, cmd_kwargs={'file_path': lambda:selected_video.file_path})
crop_video_lbl_frm_multiple = LabelFrame(self.main_frm, text="Fixed CIRCLE coordinates crop for multiple videos", font=Formats.FONT_HEADER.value, padx=5, pady=5)
input_folder = FolderSelect(crop_video_lbl_frm_multiple,"VIDEO DIRECTORY:",title="Select Folder with videos",lblwidth=20, lbl_icon='browse')
output_folder = FolderSelect(crop_video_lbl_frm_multiple, "OUTPUT DIRECTORY:", title="Select a folder for your output videos", lblwidth=20, lbl_icon='browse')
button_crop_video_multiple = SimbaButton(parent=crop_video_lbl_frm_multiple, txt="CROP VIDEOS", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=crop_single_video_circle, cmd_kwargs={'in_dir': lambda:input_folder.folder_path, 'out_dir': lambda:output_folder.folder_path})
crop_video_lbl_frm.grid(row=0, sticky=NW)
selected_video.grid(row=0, sticky=NW)
button_crop_video_single.grid(row=3, sticky=NW)
crop_video_lbl_frm_multiple.grid(row=1, sticky=NW)
input_folder.grid(row=0, sticky=NW)
output_folder.grid(row=1, sticky=NW)
button_crop_video_multiple.grid(row=3, sticky=NW)
self.main_frm.mainloop()
#_ = CropVideoCirclesPopUp()
[docs]class CropVideoPolygonsPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CROP SINGLE VIDEO (POLYGONS)", icon='polygon')
crop_video_lbl_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="Crop Video (POLYGONS)", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.CIRCLE_CROP.value)
selected_video = FileSelect( crop_video_lbl_frm, "VIDEO PATH", title="Select a video file", lblwidth=20, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2')
button_crop_video_single = SimbaButton(parent=crop_video_lbl_frm, txt="CROP VIDEO", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=crop_single_video_polygon, cmd_kwargs={'file_path': lambda:selected_video.file_path})
crop_video_lbl_frm_multiple = LabelFrame( self.main_frm, text="Fixed POLYGON coordinates crop for multiple videos", font=Formats.FONT_HEADER.value, padx=5, pady=5)
input_folder = FolderSelect( crop_video_lbl_frm_multiple, "VIDEO DIRECTORY:", title="Select Folder with videos", lblwidth=20, lbl_icon='browse')
output_folder = FolderSelect( crop_video_lbl_frm_multiple, "OUTPUT DIRECTORY:", title="Select a folder for your output videos", lblwidth=20, lbl_icon='browse')
button_crop_video_multiple = SimbaButton(parent=crop_video_lbl_frm_multiple, txt="CROP VIDEOS", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=crop_multiple_videos_polygons, cmd_kwargs={'in_dir': lambda:input_folder.folder_path, 'out_dir': lambda:output_folder.folder_path})
crop_video_lbl_frm.grid(row=0, sticky=NW)
selected_video.grid(row=0, sticky=NW)
button_crop_video_single.grid(row=3, sticky=NW)
crop_video_lbl_frm_multiple.grid(row=1, sticky=NW)
input_folder.grid(row=0, sticky=NW)
output_folder.grid(row=1, sticky=NW)
button_crop_video_multiple.grid(row=3, sticky=NW)
[docs]class ClipSingleVideoByFrameNumbers(PopUpMixin):
def __init__(self):
super().__init__(title="CLIP SINGLE VIDEO BY FRAME NUMBERS", icon='clip')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.selected_video = FileSelect(settings_frm, "VIDEO PATH: ", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=25, lbl_icon='folder')
self.start_frm_eb = Entry_Box(parent=settings_frm, fileDescription="START FRAME: ", labelwidth=25, validation="numeric", img='play', justify='center', width=30)
self.end_frm_eb = Entry_Box(parent=settings_frm, fileDescription="END FRAME: ", labelwidth=25, validation="numeric", img='stop', justify='center', width=30)
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU:', label_width=25, dropdown_width=12, tooltip_key='USE_GPU', img='gpu_3', state=gpu_state, value='FALSE')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label='OUT VIDEO QUALITY:', label_width=25, dropdown_width=12, tooltip_key='OUTPUT_VIDEO_QUALITY', img='pct_2', value=60)
settings_frm.grid(row=0, column=0, sticky=NW)
self.selected_video.grid(row=0, column=0, sticky=NW)
self.start_frm_eb.grid(row=1, column=0, sticky=NW)
self.end_frm_eb.grid(row=2, column=0, sticky=NW)
self.gpu_dropdown.grid(row=3, column=0, sticky=NW)
self.quality_dropdown.grid(row=4, column=0, sticky=NW)
run_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="RUN", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
run_btn = SimbaButton(parent=run_frm, txt='RUN', img='rocket', cmd=self.run)
interactive_btn = SimbaButton(parent=run_frm, txt='TIMELAPSE VIEWER', img='rocket', cmd=self._init_interactive_timeslider)
run_frm.grid(row=1, column=0, sticky=NW)
run_btn.grid(row=0, column=0, sticky=NW, padx=(0, 10))
interactive_btn.grid(row=0, column=1, sticky=NW)
[docs] def run(self):
check_file_exist_and_readable(file_path=self.selected_video.file_path)
video_meta_data = get_video_meta_data(video_path=self.selected_video.file_path)
check_int(name="Start frame", value=self.start_frm_eb.entry_get, min_value=0)
check_int(name="End frame", value=self.end_frm_eb.entry_get, min_value=1)
start_frame = int(self.start_frm_eb.entry_get)
end_frame = int(self.end_frm_eb.entry_get)
if start_frame >= end_frame:
raise FrameRangeError(
msg=f"Start frame ({start_frame}) is after or the same as the end frame ({end_frame})",
source=__class__.__name__,
)
if (start_frame < 0) or (end_frame < 1):
raise FrameRangeError(
msg=f"Start frame has to be at least 0 and end frame has to be at least 1",
source=__class__.__name__,
)
if start_frame > video_meta_data["frame_count"]:
raise FrameRangeError(
msg=f'The video has {video_meta_data["frame_count"]} frames, which is less than the start frame: {start_frame}',
source=__class__.__name__,
)
if end_frame > video_meta_data["frame_count"]:
raise FrameRangeError(
msg=f'The video has {video_meta_data["frame_count"]} frames, which is less than the end frame: {end_frame}',
source=__class__.__name__,
)
gpu = str_2_bool(self.gpu_dropdown.get_value())
if gpu and not check_nvidea_gpu_available():
raise FFMPEGCodecGPUError('No GPU found on machine. Try unchecking the GPU checkbox', source=self.__class__.__name__)
quality = quality_pct_to_crf(pct=int(self.quality_dropdown.get_value()))
frm_ids = [[start_frame, end_frame]]
_ = clip_videos_by_frame_ids(file_paths=[self.selected_video.file_path], frm_ids=frm_ids, save_dir=None, gpu=gpu, quality=quality)
def _init_interactive_timeslider(self):
check_file_exist_and_readable(file_path=self.selected_video.file_path, raise_error=True)
_ = get_video_meta_data(video_path=self.selected_video.file_path)
def exit_click(event):
self.click_event.set(True)
interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
interactive_ui.close()
def window_closed():
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
if interactive_ui.img_window.winfo_exists(): interactive_ui.close()
self.click_event.set(True)
interactive_ui = TimelapseSlider(video_path=self.selected_video.file_path, use_timestamps=False)
interactive_ui.run()
self.click_event = BooleanVar(value=False)
interactive_ui.img_window.protocol("WM_DELETE_WINDOW", window_closed)
interactive_ui.img_window.bind(TkBinds.ESCAPE.value, exit_click);
self.main_frm.bind(TkBinds.ESCAPE.value, exit_click)
self.main_frm.wait_variable(self.click_event)
try:
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
except:
pass
try:
self.main_frm.unbind(TkBinds.ESCAPE.value)
except:
pass
if not interactive_ui.img_window.winfo_exists(): pass
start_frm, end_frm = interactive_ui.get_start_frame(), interactive_ui.get_end_frame()
self.start_frm_eb.entry_set(start_frm)
self.end_frm_eb.entry_set(end_frm)
#ClipSingleVideoByFrameNumbers()
[docs]class ClipMultipleVideosByFrameNumbersPopUp(PopUpMixin):
def __init__(self,
data_dir: Union[str, os.PathLike],
save_dir: Union[str, os.PathLike]):
"""
:param data_dir: Directory containing video files to be clipped.
:param save_dir: Directory where to save the clipped videos.
:example:
>>> ClipMultipleVideosByFrameNumbersPopUp(data_dir='/Users/simon/Downloads/test__/test__', save_dir='/Users/simon/Downloads/test__/res')
"""
check_if_dir_exists(in_dir=data_dir, source=self.__class__.__name__, create_if_not_exist=False )
check_if_dir_exists(in_dir=save_dir, source=self.__class__.__name__, create_if_not_exist=True)
self.video_paths = find_all_videos_in_directory(directory=data_dir, as_dict=True, raise_error=True)
self.video_meta_data = [get_video_meta_data(video_path=x)["frame_count"]for x in list(self.video_paths.values())]
max_video_name_len = len(max(list(self.video_paths.keys())))
super().__init__(title="CLIP MULTIPLE VIDEOS BY FRAME NUMBERS", icon='clip')
self.save_dir = save_dir
padx = (0, 25)
data_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
SimBALabel(parent=data_frm, font=Formats.FONT_REGULAR.value, txt="VIDEO NAME", justify='center', img='video').grid(row=0, column=0, padx=padx, sticky=NW)
SimBALabel(parent=data_frm, font=Formats.FONT_REGULAR.value, txt="START FRAME", justify='center', img='play').grid(row=0, column=2, padx=padx)
SimBALabel(parent=data_frm, font=Formats.FONT_REGULAR.value, txt="END FRAME", justify='center', img='stop').grid(row=0, column=3, padx=padx)
SimBALabel(data_frm, txt="TIMELAPSE VIEWER", justify='center', font=Formats.FONT_REGULAR_BOLD.value,img='monitor').grid(row=0, column=4, sticky=NW, padx=padx)
seperator = SimBASeperator(parent=data_frm, color=None, orient='horizontal', borderwidth=1)
seperator.grid(row=1, column=0, columnspan=5, rowspan=1, sticky="ew")
self.entry_boxes, self.interactive_btns = {}, {}
for cnt, (video_name, video_path) in enumerate(self.video_paths.items()):
self.entry_boxes[video_name] = {}
img = read_frm_of_video(video_path=video_path, frame_index=0, size=(420, 280), keep_aspect_ratio=True, raise_error=False)
SimBALabel(parent=data_frm, font=Formats.FONT_REGULAR_BOLD.value, txt=video_name + f' (frames: { self.video_meta_data[cnt]})', justify='left', hover_img=img).grid(row=cnt + 2, column=0, padx=padx, sticky=NW)
self.entry_boxes[video_name]["start"] = Entry_Box(data_frm, fileDescription="", labelwidth=0, validation="numeric", justify='center')
self.entry_boxes[video_name]["end"] = Entry_Box(data_frm, fileDescription="", labelwidth=0, validation="numeric", justify='center')
self.entry_boxes[video_name]["start"].grid(row=cnt + 2, column=2, sticky=NW, padx=padx)
self.entry_boxes[video_name]["end"].grid(row=cnt + 2, column=3, sticky=NW, padx=padx)
kwargs = {'video_path': self.video_paths[video_name], 'frame_cnt': 25, 'crop_ratio': 50, 'size': 100, 'video_name': video_name}
self.interactive_btns[video_name] = SimbaButton(parent=data_frm, txt='SELECT FRAMES', cmd=self._start_interactive_ui, cmd_kwargs=kwargs, img='monitor')
self.interactive_btns[video_name].grid(row=cnt + 2, column=4, sticky=NW, padx=padx)
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
batch_settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="BATCH SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
batch_start_entry = Entry_Box(parent=batch_settings_frm, fileDescription='START FRAME:', labelwidth=25, entry_box_width=12, img='play', validation='numeric', justify='center')
batch_start_btn = SimbaButton(parent=batch_settings_frm, txt='SET', img='tick', cmd=self._batch_set_val, cmd_kwargs={'text': lambda: batch_start_entry.entry_get.strip(), 'box_type': lambda: 'start'})
batch_end_entry = Entry_Box(parent=batch_settings_frm, fileDescription='END FRAME:', labelwidth=25, entry_box_width=12, img='stop', validation='numeric', justify='center')
batch_end_btn = SimbaButton(parent=batch_settings_frm, txt='SET', img='tick', cmd=self._batch_set_val, cmd_kwargs={'text': lambda: batch_end_entry.entry_get.strip(), 'box_type': lambda: 'end'})
self.gpu_dropdown = SimBADropDown(parent=batch_settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU:', label_width=25, dropdown_width=12, tooltip_key='USE_GPU', img='gpu_3', state=gpu_state, value='FALSE')
self.quality_dropdown = SimBADropDown(parent=batch_settings_frm, dropdown_options=list(range(10, 110, 10)), label='OUT VIDEO QUALITY:', label_width=25, dropdown_width=12, tooltip_key='OUTPUT_VIDEO_QUALITY', img='pct_2', value=60)
data_frm.grid(row=2, column=0, sticky=NW)
batch_settings_frm.grid(row=1, column=0, sticky=NW)
batch_start_entry.grid(row=0, column=0, sticky=NW)
batch_start_btn.grid(row=0, column=1, sticky=NW)
batch_end_entry.grid(row=1, column=0, sticky=NW)
batch_end_btn.grid(row=1, column=1, sticky=NW)
self.gpu_dropdown.grid(row=2, column=0, sticky=NW)
self.quality_dropdown.grid(row=3, column=0, sticky=NW)
self.create_run_frm(run_function=self.run, btn_txt_clr="blue")
def _start_interactive_ui(self, **kwargs):
def exit_click(event):
self.click_event.set(True)
interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
interactive_ui.close()
def window_closed():
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
if interactive_ui.img_window.winfo_exists(): interactive_ui.close()
self.click_event.set(True)
interactive_ui = TimelapseSlider(video_path=kwargs['video_path'], frame_cnt=kwargs['frame_cnt'], crop_ratio=kwargs['crop_ratio'], use_timestamps=False)
interactive_ui.run()
self.click_event = BooleanVar(value=False)
interactive_ui.img_window.protocol("WM_DELETE_WINDOW", window_closed)
interactive_ui.img_window.bind(TkBinds.ESCAPE.value, exit_click); self.main_frm.bind(TkBinds.ESCAPE.value, exit_click)
self.main_frm.wait_variable(self.click_event)
try:
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
except:
pass
try:
self.main_frm.unbind(TkBinds.ESCAPE.value)
except:
pass
if not interactive_ui.img_window.winfo_exists():
pass
start_frm, end_frm = interactive_ui.get_start_frame(), interactive_ui.get_end_frame()
self.entry_boxes[kwargs['video_name']]["start"].entry_set(start_frm)
self.entry_boxes[kwargs['video_name']]["end"].entry_set(end_frm)
[docs] def run(self):
video_paths, frame_ids = [], []
for cnt, (video_name, v) in enumerate(self.entry_boxes.items()):
video_paths.append(self.video_paths[video_name])
video_frm_cnt = self.video_meta_data[cnt]
check_int(
name=f"START {video_name}", value=v["start"].entry_get, min_value=0
)
check_int(name=f"START {video_name}", value=v["end"].entry_get, min_value=1)
start, end = int(v["start"].entry_get), int(v["end"].entry_get)
if start >= end:
raise FrameRangeError(
msg=f"For video {video_name}, the start frame ({start}) is after or the same as the end frame ({end})",
source=__class__.__name__,
)
if (start < 0) or (end < 1):
raise FrameRangeError(
msg=f"For video {video_name}, start frame has to be at least 0 and end frame has to be at least 1",
source=__class__.__name__,
)
if start > video_frm_cnt:
raise FrameRangeError(
msg=f"The video {video_name} has {video_frm_cnt} frames, which is less than the start frame: {start}",
source=__class__.__name__,
)
if end > video_frm_cnt:
raise FrameRangeError(
msg=f"The video {video_name} has {video_frm_cnt} frames, which is less than the end frame: {end}",
source=__class__.__name__,
)
frame_ids.append([start, end])
gpu = str_2_bool(self.gpu_dropdown.get_value())
if gpu and not check_nvidea_gpu_available():
raise FFMPEGCodecGPUError('No GPU detected on machine. Try unchecking the GPU checkbox', source=self.__class__.__name__)
quality = int(self.quality_dropdown.get_value())
quality_crf = quality_pct_to_crf(pct=quality)
_ = clip_videos_by_frame_ids(file_paths=video_paths, frm_ids=frame_ids, save_dir=self.save_dir, gpu=gpu, quality=quality_crf)
def _batch_set_val(self, text: str, box_type: str):
for cnt, video_name in enumerate(self.video_paths.keys()):
if box_type == 'start':
self.entry_boxes[video_name]["start"].entry_set(text)
else:
self.entry_boxes[video_name]["end"].entry_set(text)
#ClipMultipleVideosByFrameNumbersPopUp(data_dir=r'E:\netholabs_videos\terry\mp4s\4_02_001_exp_2025_12_02_15_22_00\videos\Camera2', save_dir=r'E:\netholabs_videos\terry\mp4s\4_02_001_exp_2025_12_02_15_22_00\videos\Camera2\test')
#ClipMultipleVideosByFrameNumbersPopUp(data_dir=r"E:\maplight_videos\test_0126", save_dir=r"E:\maplight_videos\clip_test")
[docs]class InitiateClipMultipleVideosByFrameNumbersPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CLIP MULTIPLE VIDEOS BY FRAME NUMBERS", icon='clip')
data_frm = CreateLabelFrameWithIcon(
parent=self.main_frm,
header="SELECT DATA DIRECTORIES",
icon_name=Keys.DOCUMENTATION.value,
icon_link=Links.VIDEO_TOOLS.value,
)
self.input_folder = FolderSelect(
data_frm, "VIDEO DIRECTORY:", title="Select Folder with videos", lblwidth=30, lbl_icon='folder_video'
)
self.output_folder = FolderSelect(
data_frm,
"OUTPUT DIRECTORY:",
title="Select a folder for your output videos",
lblwidth=30,
lbl_icon='folder_2'
)
data_frm.grid(row=0, column=0, sticky=NW)
self.input_folder.grid(row=0, column=0, sticky=NW)
self.output_folder.grid(row=1, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
[docs] def run(self):
check_if_dir_exists(
in_dir=self.input_folder.folder_path,
source=self.__class__.__name__,
create_if_not_exist=False,
)
check_if_dir_exists(
in_dir=self.output_folder.folder_path,
source=self.__class__.__name__,
create_if_not_exist=True,
)
self.video_paths = find_all_videos_in_directory(
directory=self.input_folder.folder_path, as_dict=True, raise_error=True
)
self.root.destroy()
_ = ClipMultipleVideosByFrameNumbersPopUp(
data_dir=self.input_folder.folder_path,
save_dir=self.output_folder.folder_path,
)
[docs]class ClipMultipleVideosByTimestamps(PopUpMixin):
"""
:example:
>>> ClipMultipleVideosByTimestamps(data_dir=r"C:\troubleshooting\RAT_NOR\project_folder\videos\test", save_dir=r"C:\troubleshooting\RAT_NOR\project_folder\videos\test\out")
>>> ClipMultipleVideosByTimestamps(data_dir=r"C:\troubleshooting\mitra\project_folder\videos", save_dir=r"C:\troubleshooting\mitra\project_folder\videos\temp_3")
"""
def __init__(self, data_dir: Union[str, os.PathLike], save_dir: Union[str, os.PathLike]):
check_if_dir_exists(in_dir=data_dir, source=self.__class__.__name__, create_if_not_exist=False)
check_if_dir_exists(in_dir=save_dir, source=self.__class__.__name__, create_if_not_exist=True)
self.video_paths = find_all_videos_in_directory(directory=data_dir, as_dict=True, raise_error=True)
self.video_meta_data = [get_video_meta_data(video_path=x) for x in list(self.video_paths.values())]
super().__init__(title="CLIP MULTIPLE VIDEOS BY TIME-STAMPS", icon='clip')
self.save_dir = save_dir
batch_settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="BATCH SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
batch_start_entry = Entry_Box(parent=batch_settings_frm, fileDescription='START TIME (HH:MM:SS):', labelwidth=25, entry_box_width=12, img='play', justify='center')
batch_start_btn = SimbaButton(parent=batch_settings_frm, txt='SET', img='tick', cmd=self._batch_set_val, cmd_kwargs={'text': lambda: batch_start_entry.entry_get.strip(), 'box_type': lambda: 'start'})
batch_end_entry = Entry_Box(parent=batch_settings_frm, fileDescription='END TIME (HH:MM:SS):', labelwidth=25, entry_box_width=12, img='stop', justify='center')
batch_end_btn = SimbaButton(parent=batch_settings_frm, txt='SET', img='tick', cmd=self._batch_set_val, cmd_kwargs={'text': lambda: batch_end_entry.entry_get.strip(), 'box_type': lambda: 'end'})
batch_settings_frm.grid(row=0, column=0, sticky=NW)
batch_start_entry.grid(row=0, column=0, sticky=NW)
batch_start_btn.grid(row=0, column=1, sticky=NW)
batch_end_entry.grid(row=1, column=0, sticky=NW)
batch_end_btn.grid(row=1, column=1, sticky=NW)
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.gpu_dropdown = SimBADropDown(parent=batch_settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU:', label_width=25, dropdown_width=12, tooltip_key='USE_GPU', img='gpu_3', state=gpu_state, value='FALSE')
self.quality_dropdown = SimBADropDown(parent=batch_settings_frm, dropdown_options=list(range(10, 110, 10)), label='OUT VIDEO QUALITY:', label_width=25, dropdown_width=12, tooltip_key='OUTPUT_VIDEO_QUALITY', img='pct_2', value=60)
self.gpu_dropdown.grid(row=2, column=0, sticky=NW)
self.quality_dropdown.grid(row=3, column=0, sticky=NW)
self.save_dir = save_dir
padx = (0, 30)
data_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO SETTINGS", icon_name='video', icon_link=Links.VIDEO_TOOLS.value)
SimBALabel(data_frm, txt="VIDEO NAME", justify='center', font=Formats.FONT_REGULAR_BOLD.value, img='video').grid(row=0, column=0, sticky=NW, padx=padx)
SimBALabel(data_frm, txt="VIDEO LENGTH", justify='center', font=Formats.FONT_REGULAR_BOLD.value, img='timer_2').grid(row=0, column=1, sticky=NW, padx=padx)
SimBALabel(data_frm, txt="START TIME (HH:MM:SS)", justify='center', font=Formats.FONT_REGULAR_BOLD.value, img='play').grid(row=0, column=2, sticky=NW, padx=padx)
SimBALabel(data_frm, txt="END TIME (HH:MM:SS)", justify='center', font=Formats.FONT_REGULAR_BOLD.value, img='stop').grid(row=0, column=3, sticky=NW, padx=padx)
SimBALabel(data_frm, txt="TIMELAPSE VIEWER", justify='center', font=Formats.FONT_REGULAR_BOLD.value, img='monitor').grid(row=0, column=4, sticky=NW, padx=padx)
seperator = SimBASeperator(parent=data_frm, color=None, orient='horizontal', borderwidth=1)
seperator.grid(row=1, column=0, columnspan=5, rowspan=1, sticky="ew")
self.entry_boxes, self.interactive_btns = {}, {}
for cnt, (video_name, video_path) in enumerate(self.video_paths.items()):
self.entry_boxes[video_name] = {}
img = read_frm_of_video(video_path=video_path, frame_index=0, size=(420, 280), keep_aspect_ratio=True, raise_error=False)
SimBALabel(parent=data_frm, txt=video_name, justify='center', hover_img=img, font=Formats.FONT_REGULAR_BOLD.value).grid(row=cnt + 2, column=0, sticky=NW, padx=padx)
video_length = self.video_meta_data[cnt]["video_length_s"]
video_length_hhmmss = seconds_to_timestamp(seconds=video_length)
SimBALabel(data_frm, txt=video_length_hhmmss, justify='center').grid(row=cnt + 2, column=1, sticky=NW, padx=padx)
self.entry_boxes[video_name]["start"] = Entry_Box(data_frm, fileDescription="", labelwidth=0, justify='center', trace=self._hhmmss_validation)
self.entry_boxes[video_name]["end"] = Entry_Box(data_frm, fileDescription="", labelwidth=0, justify='center', trace=self._hhmmss_validation)
self.entry_boxes[video_name]["start"].grid(row=cnt + 2, column=2, sticky=NW, padx=padx)
self.entry_boxes[video_name]["end"].grid(row=cnt + 2, column=3, sticky=NW, padx=padx)
kwargs = {'video_path': self.video_paths[video_name], 'frame_cnt': 25, 'crop_ratio': 50, 'size': 100, 'video_name': video_name}
self.interactive_btns[video_name] = SimbaButton(parent=data_frm, txt='SELECT TIMES', cmd=self._start_interactive_ui, cmd_kwargs=kwargs, img='monitor')
self.interactive_btns[video_name].grid(row=cnt + 2, column=4, sticky=NW, padx=padx)
data_frm.grid(row=1, column=0, sticky=NW)
self.create_run_frm(run_function=self.run, btn_txt_clr="blue")
self.main_frm.mainloop()
def _batch_set_val(self, text: str, box_type: str):
for cnt, video_name in enumerate(self.video_paths.keys()):
if box_type == 'start': self.entry_boxes[video_name]["start"].entry_set(text)
else: self.entry_boxes[video_name]["end"].entry_set(text)
def _hhmmss_validation(self, entry_box: Entry_Box):
valid_value = check_if_string_value_is_valid_video_timestamp(value=entry_box.entry_get, name="", raise_error=False)
bg_clr = 'lightgreen' if valid_value else 'white'
entry_box.set_bg_clr(clr=bg_clr)
def _start_interactive_ui(self, **kwargs):
def exit_click(event):
self.click_event.set(True)
interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
interactive_ui.close()
def window_closed():
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
self.main_frm.unbind(TkBinds.ESCAPE.value)
if interactive_ui.img_window.winfo_exists(): interactive_ui.close()
self.click_event.set(True)
interactive_ui = TimelapseSlider(video_path=kwargs['video_path'],
frame_cnt=kwargs['frame_cnt'],
crop_ratio=kwargs['crop_ratio'])
interactive_ui.run()
self.click_event = BooleanVar(value=False)
interactive_ui.img_window.protocol("WM_DELETE_WINDOW", window_closed)
interactive_ui.img_window.bind(TkBinds.ESCAPE.value, exit_click); self.main_frm.bind(TkBinds.ESCAPE.value, exit_click)
self.main_frm.wait_variable(self.click_event)
try:
if interactive_ui.img_window.winfo_exists(): interactive_ui.img_window.unbind(TkBinds.ESCAPE.value)
except:
pass
try:
self.main_frm.unbind(TkBinds.ESCAPE.value)
except:
pass
if not interactive_ui.img_window.winfo_exists():
pass
start_time, end_time = interactive_ui.get_start_time_str(), interactive_ui.get_end_time_str()
self.entry_boxes[kwargs['video_name']]["start"].entry_set(start_time)
self.entry_boxes[kwargs['video_name']]["end"].entry_set(end_time)
self._hhmmss_validation(entry_box=self.entry_boxes[kwargs['video_name']]["start"])
self._hhmmss_validation(entry_box=self.entry_boxes[kwargs['video_name']]["end"])
[docs] def run(self):
timer = SimbaTimer(start=True)
gpu = str_2_bool(self.gpu_dropdown.get_value())
quality_pct = int(self.quality_dropdown.get_value())
for cnt, (video_name, v) in enumerate(self.entry_boxes.items()):
start, end = v["start"].entry_get, v["end"].entry_get
check_if_string_value_is_valid_video_timestamp(value=start, name=f"{video_name} START TIME" )
check_if_string_value_is_valid_video_timestamp(value=end, name=f"{video_name} END TIME")
check_that_hhmmss_start_is_before_end(start_time=start, end_time=end, name=video_name)
check_if_hhmmss_timestamp_is_valid_part_of_video(timestamp=start, video_path=self.video_paths[video_name])
check_if_hhmmss_timestamp_is_valid_part_of_video(timestamp=end, video_path=self.video_paths[video_name])
clip_video_in_range(file_path=self.video_paths[video_name], start_time=start, end_time=end, out_dir=self.save_dir, overwrite=True, include_clip_time_in_filename=False, gpu=gpu, quality=quality_pct, codec='libx264', verbose=True)
timer.stop_timer()
stdout_success(msg=f"{len(self.entry_boxes)} videos clipped by time-stamps and saved in {self.save_dir}", elapsed_time=timer.elapsed_time_str,)
#ClipMultipleVideosByTimestamps(data_dir=r"E:\maplight_videos\test_0126", save_dir=r"E:\maplight_videos\clip_test")
[docs]class InitiateClipMultipleVideosByTimestampsPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CLIP MULTIPLE VIDEOS BY TIME-STAMPS", icon='clip')
data_frm = CreateLabelFrameWithIcon(
parent=self.main_frm,
header="SELECT DATA DIRECTORIES",
icon_name=Keys.DOCUMENTATION.value,
icon_link=Links.VIDEO_TOOLS.value,
)
self.input_folder = FolderSelect(
data_frm, "VIDEO DIRECTORY:", title="Select Folder with videos", lblwidth=30, lbl_icon='folder'
)
self.output_folder = FolderSelect(
data_frm,
"OUTPUT DIRECTORY:",
title="Select a folder for your output videos",
lblwidth=30,
lbl_icon='folder'
)
data_frm.grid(row=0, column=0, sticky=NW)
self.input_folder.grid(row=0, column=0, sticky=NW)
self.output_folder.grid(row=1, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
[docs] def run(self):
check_if_dir_exists(
in_dir=self.input_folder.folder_path,
source=self.__class__.__name__,
create_if_not_exist=False,
)
check_if_dir_exists(
in_dir=self.output_folder.folder_path,
source=self.__class__.__name__,
create_if_not_exist=True,
)
self.video_paths = find_all_videos_in_directory(
directory=self.input_folder.folder_path, as_dict=True, raise_error=True
)
self.root.destroy()
_ = ClipMultipleVideosByTimestamps(
data_dir=self.input_folder.folder_path,
save_dir=self.output_folder.folder_path,
)
[docs]class BrightnessContrastPopUp(PopUpMixin):
"""
.. video:: _static/img/brightness_contrast_ui.webm
:width: 700
:autoplay:
:loop:
:muted:
:align: center
"""
def __init__(self):
super().__init__(title="CHANGE BRIGHTNESS / CONTRAST", icon='brightness')
self.datetime = datetime.now().strftime("%Y%m%d%H%M%S")
setting_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=setting_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], dropdown_width=20, value='FALSE', state=gpu_available, img='gpu_3', label_width=25)
setting_frm.grid(row=0, column=0, sticky="NW")
self.gpu_dropdown.grid(row=0, column=0, sticky="NW")
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CHANGE BRIGHTNESS / CONTRAST SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=25, lbl_icon='video_2')
run_video_btn = SimbaButton(parent=single_video_frm, txt="RUN SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_video)
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
run_video_btn.grid(row=1, column=0, sticky="NW")
video_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CHANGE BRIGHTNESS / CONTRAST MULTIPLE VIDEOS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_dir = FolderSelect(video_dir_frm, "VIDEO DIRECTORY PATH:", lblwidth=25, lbl_icon='folder')
run_dir_btn = SimbaButton(parent=video_dir_frm, txt="RUN VIDEO DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_directory)
video_dir_frm.grid(row=2, column=0, sticky="NW")
self.selected_dir.grid(row=0, column=0, sticky="NW")
run_dir_btn.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run_video(self):
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
ui = BrightnessContrastUI(data=video_path)
self.brightness, self.contrast = ui.run()
self.video_paths = [video_path]
self.apply()
[docs] def run_directory(self):
video_dir = self.selected_dir.folder_path
check_if_dir_exists(in_dir=video_dir, source=self.__class__.__name__)
self.video_paths = find_files_of_filetypes_in_directory(directory=video_dir, extensions=Options.ALL_VIDEO_FORMAT_OPTIONS.value, raise_error=True)
ui = BrightnessContrastUI(data=self.video_paths[0])
self.brightness, self.contrast = ui.run()
self.apply()
[docs] def apply(self):
timer = SimbaTimer(start=True)
gpu = str_2_bool(self.gpu_dropdown.get_value())
for file_cnt, file_path in enumerate(self.video_paths):
video_timer = SimbaTimer(start=True)
dir, video_name, ext = get_fn_ext(filepath=file_path)
print(f'Creating copy of {video_name}...')
out_path = os.path.join(dir, f'{video_name}_eq_{self.datetime}{ext}')
if not gpu:
cmd = f'ffmpeg -i "{file_path}" -vf "eq=brightness={self.brightness}:contrast={self.contrast}" -loglevel error -stats "{out_path}" -y'
else:
cmd = f'ffmpeg -hwaccel auto -i "{file_path}" -vf "eq=brightness={self.brightness}:contrast={self.contrast}" -c:v h264_nvenc -loglevel error -stats "{out_path}" -y'
#cmd = f'ffmpeg -i -hwaccel auto "{file_path}" -vf "eq=brightness={self.brightness}:contrast={self.contrast}" -c:v h264_nvenc -loglevel error -stats "{out_path}" -y'
subprocess.call(cmd, shell=True, stdout=subprocess.PIPE)
video_timer.stop_timer()
stdout_success(msg=f'Video {out_path} complete!', elapsed_time=video_timer.elapsed_time_str)
timer.stop_timer()
stdout_success(f'{len(self.video_paths)} video(s) converted.', elapsed_time=timer.elapsed_time_str)
#BrightnessContrastPopUp()
[docs]class InteractiveClahePopUp(PopUpMixin):
"""
.. video:: _static/img/interactive_clahe_ui.webm
:width: 500
:autoplay:
:loop:
:muted:
:align: center
"""
def __init__(self):
super().__init__(title="INTERACTIVE CLAHE", icon='clahe')
self.datetime = datetime.now().strftime("%Y%m%d%H%M%S")
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name='settings', icon_link=Links.VIDEO_TOOLS.value)
self.core_cnt_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, find_core_cnt()[0]+1)), label='CORE COUNT:', label_width=25, dropdown_width=20, value=1, img='cpu_small')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label='USE GPU:', label_width=25, dropdown_width=20, value='FALSE', img='gpu_3')
if not check_nvidea_gpu_available():
self.gpu_dropdown.disable()
settings_frm.grid(row=0, column=0, sticky=NW)
self.core_cnt_dropdown.grid(row=0, column=0, sticky=NW)
self.gpu_dropdown.grid(row=1, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="INTERACTIVE CLAHE - SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lblwidth=25, lbl_icon='video_2')
run_video_btn = SimbaButton(parent=single_video_frm, txt="RUN SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_video, width=160)
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
run_video_btn.grid(row=1, column=0, sticky="NW")
video_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="INTERACTIVE CLAHE - MULTIPLE VIDEOS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_dir = FolderSelect(video_dir_frm, "VIDEO DIRECTORY PATH:", lblwidth=25, lbl_icon='folder')
run_dir_btn = SimbaButton(parent=video_dir_frm, txt="RUN VIDEO DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.run_directory, width=160)
video_dir_frm.grid(row=2, column=0, sticky="NW")
self.selected_dir.grid(row=0, column=0, sticky="NW")
run_dir_btn.grid(row=1, column=0, sticky="NW")
[docs] def run_video(self):
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
self.clip_limit, self.tile_size = interactive_clahe_ui(data=video_path)
self.video_paths = [video_path]
self.apply()
[docs] def run_directory(self):
video_dir = self.selected_dir.folder_path
check_if_dir_exists(in_dir=video_dir, source=self.__class__.__name__)
self.video_paths = find_files_of_filetypes_in_directory(directory=video_dir, extensions=Options.ALL_VIDEO_FORMAT_OPTIONS.value, raise_error=True)
self.clip_limit, self.tile_size = interactive_clahe_ui(data=self.video_paths[0])
self.apply()
def _get_settings(self):
self.core_cnt = int(self.core_cnt_dropdown.get_value())
self.gpu = str_2_bool(self.gpu_dropdown.get_value())
[docs] def apply(self):
timer = SimbaTimer(start=True)
self._get_settings()
for file_cnt, file_path in enumerate(self.video_paths):
dir, video_name, ext = get_fn_ext(filepath=file_path)
print(f'Creating CLAHE copy of {video_name}...')
out_path = os.path.join(dir, f'{video_name}_CLAHE_CLIPLIMIT_{int(self.clip_limit)}_TILESIZE_{int(self.tile_size)}_{self.datetime}{ext}')
if self.core_cnt == 1:
clahe_enhance_video(file_path=file_path, clip_limit=int(self.clip_limit), tile_grid_size=(int(self.tile_size), int(self.tile_size)), out_path=out_path)
else:
clahe_enhance_video_mp(file_path=file_path, clip_limit=int(self.clip_limit), tile_grid_size=(int(self.tile_size), int(self.tile_size)), out_path=out_path, gpu=self.gpu)
timer.stop_timer()
stdout_success(f'{len(self.video_paths)} video(s) converted.', elapsed_time=timer.elapsed_time_str)
#_ = InteractiveClahePopUp()
[docs]class DownsampleSingleVideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self,title="DOWN-SAMPLE SINGLE VIDEO RESOLUTION", icon='minus')
choose_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SELECT VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.DOWNSAMPLE.value)
self.video_path_selected = FileSelect(choose_video_frm, "VIDEO PATH: ", title="Select a video file", file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)])
choose_video_frm.grid(row=0, column=0, sticky=NW)
self.video_path_selected.grid(row=0, column=0, sticky=NW)
gpu_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="GPU (REDUCED RUNTIMES)", icon_name='gpu_3', icon_link=Links.DOWNSAMPLE.value)
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=gpu_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], label_width=20, dropdown_width=20, value='FALSE', state=gpu_available, img='gpu_3')
gpu_frm.grid(row=1, column=0, sticky=NW)
self.gpu_dropdown.grid(row=0, column=0, sticky=NW)
quality_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="OUTPUT QUALITY", icon_name='pct_2', icon_link=Links.DOWNSAMPLE.value)
self.quality_dropdown = SimBADropDown(parent=quality_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=20, dropdown_width=35, value=60, img='pct_2', tooltip_key='OUPUT_VIDEO_QUALITY')
quality_frm.grid(row=2, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
custom_size_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CUSTOM RESOLUTION", icon_name='monitor', icon_link=Links.DOWNSAMPLE.value,padx=5,pady=5)
self.entry_width = Entry_Box(custom_size_frm, "WIDTH:", 20, validation="numeric", img='width')
self.entry_height = Entry_Box(custom_size_frm, "HEIGHT", 20, validation="numeric", img='height')
self.custom_downsample_btn = SimbaButton(parent=custom_size_frm, txt="DOWN-SAMPLE USING CUSTOM RESOLUTION", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.downsample_custom)
custom_size_frm.grid(row=3, column=0, sticky=NW)
self.entry_width.grid(row=0, column=0, sticky=NW)
self.entry_height.grid(row=1, column=0, sticky=NW)
self.custom_downsample_btn.grid(row=2, column=0, sticky=NW)
default_size_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="DEFAULT RESOLUTION", icon_name='monitor', icon_link=Links.DOWNSAMPLE.value,padx=5,pady=5)
self.width_dropdown = SimBADropDown(parent=default_size_frm, label="WIDTH:", dropdown_options=Options.RESOLUTION_OPTIONS_2.value, label_width=20, dropdown_width=20, value=640, img='width')
self.height_dropdown = SimBADropDown(parent=default_size_frm, label="HEIGHT:", dropdown_options=Options.RESOLUTION_OPTIONS_2.value, label_width=20, dropdown_width=20, value="AUTO", img='height')
self.default_downsample_btn = SimbaButton(parent=default_size_frm, txt="DOWN-SAMPLE USING DEFAULT RESOLUTION", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=self.downsample_default)
default_size_frm.grid(row=4, column=0, sticky=NW)
self.width_dropdown.grid(row=0, column=0, sticky=NW)
self.height_dropdown.grid(row=1, column=0, sticky=NW)
self.default_downsample_btn.grid(row=2, column=0, sticky=NW)
def _checks(self):
check_ffmpeg_available(raise_error=True)
self.gpu = str_2_bool(self.gpu_dropdown.get_value())
self.file_path = self.video_path_selected.file_path
check_file_exist_and_readable(file_path=self.file_path)
_ = get_video_meta_data(video_path=self.file_path)
quality = int(self.quality_dropdown.get_value())
self.quality_crf = quality_pct_to_crf(pct=quality)
[docs] def downsample_custom(self):
self._checks()
width, height = self.entry_width.entry_get, self.entry_height.entry_get
check_int(name=f'{self.__class__.__name__} width', value=width, min_value=1)
check_int(name=f'{self.__class__.__name__} height', value=height, min_value=1)
threading.Thread(target=downsample_video(file_path=self.file_path, video_height=height, video_width=width, gpu=self.gpu, quality=self.quality_crf)).start()
[docs] def downsample_default(self):
self._checks()
width, height = self.width_dropdown.getChoices(), self.height_dropdown.getChoices()
if width == 'AUTO' and height == 'AUTO':
raise InvalidInputError(msg='Both width and height cannot be AUTO', source=self.__class__.__name__)
elif width == 'AUTO':
resize_videos_by_height(video_paths=[self.file_path], height=int(height), overwrite=False, save_dir=None, gpu=self.gpu, suffix='downsampled', quality=self.quality_crf, verbose=True)
elif height == 'AUTO':
resize_videos_by_width(video_paths=[self.file_path], width=int(width), overwrite=False, save_dir=None, gpu=self.gpu, suffix='downsampled', quality=self.quality_crf, verbose=True)
else:
threading.Thread(target=downsample_video(file_path=self.file_path, video_height=height, video_width=width, gpu=self.gpu, quality=self.quality_crf)).start()
[docs]class DownsampleMultipleVideosPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self,title="DOWN-SAMPLE MULTIPLE VIDEO RESOLUTION", icon='minus')
choose_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SELECT VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.DOWNSAMPLE.value)
self.video_dir_selected = FolderSelect(choose_video_frm, "VIDEO DIRECTORY:",title="Select Folder with videos", lblwidth=20)
choose_video_frm.grid(row=0, column=0, sticky=NW)
self.video_dir_selected.grid(row=0, column=0, sticky=NW)
gpu_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="GPU (REDUCED RUNTIMES)", icon_name='gpu_3', icon_link=Links.DOWNSAMPLE.value)
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.gpu_dropdown = SimBADropDown(parent=gpu_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], dropdown_width=20, value='FALSE', state=gpu_available, img='gpu_3', label_width=20)
gpu_frm.grid(row=1, column=0, sticky=NW)
self.gpu_dropdown.grid(row=0, column=0, sticky=NW)
quality_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="OUTPUT QUALITY", icon_name='pct_2', icon_link=Links.DOWNSAMPLE.value)
self.quality_dropdown = SimBADropDown(parent=quality_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=20, dropdown_width=35, value=60, img='pct_2', tooltip_key='OUPUT_VIDEO_QUALITY')
quality_frm.grid(row=2, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
custom_size_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CUSTOM RESOLUTION", icon_name='monitor', icon_link=Links.DOWNSAMPLE.value,padx=5,pady=5)
self.entry_width = Entry_Box(custom_size_frm, "WIDTH:", 20, validation="numeric", img='width')
self.entry_height = Entry_Box(custom_size_frm, "HEIGHT", 20, validation="numeric", img='height')
self.custom_downsample_btn = SimbaButton(parent=custom_size_frm, txt="DOWN-SAMPLE USING CUSTOM RESOLUTION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.downsample_custom)
custom_size_frm.grid(row=3, column=0, sticky=NW)
self.entry_width.grid(row=0, column=0, sticky=NW)
self.entry_height.grid(row=1, column=0, sticky=NW)
self.custom_downsample_btn.grid(row=2, column=0, sticky=NW)
default_size_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="DEFAULT RESOLUTION", icon_name='monitor', icon_link=Links.DOWNSAMPLE.value,padx=5,pady=5)
self.width_dropdown = SimBADropDown(parent=default_size_frm, label="WIDTH:", dropdown_options=Options.RESOLUTION_OPTIONS_2.value, label_width=20, dropdown_width=20, value=640, img='width')
self.height_dropdown = SimBADropDown(parent=default_size_frm, label="HEIGHT:", dropdown_options=Options.RESOLUTION_OPTIONS_2.value, label_width=20, dropdown_width=20, value="AUTO", img='height')
self.default_downsample_btn = SimbaButton(parent=default_size_frm, txt="DOWN-SAMPLE USING DEFAULT RESOLUTION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.downsample_default)
default_size_frm.grid(row=4, column=0, sticky=NW)
self.width_dropdown.grid(row=0, column=0, sticky=NW)
self.height_dropdown.grid(row=1, column=0, sticky=NW)
self.default_downsample_btn.grid(row=2, column=0, sticky=NW)
def _checks(self):
check_ffmpeg_available(raise_error=True)
self.gpu = str_2_bool(self.gpu_dropdown.get_value())
self.video_directory = self.video_dir_selected.folder_path
check_if_dir_exists(in_dir=self.video_directory)
self.video_paths = find_all_videos_in_directory(directory=self.video_directory, raise_error=True, as_dict=True)
quality = int(self.quality_dropdown.get_value())
self.quality_crf = quality_pct_to_crf(pct=quality)
[docs] def downsample_custom(self):
self._checks()
width, height = self.entry_width.entry_get, self.entry_height.entry_get
check_int(name=f'{self.__class__.__name__} width', value=width, min_value=1)
check_int(name=f'{self.__class__.__name__} height', value=height, min_value=1)
for file_path in self.video_paths.values():
threading.Thread(target=downsample_video(file_path=file_path, video_height=height, video_width=width, gpu=self.gpu, quality=self.quality_crf)).start()
[docs] def downsample_default(self):
self._checks()
width, height = self.width_dropdown.getChoices(), self.height_dropdown.getChoices()
if width == 'AUTO' and height == 'AUTO':
raise InvalidInputError(msg='Both width and height cannot be AUTO', source=self.__class__.__name__)
elif width == 'AUTO':
resize_videos_by_height(video_paths=list(self.video_paths.values()), height=int(height), overwrite=False, save_dir=None, gpu=self.gpu, suffix='downsampled', quality=self.quality_crf, verbose=True)
elif height == 'AUTO':
resize_videos_by_width(video_paths=list(self.video_paths.values()), width=int(width), overwrite=False, save_dir=None, gpu=self.gpu, suffix='downsampled', quality=self.quality_crf, verbose=True)
else:
for file_path in self.video_paths.values():
threading.Thread(target=downsample_video(file_path=file_path, video_height=height, video_width=width, gpu=self.gpu, quality=self.quality_crf)).start()
#DownsampleMultipleVideosPopUp()
[docs]class Convert2jpegPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CONVERT IMAGES TO JPEG", icon='jpeg')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.quality_scale = SimBAScaleBar(parent=settings_frm, label="JPEG OUTPUT QUALITY: ", orient=HORIZONTAL, length=200, value=95, label_width=25, lbl_img='pct_2')
settings_frm.grid(row=0, column=0, sticky="NW")
self.quality_scale.grid(row=0, column=0, sticky="NW")
img_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE DIRECTORY TO JPEG", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_frame_dir = FolderSelect(img_dir_frm, "IMAGE DIRECTORY PATH:", title="Select a image directory", lblwidth=25, lbl_icon='folder')
run_btn_dir = SimbaButton(parent=img_dir_frm, txt="RUN DIRECTORY JPEG CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.run_dir)
img_dir_frm.grid(row=1, column=0, sticky="NW")
self.selected_frame_dir.grid(row=0, column=0, sticky="NW")
run_btn_dir.grid(row=1, column=0, sticky="NW")
img_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE TO JPEG", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_file = FileSelect(img_frm, "IMAGE PATH:", title="Select an image file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_IMAGE_FORMAT_OPTIONS.value)], lbl_icon='frames')
run_btn_img = SimbaButton(parent=img_frm, txt="RUN IMAGE JPEG CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.run_img)
img_frm.grid(row=2, column=0, sticky="NW")
self.selected_file.grid(row=0, column=0, sticky="NW")
run_btn_img.grid(row=1, column=0, sticky="NW")
[docs] def run_dir(self):
folder_path = self.selected_frame_dir.folder_path
check_if_dir_exists(in_dir=folder_path)
_ = convert_to_jpeg(path=folder_path, quality=int(self.quality_scale.get_value()), verbose=True)
[docs] def run_img(self):
file_path = self.selected_file.file_path
check_file_exist_and_readable(file_path)
_ = convert_to_jpeg(path=file_path, quality=int(self.quality_scale.get_value()), verbose=True)
[docs]class Convert2bmpPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CONVERT IMAGES TO BMP", icon='bmp')
img_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE DIRECTORY TO BMP", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_frame_dir = FolderSelect(img_dir_frm, "IMAGE DIRECTORY PATH:", title="Select a image directory", lblwidth=25, lbl_icon='folder')
run_btn_dir = SimbaButton(parent=img_dir_frm, txt="RUN DIRECTORY BMP CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.run_dir)
img_dir_frm.grid(row=0, column=0, sticky="NW")
self.selected_frame_dir.grid(row=0, column=0, sticky="NW")
run_btn_dir.grid(row=1, column=0, sticky="NW")
img_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE TO BMP", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_file = FileSelect(img_frm, "IMAGE PATH:", title="Select an image file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_IMAGE_FORMAT_OPTIONS.value)], lbl_icon='bmp')
run_btn_img = SimbaButton(parent=img_frm, txt="RUN IMAGE BMP CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run_img())
img_frm.grid(row=1, column=0, sticky="NW")
self.selected_file.grid(row=0, column=0, sticky="NW")
run_btn_img.grid(row=1, column=0, sticky="NW")
[docs] def run_dir(self):
folder_path = self.selected_frame_dir.folder_path
check_if_dir_exists(in_dir=folder_path)
_ = convert_to_bmp(path=folder_path, verbose=True)
[docs] def run_img(self):
file_path = self.selected_file.file_path
check_file_exist_and_readable(file_path)
_ = convert_to_bmp(path=file_path, verbose=True)
[docs]class Convert2WEBPPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CONVERT IMAGES TO WEBP", icon='webp')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.quality_scale = SimBAScaleBar(parent=settings_frm, from_=0, to=100, length=200, label='WEBP QUALITY: ', label_clr='black', lbl_font=Formats.FONT_REGULAR.value, value=95, tickinterval=25, sliderrelief='raised', showvalue=True, lbl_img='pct')
settings_frm.grid(row=0, column=0, sticky="NW")
self.quality_scale.grid(row=0, column=0, sticky="NW")
convert_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE DIRECTORY TO WEBP", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_frame_dir = FolderSelect(convert_dir_frm, "IMAGE DIRECTORY PATH:", title="Select a image directory", lblwidth=25, lbl_icon='browse')
run_btn_dir = SimbaButton(parent=convert_dir_frm, txt="RUN IMAGE DIRECTORY WEBP CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.run_dir)
convert_dir_frm.grid(row=1, column=0, sticky="NW")
self.selected_frame_dir.grid(row=0, column=0, sticky="NW")
run_btn_dir.grid(row=1, column=0, sticky="NW")
convert_img_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE FILE TO WEBP", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_file = FileSelect(convert_img_frm, "IMAGE PATH:", title="Select an image file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_IMAGE_FORMAT_OPTIONS.value)], lbl_icon='file_type')
run_btn_frm = SimbaButton(parent=convert_img_frm, txt="RUN IMAGE WEBP CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=self.run_img)
convert_img_frm.grid(row=2, column=0, sticky="NW")
self.selected_file.grid(row=0, column=0, sticky="NW")
run_btn_frm.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run_dir(self):
folder_path = self.selected_frame_dir.folder_path
check_if_dir_exists(in_dir=folder_path)
quality = int(self.quality_scale.get_value())
_ = convert_to_webp(path=folder_path, quality=quality, verbose=True)
[docs] def run_img(self):
file_path = self.selected_file.file_path
check_file_exist_and_readable(file_path)
quality = int(self.quality_scale.get_value())
_ = convert_to_webp(path=file_path, quality=quality, verbose=True)
#Convert2WEBPPopUp()
[docs]class Convert2TIFFPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CONVERT IMAGE DIRECTORY TO TIFF", icon='tiff')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_frame_dir = FolderSelect(settings_frm, "IMAGE DIRECTORY PATH:", title="Select a image directory", lblwidth=25, lbl_icon='browse')
self.compression_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['raw', 'tiff_deflate', 'tiff_lzw'], label="COMPRESSION:", label_width=25, dropdown_width=25, value='raw', img='file_type')
self.stack_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['FALSE', 'TRUE'], label="STACK:", label_width=25, dropdown_width=25, value='FALSE', img='stack')
self.create_run_frm(run_function=self.run, title='RUN TIFF CONVERSION')
settings_frm.grid(row=0, column=0, sticky="NW")
self.selected_frame_dir.grid(row=0, column=0, sticky="NW")
self.compression_dropdown.grid(row=1, column=0, sticky="NW")
self.stack_dropdown.grid(row=2, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self):
folder_path = self.selected_frame_dir.folder_path
check_if_dir_exists(in_dir=folder_path)
stack = str_2_bool(self.stack_dropdown.get_value())
convert_to_tiff(directory=folder_path, compression=self.compression_dropdown.get_value(), verbose=True, stack=stack)
[docs]class Convert2PNGPopUp(PopUpMixin):
def __init__(self):
super().__init__(title="CONVERT IMAGE TO PNG", icon='png')
img_dir_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE DIRECTORY TO PNG", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_frame_dir = FolderSelect(img_dir_frm, "IMAGE DIRECTORY PATH:", title="Select a image directory", lblwidth=25, lbl_icon='folder')
run_btn_dir = SimbaButton(parent=img_dir_frm, txt="RUN DIRECTORY PNG CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run_dir())
img_dir_frm.grid(row=0, column=0, sticky="NW")
self.selected_frame_dir.grid(row=0, column=0, sticky="NW")
run_btn_dir.grid(row=1, column=0, sticky="NW")
img_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="CONVERT IMAGE TO PNG", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_file_dir = FileSelect(img_frm, "IMAGE PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_IMAGE_FORMAT_OPTIONS.value)], lbl_icon='file_type')
run_btn_img = SimbaButton(parent=img_frm, txt="RUN IMAGE PNG CONVERSION", img='rocket', txt_clr='black', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run_img())
img_frm.grid(row=1, column=0, sticky="NW")
self.selected_file_dir.grid(row=0, column=0, sticky="NW")
run_btn_img.grid(row=1, column=0, sticky="NW")
self.main_frm.mainloop()
[docs] def run_dir(self):
folder_path = self.selected_frame_dir.folder_path
check_if_dir_exists(in_dir=folder_path)
_ = convert_to_png(path=folder_path, verbose=True)
[docs] def run_img(self):
file_path = self.selected_file_dir.file_path
check_file_exist_and_readable(file_path)
_ = convert_to_png(path=file_path, verbose=True)
[docs]class Convert2MP4PopUp(PopUpMixin):
"""
:example:
>>> Convert2MP4PopUp()
"""
def __init__(self):
self.MP4_CODEC_LK = {'HEVC (H.265)': 'libx265', 'H.264 (AVC)': 'libx264', 'VP9': 'vp9', 'GPU (h264_cuvid)': 'h264_cuvid', 'Guaranteed powerpoint compatible': 'powerpoint'}
self.cpu_codec_qualities = list(range(10, 110, 10))
self.gpu_codec_qualities = ['Low', 'Medium', 'High']
super().__init__(title="CONVERT VIDEOS TO MP4", icon='mp4')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name='settings', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5, relief='solid')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=self.cpu_codec_qualities, label="OUTPUT VIDEO QUALITY:", label_width=30, dropdown_width=40, value=60, img='pct', tooltip_key='CONVERT2MP4_QUALITY')
self.codec_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.MP4_CODEC_LK.keys()), label="COMPRESSION CODEC:", label_width=30, dropdown_width=40, value='H.264 (AVC)', command=self.update_quality_dropdown, img='file_type', tooltip_key='CONVERT2MP4_CODEC')
self.keep_audio_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['FALSE', 'TRUE'], label="KEEP AUDIO (IF EXIST):", label_width=30, dropdown_width=40, value='FALSE', img='audio', tooltip_key='CONVERT2MP4_KEEP_AUDIO')
settings_frm.grid(row=0, column=0, sticky=NW, padx=10, pady=10)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
self.codec_dropdown.grid(row=1, column=0, sticky=NW)
self.keep_audio_dropdown.grid(row=2, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO", icon_name='video', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5, relief='solid')
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=30, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file', tooltip_key='CONVERT2MP4_VIDEO_PATH')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', cmd=self.run, cmd_kwargs={'multiple': False})
single_video_frm.grid(row=1, column=0, sticky=NW, padx=10, pady=10)
self.selected_video.grid(row=0, column=0, sticky=NW)
single_video_run.grid(row=1, column=0, sticky=NW)
multiple_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO DIRECTORY", icon_name='stack', icon_link=Links.VIDEO_TOOLS.value, padx=5, pady=5, relief='solid')
self.selected_video_dir = FolderSelect(multiple_video_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=30, lbl_icon='browse', tooltip_key='CONVERT2MP4_VIDEO_DIR_PATH')
multiple_video_run = SimbaButton(parent=multiple_video_frm, txt="RUN - VIDEO DIRECTORY", img='rocket', cmd=self.run, cmd_kwargs={'multiple': True})
multiple_video_frm.grid(row=2, column=0, sticky=NW, padx=10, pady=10)
multiple_video_run.grid(row=1, column=0, sticky=NW)
self.selected_video_dir.grid(row=0, column=0, sticky=NW)
self.main_frm.mainloop()
[docs] def update_quality_dropdown(self, k):
if k == 'GPU (h264_cuvid)': option_lst = self.gpu_codec_qualities
else: option_lst = self.cpu_codec_qualities
self.quality_dropdown.dropdown['values'] = option_lst
self.quality_dropdown.dropdown.set(option_lst[0])
[docs] def run(self, multiple: bool):
if not multiple:
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
else:
video_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=video_path, source=self.__class__.__name__)
codec = self.MP4_CODEC_LK[self.codec_dropdown.getChoices()]
quality = self.quality_dropdown.getChoices()
audio = str_2_bool(self.keep_audio_dropdown.get_value())
threading.Thread(target=convert_to_mp4(path=video_path, codec=codec, quality=quality, keep_audio=audio))
#Convert2MP4PopUp()
[docs]class Convert2AVIPopUp(PopUpMixin):
"""
:example:
>>> Convert2AVIPopUp()
"""
def __init__(self):
super().__init__(title="CONVERT VIDEOS TO AVI", icon='avi')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.AVI_CODEC_LK = {'XviD': 'xvid', 'DivX': 'divx', 'MJPEG': 'mjpeg'}
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=25, dropdown_width=30, value=60, img='pct')
self.codec_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.AVI_CODEC_LK.keys()), label="COMPRESSION CODEC:", label_width=25, dropdown_width=30, value='DivX', img='file_type')
settings_frm.grid(row=0, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
self.codec_dropdown.grid(row=1, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky=NW)
self.selected_video.grid(row=0, column=0, sticky=NW)
single_video_run.grid(row=1, column=0, sticky=NW)
multiple_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO DIRECTORY", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_video_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='browse')
multiple_video_run = SimbaButton(parent=multiple_video_frm, txt="RUN - VIDEO DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_video_frm.grid(row=2, column=0, sticky=NW)
self.selected_video_dir.grid(row=0, column=0, sticky=NW)
multiple_video_run.grid(row=1, column=0, sticky=NW)
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
if not multiple:
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
else:
video_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=video_path, source=self.__class__.__name__)
codec = self.AVI_CODEC_LK[self.codec_dropdown.getChoices()]
quality = int(self.quality_dropdown.getChoices())
threading.Thread(target=convert_to_avi(path=video_path, codec=codec, quality=quality))
[docs]class Convert2WEBMPopUp(PopUpMixin):
"""
:example:
>>> Convert2WEBMPopUp()
"""
def __init__(self):
super().__init__(title="CONVERT VIDEOS TO WEBM", icon='webm')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.WEBM_CODEC_LK = {'VP8': 'vp8', 'VP9': 'vp9', 'AV1': 'av1'}
self.quality_dropdown = SimBADropDown(parent=settings_frm, label="OUTPUT VIDEO QUALITY:", dropdown_options=list(range(10, 110, 10)), label_width=25, value=60, img='pct', dropdown_width=30)
self.codec_dropdown = SimBADropDown(parent=settings_frm, label="COMPRESSION CODEC:", dropdown_options=list(self.WEBM_CODEC_LK.keys()), label_width=25, value='VP9', img='file_type', dropdown_width=30)
settings_frm.grid(row=0, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
self.codec_dropdown.grid(row=1, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky=NW)
self.selected_video.grid(row=0, column=0, sticky=NW)
single_video_run.grid(row=1, column=0, sticky=NW)
multiple_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO DIRECTORY", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_video_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='browse')
multiple_video_run = SimbaButton(parent=multiple_video_frm, txt="RUN - VIDEO DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_video_frm.grid(row=2, column=0, sticky=NW)
self.selected_video_dir.grid(row=0, column=0, sticky=NW)
multiple_video_run.grid(row=1, column=0, sticky=NW)
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
if not multiple:
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
else:
video_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=video_path, source=self.__class__.__name__)
codec = self.WEBM_CODEC_LK[self.codec_dropdown.getChoices()]
quality = int(self.quality_dropdown.getChoices())
threading.Thread(target=convert_to_webm(path=video_path, codec=codec, quality=quality))
#Convert2WEBMPopUp()
[docs]class Convert2MOVPopUp(PopUpMixin):
"""
:example:
>>> Convert2MOVPopUp()
"""
def __init__(self):
super().__init__(title="CONVERT VIDEOS TO MOV")
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.MOV_CODEC_LK = {'ProRes Kostya Samanta': 'prores',
'Animation': 'animation',
'CineForm': 'cineform',
'DNxHD/DNxHR': 'dnxhd'}
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=25, dropdown_width=30, value=60, img='pct', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.codec_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.MOV_CODEC_LK.keys()), label="COMPRESSION CODEC:", label_width=25, dropdown_width=30, value='ProRes Kostya Samanta', img='file_type')
settings_frm.grid(row=0, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
self.codec_dropdown.grid(row=1, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)])
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky=NW)
self.selected_video.grid(row=0, column=0, sticky=NW)
single_video_run.grid(row=1, column=0, sticky=NW)
multiple_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO DIRECTORY", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_video_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='browse')
multiple_video_run = SimbaButton(parent=multiple_video_frm, txt="RUN - VIDEO DIRECTORY", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_video_frm.grid(row=2, column=0, sticky=NW)
self.selected_video_dir.grid(row=0, column=0, sticky=NW)
multiple_video_run.grid(row=1, column=0, sticky=NW)
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
if not multiple:
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
else:
video_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=video_path, source=self.__class__.__name__)
codec = self.MOV_CODEC_LK[self.codec_dropdown.get_value()]
quality = int(self.quality_dropdown.get_value())
threading.Thread(target=convert_to_mov(path=video_path, codec=codec, quality=quality))
[docs]class SuperimposeWatermarkPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="WATERMARK VIDEOS", icon='watermark_green')
self.LOCATIONS = {'TOP LEFT': 'top_left', 'TOP RIGHT': 'top_right', 'BOTTOM LEFT': 'bottom_left', 'BOTTOM RIGHT': 'bottom_right', 'CENTER': 'center'}
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
opacities = [round(x, 1) for x in list(np.arange(0.1, 1.1, 0.1))]
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.selected_img = FileSelect(settings_frm, "WATERMARK IMAGE PATH:", title="Select an image file", file_types=[("VIDEO", Options.ALL_IMAGE_FORMAT_OPTIONS.value)], lblwidth=25, lbl_icon='frames', tooltip_key='WATERMARK_IMAGE_PATH')
self.location_dropdown = SimBADropDown(parent=settings_frm, label="WATERMARK LOCATION:", dropdown_options=list(self.LOCATIONS.keys()), label_width=25, dropdown_width=30, img='location', value='TOP LEFT', tooltip_key='WATERMARK_LOCATION')
self.opacity_dropdown = SimBADropDown(parent=settings_frm, label="WATERMARK OPACITY:", dropdown_options=opacities, label_width=25, dropdown_width=30, img='opacity', value=0.5, tooltip_key='WATERMARK_OPACITY')
self.size_dropdown = SimBADropDown(parent=settings_frm, label="WATERMARK SCALE %:", dropdown_options=list(range(5, 100, 5)), label_width=25, dropdown_width=30, img='size_black', value=5, tooltip_key='WATERMARK_SCALE')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], label_width=25, dropdown_width=30, img='gpu_3', value='FALSE', state=self.gpu_available, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.selected_img.grid(row=0, column=0, sticky=NW)
self.location_dropdown.grid(row=1, column=0, sticky=NW)
self.opacity_dropdown.grid(row=2, column=0, sticky=NW)
self.size_dropdown.grid(row=3, column=0, sticky=NW)
self.gpu_dropdown.grid(row=4, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - SUPERIMPOSE WATERMARK", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - SUPERIMPOSE WATERMARK", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
gpu = str_2_bool(self.gpu_dropdown.get_value())
img_path = self.selected_img.file_path
loc = self.location_dropdown.get_value()
loc = self.LOCATIONS[loc]
opacity = float(self.opacity_dropdown.get_value())
size = float(int(self.size_dropdown.get_value()) / 100)
if size == 1.0: size = size - 0.001
check_file_exist_and_readable(file_path=img_path)
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=watermark_video(video_path=data_path,
watermark_path=img_path, position=loc,
opacity=opacity,
scale=size,
gpu=gpu)).start()
#SuperimposeWatermarkPopUp()
[docs]class SuperimposeTimerPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="SUPER-IMPOSE TIME ON VIDEOS", icon='superimpose')
self.LOCATIONS = {'TOP LEFT': 'top_left', 'TOP RIGHT': 'top_right', 'TOP MIDDLE': 'top_middle', 'BOTTOM LEFT': 'bottom_left', 'BOTTOM RIGHT': 'bottom_right', 'BOTTOM MIDDLE': 'bottom_middle'}
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.color_dict = get_color_dict()
self.font_dict = get_fonts()
gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.location_dropdown = SimBADropDown(parent=settings_frm, label="TIMER LOCATION:", dropdown_options=list(self.LOCATIONS.keys()), label_width=30, dropdown_width=35, value='TOP LEFT', img='location')
self.font_dropdown = SimBADropDown(parent=settings_frm, label="TIMER FONT:", dropdown_options=list(self.font_dict.keys()), label_width=30, dropdown_width=35, value='Arial', img='font')
self.font_size_dropdown = SimBADropDown(parent=settings_frm, label="FONT SIZE:", dropdown_options=list(range(20, 100, 5)), label_width=30, dropdown_width=35, value=20, img='font_size')
self.font_color_dropdown = SimBADropDown(parent=settings_frm, label="FONT COLOR:", dropdown_options=list(self.color_dict.keys()), label_width=30, dropdown_width=35, value='White', img='font_size')
self.font_border_dropdown = SimBADropDown(parent=settings_frm, label="FONT BORDER COLOR:", dropdown_options=list(self.color_dict.keys()), label_width=30, dropdown_width=35, value='Black', img='text_color')
self.font_border_width_dropdown = SimBADropDown(parent=settings_frm, label="FONT BORDER WIDTH:", dropdown_options=list(range(2, 52, 2)), label_width=30, dropdown_width=35, value=2, img='text_black')
self.timer_format_dropdown = SimBADropDown(parent=settings_frm, label="TIME FORMAT:", dropdown_options=['MM:SS', 'HH:MM:SS', 'SS.MMMMMM', 'HH:MM:SS.MMMM'], label_width=30, dropdown_width=35, value='HH:MM:SS.MMMM', img='clock')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=30, dropdown_width=35, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], label_width=30, dropdown_width=35, value='FALSE', state=gpu_available, img='gpu_3', tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.location_dropdown.grid(row=0, column=0, sticky=NW)
self.font_dropdown.grid(row=1, column=0, sticky=NW)
self.font_size_dropdown.grid(row=2, column=0, sticky=NW)
self.font_color_dropdown.grid(row=3, column=0, sticky=NW)
self.font_border_dropdown.grid(row=4, column=0, sticky=NW)
self.font_border_width_dropdown.grid(row=5, column=0, sticky=NW)
self.timer_format_dropdown.grid(row=6, column=0, sticky=NW)
self.quality_dropdown.grid(row=7, column=0, sticky=NW)
self.gpu_dropdown.grid(row=8, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - SUPERIMPOSE TIMER", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - SUPERIMPOSE TIMER", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
gpu = str_2_bool(self.gpu_dropdown.get_value())
loc = self.location_dropdown.get_value()
loc = self.LOCATIONS[loc]
font_size = int(self.font_size_dropdown.get_value())
font = self.font_dropdown.get_value()
font_clr = self.font_color_dropdown.get_value()
font_border_clr = self.font_border_dropdown.get_value()
font_border_width = int(self.font_border_width_dropdown.get_value())
timer_format = self.timer_format_dropdown.get_value()
quality_pct = int(self.quality_dropdown.get_value())
quality_crf = quality_pct_to_crf(pct=quality_pct)
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=superimpose_elapsed_time(video_path=data_path,
font=font,
font_size=font_size,
font_color=font_clr,
font_border_color=font_border_clr,
font_border_width=font_border_width,
time_format=timer_format,
position=loc,
quality=quality_crf,
gpu=gpu)).start()
[docs]class SuperimposeProgressBarPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="SUPER-IMPOSE PROGRESS BAR ON VIDEOS", icon='superimpose')
self.LOCATIONS = {'TOP': 'top', 'BOTTOM': 'bottom'}
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.color_dict = get_color_dict()
size_lst = list(range(0, 110, 5))
size_lst[0] = 1
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.bar_loc_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.LOCATIONS.keys()), label_width=25, value='BOTTOM', label="PROGRESS BAR LOCATION:", img='location', tooltip_key='PROGRESS_BAR_LOCATION')
self.bar_color_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.color_dict.keys()), label_width=25, value='Red', label="PROGRESS BAR COLOR:", img='color_wheel', tooltip_key='PROGRESS_BAR_COLOR')
self.bar_size_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=size_lst, label_width=25, value=10, label="PROGRESS BAR HEIGHT (%):", img='height', tooltip_key='PROGRESS_BAR_HEIGHT')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label_width=25, value='FALSE', label="USE GPU:", img='gpu_3', state=self.gpu_available, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.bar_loc_dropdown.grid(row=0, column=0, sticky=NW)
self.bar_color_dropdown.grid(row=1, column=0, sticky=NW)
self.bar_size_dropdown.grid(row=2, column=0, sticky=NW)
self.gpu_dropdown.grid(row=3, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - SUPERIMPOSE PROGRESS BAR", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - SUPERIMPOSE PROGRESS BAR", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
gpu = str_2_bool(self.gpu_dropdown.get_value())
loc = self.bar_loc_dropdown.get_value()
loc = self.LOCATIONS[loc]
bar_clr = self.bar_color_dropdown.get_value()
bar_size = int(self.bar_size_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=superimpose_video_progressbar(video_path=data_path,
bar_height=bar_size,
color=bar_clr,
position=loc,
gpu=gpu)).start()
#SuperimposeProgressBarPopUp()
[docs]class SuperimposeVideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="SUPER-IMPOSE VIDEO ON VIDEO", icon='superimpose')
self.LOCATIONS = {'TOP LEFT': 'top_left', 'TOP RIGHT': 'top_right', 'BOTTOM LEFT': 'bottom_left', 'BOTTOM RIGHT': 'bottom_right', 'CENTER': 'center'}
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
opacities = [round(x, 1) for x in list(np.arange(0.1, 1.1, 0.1))]
scales = [round(x, 2) for x in list(np.arange(0.05, 1.0, 0.05))]
self.main_video_path = FileSelect(settings_frm, "MAIN VIDEO PATH:", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_OPTIONS.value)], lblwidth=25, lbl_icon='video_2', tooltip_key='SUPERIMPOSE_VIDEO_MAIN_VIDEO_PATH')
self.overlay_video_path = FileSelect(settings_frm, "OVERLAY VIDEO PATH:", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_OPTIONS.value)], lblwidth=25, lbl_icon='video_2', tooltip_key='SUPERIMPOSE_VIDEO_OVERLAY_VIDEO_PATH')
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.location_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.LOCATIONS.keys()), label="OVERLAY VIDEO LOCATION:", label_width=25, dropdown_width=30, value='TOP LEFT', img='location', tooltip_key='SUPERIMPOSE_VIDEO_OVERLAY_LOCATION')
self.opacity_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=opacities, label="OVERLAY VIDEO OPACITY:", label_width=25, dropdown_width=30, value=0.5, img='opacity', tooltip_key='SUPERIMPOSE_VIDEO_OVERLAY_OPACITY')
self.size_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=scales, label="OVERLAY VIDEO SCALE (%):", label_width=25, dropdown_width=30, value=0.05, img='size_black', tooltip_key='SUPERIMPOSE_VIDEO_OVERLAY_SCALE')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU:", label_width=25, dropdown_width=30, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.main_video_path.grid(row=0, column=0, sticky=NW)
self.overlay_video_path.grid(row=1, column=0, sticky=NW)
self.location_dropdown.grid(row=2, column=0, sticky=NW)
self.opacity_dropdown.grid(row=3, column=0, sticky=NW)
self.size_dropdown.grid(row=4, column=0, sticky=NW)
self.gpu_dropdown.grid(row=5, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
#self.main_frm.mainloop()
[docs] def run(self):
loc = self.location_dropdown.get_value()
loc = self.LOCATIONS[loc]
gpu = str_2_bool(self.gpu_dropdown.get_value())
opacity = float(self.opacity_dropdown.get_value())
size = float(self.size_dropdown.get_value())
video_path = self.main_video_path.file_path
overlay_path = self.overlay_video_path.file_path
check_file_exist_and_readable(file_path=video_path)
check_file_exist_and_readable(file_path=overlay_path)
threading.Thread(target=superimpose_overlay_video(video_path=video_path,
overlay_video_path=overlay_path,
position=loc,
opacity=opacity,
scale=size,
gpu=gpu)).start()
[docs]class SuperimposeVideoNamesPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="SUPER-IMPOSE VIDEO NAMES ON VIDEOS", icon='superimpose')
self.LOCATIONS = {'TOP LEFT': 'top_left', 'TOP RIGHT': 'top_right', 'TOP MIDDLE': 'top_middle', 'BOTTOM LEFT': 'bottom_left', 'BOTTOM RIGHT': 'bottom_right', 'BOTTOM MIDDLE': 'bottom_middle'}
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.color_dict = get_color_dict()
self.font_dict = get_fonts()
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.location_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.LOCATIONS.keys()), label_width=25, value='TOP LEFT', label="VIDEO NAME TEXT LOCATION:", img='location', tooltip_key='SUPERIMPOSE_VIDEO_NAME_TEXT_LOCATION')
self.font_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.font_dict.keys()), label_width=25, value='Arial', label="FONT:", img='font', tooltip_key='SUPERIMPOSE_VIDEO_NAME_FONT')
self.font_size_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(5, 105, 5)), label_width=25, value=20, label="FONT SIZE:", img='font_size', tooltip_key='SUPERIMPOSE_VIDEO_NAME_FONT_SIZE')
self.font_color_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.color_dict.keys()), label_width=25, value='White', label="FONT COLOR:", img='color_wheel', tooltip_key='SUPERIMPOSE_VIDEO_NAME_FONT_COLOR')
self.font_border_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.color_dict.keys()), label_width=25, value='Black', label="FONT BORDER COLOR:", img='text', tooltip_key='SUPERIMPOSE_VIDEO_NAME_FONT_BORDER_COLOR')
self.font_border_width_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(2, 52, 2)), label_width=25, value=2, label="FONT BORDER WIDTH:", img='width', tooltip_key='SUPERIMPOSE_VIDEO_NAME_FONT_BORDER_WIDTH')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY: ", label_width=25, dropdown_width=30, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label_width=25, value='FALSE', label="USE GPU:", img='gpu_3', state=self.gpu_available, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.location_dropdown.grid(row=0, column=0, sticky=NW)
self.font_dropdown.grid(row=1, column=0, sticky=NW)
self.font_size_dropdown.grid(row=2, column=0, sticky=NW)
self.font_color_dropdown.grid(row=3, column=0, sticky=NW)
self.font_border_dropdown.grid(row=4, column=0, sticky=NW)
self.font_border_width_dropdown.grid(row=5, column=0, sticky=NW)
self.quality_dropdown.grid(row=6, column=0, sticky=NW)
self.gpu_dropdown.grid(row=7, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - SUPERIMPOSE VIDEO NAME", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - SUPERIMPOSE VIDEO NAME", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
loc = self.location_dropdown.get_value()
loc = self.LOCATIONS[loc]
gpu = str_2_bool(self.gpu_dropdown.get_value())
font_size = int(self.font_size_dropdown.get_value())
font = self.font_dropdown.get_value()
font_clr = self.font_color_dropdown.get_value()
font_border_clr = self.font_border_dropdown.get_value()
font_border_width = int(self.font_border_width_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
quality = int(self.quality_dropdown.get_value())
threading.Thread(target=superimpose_video_names(video_path=data_path,
font=font,
font_size=font_size,
font_color=font_clr,
font_border_color=font_border_clr,
font_border_width=font_border_width,
position=loc,
quality=quality,
gpu=gpu)).start()
#SuperimposeVideoNamesPopUp()
[docs]class SuperimposeTextPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="SUPER-IMPOSE TEXT ON VIDEOS", icon='superimpose')
self.LOCATIONS = {'TOP LEFT': 'top_left', 'TOP RIGHT': 'top_right', 'TOP MIDDLE': 'top_middle', 'BOTTOM LEFT': 'bottom_left', 'BOTTOM RIGHT': 'bottom_right', 'BOTTOM MIDDLE': 'bottom_middle'}
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.color_dict = get_color_dict()
self.font_dict = get_fonts()
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.location_dropdown = SimBADropDown(parent=settings_frm, label="TEXT LOCATION:", dropdown_options=list(self.LOCATIONS.keys()), label_width=25, value='TOP LEFT', img='location', tooltip_key='SUPERIMPOSE_TEXT_LOCATION')
self.text_eb = Entry_Box(parent=settings_frm, labelwidth=25, entry_box_width=50, fileDescription='TEXT:', img='text', tooltip_key='SUPERIMPOSE_TEXT_VALUE')
self.font_dropdown = SimBADropDown(parent=settings_frm, label="FONT:", dropdown_options=list(self.font_dict.keys()), label_width=25, value='Arial', img='font', tooltip_key='SUPERIMPOSE_TEXT_FONT')
self.font_size_dropdown = SimBADropDown(parent=settings_frm, label="FONT SIZE:", dropdown_options=list(range(5, 105, 5)), label_width=25, value=20, img='font_size', tooltip_key='SUPERIMPOSE_TEXT_FONT_SIZE')
self.font_color_dropdown = SimBADropDown(parent=settings_frm, label="FONT COLOR:", dropdown_options=list(self.color_dict.keys()), label_width=25, value='White', img='text_color', tooltip_key='SUPERIMPOSE_TEXT_FONT_COLOR')
self.font_border_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.color_dict.keys()), label_width=25, value='Black', label="FONT BORDER COLOR:", img='line', tooltip_key='SUPERIMPOSE_TEXT_FONT_BORDER_COLOR')
self.font_border_width_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(2, 52, 2)), label_width=25, value=2, label="FONT BORDER WIDTH:", img='width', tooltip_key='SUPERIMPOSE_TEXT_FONT_BORDER_WIDTH')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY: ", label_width=25, dropdown_width=30, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label_width=25, value='FALSE', label="USE GPU:", img='gpu_3', state=self.gpu_available, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.location_dropdown.grid(row=0, column=0, sticky=NW)
self.text_eb.grid(row=1, column=0, sticky=NW)
self.font_dropdown.grid(row=2, column=0, sticky=NW)
self.font_size_dropdown.grid(row=3, column=0, sticky=NW)
self.font_color_dropdown.grid(row=4, column=0, sticky=NW)
self.font_border_dropdown.grid(row=5, column=0, sticky=NW)
self.font_border_width_dropdown.grid(row=6, column=0, sticky=NW)
self.quality_dropdown.grid(row=7, column=0, sticky=NW)
self.gpu_dropdown.grid(row=8, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - SUPERIMPOSE TEXT", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - SUPERIMPOSE TEXT", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
loc = self.location_dropdown.get_value()
loc = self.LOCATIONS[loc]
text = self.text_eb.entry_get
gpu = str_2_bool(self.gpu_dropdown.get_value())
check_str(name='text', value=text)
font = self.font_dropdown.get_value()
font_size = int(self.font_size_dropdown.get_value())
font_clr = self.font_color_dropdown.get_value()
font_border_clr = self.font_border_dropdown.get_value()
font_border_width = int(self.font_border_width_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
quality = int(self.quality_dropdown.get_value())
threading.Thread(target=superimpose_freetext(video_path=data_path,
text=text,
font=font,
font_size=font_size,
font_color=font_clr,
font_border_color=font_border_clr,
font_border_width=font_border_width,
position=loc,
quality=quality,
gpu=gpu)).start()
#SuperimposeTextPopUp()
[docs]class BoxBlurPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="BOX BLUR VIDEOS", icon='smooth')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
blur_lvl = [round(x, 2) for x in list(np.arange(0.05, 1.0, 0.05))]
self.blur_lvl_dropdown = SimBADropDown(parent=settings_frm, label="BLUR LEVEL:", dropdown_options=blur_lvl, label_width=25, dropdown_width=30, value=0.02, img='smooth', tooltip_key='BOX_BLUR_BLUR_LEVEL')
self.invert_dropdown = SimBADropDown(parent=settings_frm, label="INVERT BLUR REGION:", dropdown_options=['TRUE', 'FALSE'], label_width=25, dropdown_width=30, value='FALSE', img='invert', tooltip_key='BOX_BLUR_INVERT_REGION')
settings_frm.grid(row=0, column=0, sticky=NW)
self.blur_lvl_dropdown.grid(row=0, column=0, sticky=NW)
self.invert_dropdown.grid(row=1, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="APPLY BOX-BLUR", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file', tooltip_key='BOX_BLUR_VIDEO_PATH')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run())
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self):
video_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=video_path)
blur_lvl = float(self.blur_lvl_dropdown.get_value())
invert = str_2_bool(self.invert_dropdown.get_value())
threading.Thread(target=roi_blurbox(video_path=video_path, blur_level=blur_lvl, invert=invert)).start()
[docs]class BackgroundRemoverSingleVideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="REMOVE BACKGROUND IN A VIDEO", icon='black_and_white')
self.clr_dict = get_color_dict()
self.foreground_clr_options = list(self.clr_dict.keys())
self.foreground_clr_options.append('Original')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.video_path = FileSelect(settings_frm, "VIDEO PATH:", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_OPTIONS.value)], lblwidth=45, lbl_icon='video_2', tooltip_key='BG_REMOVE_VIDEO_PATH')
self.bg_video_path = FileSelect(settings_frm, "BACKGROUND REFERENCE VIDEO PATH (OPTIONAL):", title="Select a video file", file_types=[("VIDEO", Options.ALL_VIDEO_FORMAT_OPTIONS.value)], lblwidth=45, lbl_icon='video_2', tooltip_key='BG_REMOVE_BG_REFERENCE_VIDEO_PATH')
self.bg_clr_dropdown = SimBADropDown(parent=settings_frm, label="BACKGROUND COLOR:", dropdown_options=list(self.clr_dict.keys()), label_width=45, value='White', img='fill', tooltip_key='BG_REMOVE_BACKGROUND_COLOR')
self.fg_clr_dropdown = SimBADropDown(parent=settings_frm, label="FOREGROUND COLOR:", dropdown_options=self.foreground_clr_options, label_width=45, value='Original', img='mouse_head', tooltip_key='BG_REMOVE_FOREGROUND_COLOR')
self.bg_threshold_dropdown = SimBADropDown(parent=settings_frm, label="BACKGROUND THRESHOLD:", dropdown_options=list(range(1, 100)), label_width=45, value=30, img='threshold', tooltip_key='BG_REMOVE_BACKGROUND_THRESHOLD')
self.bg_start_eb = Entry_Box(parent=settings_frm, labelwidth=45, entry_box_width=15, fileDescription='BACKGROUND VIDEO START (FRAME # OR TIME):', img='play', value='00:00:00', status=DISABLED, tooltip_key='BG_REMOVE_BG_START')
self.bg_end_eb = Entry_Box(parent=settings_frm, labelwidth=45, entry_box_width=15, fileDescription='BACKGROUND VIDEO END (FRAME # OR TIME):', img='stop', value='00:00:20', status=DISABLED, tooltip_key='BG_REMOVE_BG_END')
self.multiprocess_dropdown = SimBADropDown(parent=settings_frm, label="CPU CORE COUNT:", dropdown_options=list(range(1, find_core_cnt()[0]+1)), label_width=45, value=int(find_core_cnt()[0]/2), img='cpu_small', tooltip_key='BG_REMOVE_CPU_CORE_COUNT')
self.entire_video_as_bg_cb, self.entire_video_as_bg_var = SimbaCheckbox(parent=settings_frm, txt="COMPUTE BACKGROUND FROM ENTIRE VIDEO", font=Formats.FONT_REGULAR.value, val=True, cmd=lambda: self.enable_entrybox_from_checkbox(check_box_var=self.entire_video_as_bg_var, entry_boxes=[self.bg_start_eb, self.bg_end_eb], reverse=True), tooltip_key='BG_REMOVE_ENTIRE_VIDEO_AS_BG')
settings_frm.grid(row=0, column=0, sticky=NW)
self.video_path.grid(row=0, column=0, sticky=NW)
self.bg_video_path.grid(row=1, column=0, sticky=NW)
self.bg_clr_dropdown.grid(row=2, column=0, sticky=NW)
self.fg_clr_dropdown.grid(row=3, column=0, sticky=NW)
self.bg_threshold_dropdown.grid(row=4, column=0, sticky=NW)
self.multiprocess_dropdown.grid(row=5, column=0, sticky=NW)
self.entire_video_as_bg_cb.grid(row=6, column=0, sticky=NW)
self.bg_start_eb.grid(row=7, column=0, sticky=NW)
self.bg_end_eb.grid(row=8, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
video_path = self.video_path.file_path
video_meta_data = get_video_meta_data(video_path=video_path)
bg_video = self.bg_video_path.file_path
bg_threshold = int(self.bg_threshold_dropdown.getChoices())
bg_threshold = int((bg_threshold/100) * 255)
bg_clr = self.colors_dict[self.bg_clr_dropdown.getChoices()]
fg_clr = self.fg_clr_dropdown.getChoices()
core_cnt = int(self.multiprocess_dropdown.get_value())
if fg_clr != 'Original':
fg_clr = self.colors_dict[self.fg_clr_dropdown.getChoices()]
else:
fg_clr = None
if bg_clr == fg_clr:
raise DuplicationError(msg=f'The background and foreground color cannot be the same color ({fg_clr})', source=self.__class__.__name__)
if not os.path.isfile(bg_video):
bg_video = deepcopy(video_path)
else:
_ = get_video_meta_data(video_path=bg_video)
if not self.entire_video_as_bg_var.get():
start, end = self.bg_start_eb.entry_get.strip(), self.bg_end_eb.entry_get.strip()
int_start, _ = check_int(name='', value=start, min_value=0, raise_error=False)
int_end, _ = check_int(name='', value=end, min_value=0, raise_error=False)
if int_start and int_end:
bg_start_time, bg_end_time = None, None
bg_start_frm, bg_end_frm = int(int_start), int(int_end)
if bg_start_frm >= bg_end_frm:
raise InvalidInputError(msg=f'Start frame has to be before end frame (start: {bg_start_frm}, end: {bg_end_frm})', source=self.__class__.__name__)
else:
check_if_string_value_is_valid_video_timestamp(value=start, name='START FRAME')
check_if_string_value_is_valid_video_timestamp(value=end, name='END FRAME')
check_that_hhmmss_start_is_before_end(start_time=start, end_time=end, name='START AND END TIME')
bg_start_frm, bg_end_frm = None, None
bg_start_time, bg_end_time = start, end
else:
bg_video_meta_data = get_video_meta_data(video_path=bg_video)
bg_start_frm, bg_end_frm = 0, bg_video_meta_data['frame_count']
bg_start_time, bg_end_time = None, None
stdout_information(msg=f'Running background subtraction for video {video_meta_data["video_name"]}...', source=self.__class__.__name__)
if core_cnt == 1:
video_bg_subtraction(video_path=video_path,
bg_video_path=bg_video,
bg_start_frm=bg_start_frm,
bg_end_frm=bg_end_frm,
bg_start_time=bg_start_time,
bg_end_time=bg_end_time,
bg_color=bg_clr,
fg_color=fg_clr,
threshold=bg_threshold)
else:
core_cnt = int(self.multiprocess_dropdown.getChoices())
video_bg_subtraction_mp(video_path=video_path,
bg_video_path=bg_video,
bg_start_frm=bg_start_frm,
bg_end_frm=bg_end_frm,
bg_start_time=bg_start_time,
bg_end_time=bg_end_time,
bg_color=bg_clr,
fg_color=fg_clr,
core_cnt=core_cnt,
threshold=bg_threshold)
#BackgroundRemoverSingleVideoPopUp()
[docs]class BackgroundRemoverDirectoryPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="REMOVE BACKGROUNDS IN MULTIPLE VIDEOS", icon='black_and_white')
self.clr_dict = get_color_dict()
self.foreground_clr_options = list(self.clr_dict.keys())
self.foreground_clr_options.append('Original')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.dir_path = FolderSelect(settings_frm, "VIDEO DIRECTORY:", lblwidth=45, lbl_icon='video_2')
self.bg_dir_path = FolderSelect(settings_frm, "BACKGROUND VIDEO DIRECTORY (OPTIONAL):", lblwidth=45, lbl_icon='video_2')
self.bg_clr_dropdown = SimBADropDown(parent=settings_frm, label="BACKGROUND COLOR:", dropdown_options=list(self.clr_dict.keys()), label_width=45, value='White', img='fill')
self.fg_clr_dropdown = SimBADropDown(parent=settings_frm, label="FOREGROUND COLOR:", dropdown_options=self.foreground_clr_options, label_width=45, value='Original', img='mouse_head')
self.bg_threshold_dropdown = SimBADropDown(parent=settings_frm, label="BACKGROUND THRESHOLD:", dropdown_options=list(range(1, 100)), label_width=45, value=30, img='threshold')
self.bg_start_eb = Entry_Box(parent=settings_frm, labelwidth=45, entry_box_width=15, fileDescription='BACKGROUND VIDEO START (FRAME # OR TIME):', img='play', status=DISABLED, value='00:00:00')
self.bg_end_eb = Entry_Box(parent=settings_frm, labelwidth=45, entry_box_width=15, fileDescription='BACKGROUND VIDEO END (FRAME # OR TIME):', img='stop', status=DISABLED, value='00:00:20')
self.multiprocess_dropdown = SimBADropDown(parent=settings_frm, label="CPU CORE COUNT:", dropdown_options=list(range(1, find_core_cnt()[0]+1)), label_width=45, value=int(find_core_cnt()[0]/2), img='cpu_small')
self.entire_video_as_bg_cb, self.entire_video_as_bg_var = SimbaCheckbox(parent=settings_frm, txt="COMPUTE BACKGROUND FROM ENTIRE VIDEO", font=Formats.FONT_REGULAR.value, val=True, cmd=lambda: self.enable_entrybox_from_checkbox(check_box_var=self.entire_video_as_bg_var, entry_boxes=[self.bg_start_eb, self.bg_end_eb], reverse=True))
settings_frm.grid(row=0, column=0, sticky=NW)
self.dir_path.grid(row=0, column=0, sticky=NW)
self.bg_dir_path.grid(row=1, column=0, sticky=NW)
self.bg_clr_dropdown.grid(row=2, column=0, sticky=NW)
self.fg_clr_dropdown.grid(row=3, column=0, sticky=NW)
self.bg_threshold_dropdown.grid(row=4, column=0, sticky=NW)
self.entire_video_as_bg_cb.grid(row=5, column=0, sticky=NW)
self.bg_start_eb.grid(row=6, column=0, sticky=NW)
self.bg_end_eb.grid(row=7, column=0, sticky=NW)
self.multiprocess_dropdown.grid(row=9, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
#self.main_frm.mainloop()
[docs] def run(self):
videos_directory_path = self.dir_path.folder_path
bg_videos_directory_path = self.bg_dir_path.folder_path
bg_threshold = int(self.bg_threshold_dropdown.getChoices())
bg_threshold = int((bg_threshold/100) * 255)
check_if_dir_exists(in_dir=videos_directory_path)
bg_clr = self.colors_dict[self.bg_clr_dropdown.getChoices()]
fg_clr = self.fg_clr_dropdown.getChoices()
if fg_clr != 'Original':
fg_clr = self.colors_dict[self.fg_clr_dropdown.getChoices()]
else:
fg_clr = None
if bg_clr == fg_clr:
raise DuplicationError(msg=f'The background and foreground color cannot be the same color ({fg_clr})', source=self.__class__.__name__)
video_paths = find_all_videos_in_directory(directory=videos_directory_path, as_dict=True, raise_error=True)
if os.path.isdir(bg_videos_directory_path):
bg_video_paths = find_all_videos_in_directory(directory=bg_videos_directory_path, as_dict=True, raise_error=True)
video_paths_names, bg_video_paths_names = list(video_paths.keys()), list(bg_video_paths.keys())
missing_bg_videos = [x for x in video_paths_names if x not in bg_video_paths_names]
if len(missing_bg_videos) > 0:
raise NoDataError(msg=f'Not all videos in {videos_directory_path} directory are represented in the {bg_videos_directory_path} directory', source=self.__class__.__name__)
else:
bg_video_paths = deepcopy(video_paths)
if not self.entire_video_as_bg_var.get():
start, end = self.bg_start_eb.entry_get.strip(), self.bg_end_eb.entry_get.strip()
int_start, _ = check_int(name='', value=start, min_value=0, raise_error=False)
int_end, _ = check_int(name='', value=end, min_value=0, raise_error=False)
if int_start and int_end:
bg_start_time, bg_end_time = None, None
bg_start_frm, bg_end_frm = int(int_start), int(int_end)
if bg_start_frm >= bg_end_frm:
raise InvalidInputError(msg=f'Start frame has to be before end frame (start: {bg_start_frm}, end: {bg_end_frm})', source=self.__class__.__name__)
else:
check_if_string_value_is_valid_video_timestamp(value=start, name='START FRAME')
check_if_string_value_is_valid_video_timestamp(value=end, name='END FRAME')
check_that_hhmmss_start_is_before_end(start_time=start, end_time=end, name='START AND END TIME')
bg_start_frm, bg_end_frm = None, None
bg_start_time, bg_end_time = start, end
for cnt, (video_name, video_path) in enumerate(video_paths.items()):
print(f'Running background subtraction for video {video_name}... (Video {cnt+1}/{len(list(video_paths.keys()))})')
bg_video_path = bg_video_paths[video_name]
core_cnt = int(self.multiprocess_dropdown.get_value())
if self.entire_video_as_bg_var.get():
bg_video_meta_data = get_video_meta_data(video_path=bg_video_path)
bg_start_frm, bg_end_frm = 0, bg_video_meta_data['frame_count']
bg_start_time, bg_end_time = None, None
if core_cnt == 1:
video_bg_subtraction(video_path=video_path,
bg_video_path=bg_video_path,
bg_start_frm=bg_start_frm,
bg_end_frm=bg_end_frm,
bg_start_time=bg_start_time,
bg_end_time=bg_end_time,
bg_color=bg_clr,
fg_color=fg_clr,
threshold=bg_threshold)
else:
core_cnt = int(self.multiprocess_dropdown.getChoices())
video_bg_subtraction_mp(video_path=video_path,
bg_video_path=bg_video_path,
bg_start_frm=bg_start_frm,
bg_end_frm=bg_end_frm,
bg_start_time=bg_start_time,
bg_end_time=bg_end_time,
bg_color=bg_clr,
fg_color=fg_clr,
core_cnt=core_cnt,
threshold=bg_threshold)
#BackgroundRemoverDirectoryPopUp()
[docs]class RotateVideoSetDegreesPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="INTERACTIVELY ROTATE VIDEOS", icon='rotate')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.degrees_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, 360, 1)), label="CLOCKWISE DEGREES:", label_width=25, dropdown_width=25, value=90, img='rotate', tooltip_key='ROTATE_VIDEO_DEGREES')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=25, dropdown_width=25, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU:", label_width=25, dropdown_width=25, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky="NW")
self.degrees_dropdown.grid(row=0, column=0, sticky="NW")
self.quality_dropdown.grid(row=1, column=0, sticky="NW")
self.gpu_dropdown.grid(row=2, column=0, sticky="NW")
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - ROTATE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - ROTATE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
[docs] def run(self, multiple: bool):
degrees = int(self.degrees_dropdown.get_value())
quality = int(self.quality_dropdown.get_value())
gpu = str_2_bool(self.gpu_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=rotate_video(video_path=data_path,
degrees=degrees,
quality=quality,
gpu=gpu)).start()
[docs]class FlipVideosPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="FLIP VIDEOS", icon='flip_green')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.horizontal_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="HORIZONTAL FLIP:", label_width=25, dropdown_width=25, value='FALSE', img='flip_green', tooltip_key='HORIZONTAL_FLIP')
self.vertical_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="VERTICAL FLIP:", label_width=25, dropdown_width=25, value='FALSE', img='flip_green', tooltip_key='VERTICAL_FLIP')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=25, dropdown_width=25, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU:", label_width=25, dropdown_width=25, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky="NW")
self.vertical_dropdown.grid(row=0, column=0, sticky="NW")
self.horizontal_dropdown.grid(row=1, column=0, sticky="NW")
self.quality_dropdown.grid(row=2, column=0, sticky="NW")
self.gpu_dropdown.grid(row=3, column=0, sticky="NW")
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - FLIP", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='video_2')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - FLIP", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
[docs] def run(self, multiple: bool):
vertical_flip = str_2_bool(self.vertical_dropdown.get_value())
horizontal_flip = str_2_bool(self.horizontal_dropdown.get_value())
gpu = str_2_bool(self.gpu_dropdown.get_value())
if not vertical_flip and not horizontal_flip:
raise InvalidInputError(msg='Flip videos vertically and/or horizontally. Got both as False', source=self.__class__.__name__)
quality = int(self.quality_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=flip_videos(video_path=data_path,
vertical_flip=vertical_flip,
horizontal_flip=horizontal_flip,
quality=quality,
gpu=gpu)).start()
[docs]class UpsampleVideosPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="UPSAMPLE VIDEOS USING INTERPOLATION (WARNING: LONG RUN-TIMES)", icon='sample')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.fps_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(1, 500)), label="NEW FRAME-RATE (FPS):", label_width=25, dropdown_width=25, value=60, img='fps')
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY (%):", label_width=25, dropdown_width=25, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
settings_frm.grid(row=0, column=0, sticky="NW")
self.fps_dropdown.grid(row=0, column=0, sticky="NW")
self.quality_dropdown.grid(row=1, column=0, sticky="NW")
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - UP-SAMPLE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)])
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - UP-SAMPLE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25)
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
target_fps = int(self.fps_dropdown.get_value())
target_quality = int(self.quality_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=upsample_fps(video_path=data_path,
fps=target_fps,
quality=target_quality)).start()
[docs]class ReverseVideoPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="REVERSE VIDEOS", icon='reverse_blue')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.MP4_CODEC_LK = {'HEVC (H.265)': 'libx265', 'H.264 (AVC)': 'libx264', 'VP9': 'vp9'}
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.quality_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(range(10, 110, 10)), label="OUTPUT VIDEO QUALITY:", label_width=25, dropdown_width=25, value=60, img='pct_2', tooltip_key='OUTPUT_VIDEO_QUALITY')
self.codec_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=list(self.MP4_CODEC_LK.keys()), label="COMPRESSION CODEC:", label_width=25, dropdown_width=25, value='HEVC (H.265)', img='file_type')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU:", label_width=25, dropdown_width=25, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.quality_dropdown.grid(row=0, column=0, sticky=NW)
self.codec_dropdown.grid(row=1, column=0, sticky=NW)
self.gpu_dropdown.grid(row=2, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - REVERSE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)])
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - REVERSE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25)
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
target_quality = int(self.quality_dropdown.get_value())
codec = self.MP4_CODEC_LK[self.codec_dropdown.get_value()]
gpu = str_2_bool(self.gpu_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
reverse_videos(path=data_path,
quality=target_quality,
codec=codec,
gpu=gpu)
[docs]class Convert2BlackWhitePopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CONVERT VIDEOS TO BLACK AND WHITE (NOTE: NOT GRAYSCALE)", icon='black_and_white')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
threshold = [round(x, 2) for x in list(np.arange(0.01, 1.01, 0.01))]
gpu_state = NORMAL if check_nvidea_gpu_available(raise_error=False) else DISABLED
self.threshold_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=threshold, label="BLACK THRESHOLD:", label_width=25, dropdown_width=25, value=0.5, img='threshold', tooltip_key='CONVERT2BW_THRESHOLD')
self.gpu_dropdown = SimBADropDown(parent=settings_frm, dropdown_options=['TRUE', 'FALSE'], label="USE GPU:", label_width=25, dropdown_width=25, value='FALSE', img='gpu_3', state=gpu_state, tooltip_key='USE_GPU')
settings_frm.grid(row=0, column=0, sticky=NW)
self.threshold_dropdown.grid(row=0, column=0, sticky=NW)
self.gpu_dropdown.grid(row=1, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - CONVERT TO BLACK & WHITE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], tooltip_key='CONVERT2BW_VIDEO_PATH')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - CONVERT TO BLACK & WHITE", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, tooltip_key='CONVERT2BW_VIDEO_DIR_PATH')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
#self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
threshold = float(self.threshold_dropdown.get_value())
gpu = str_2_bool(self.gpu_dropdown.get_value())
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
threading.Thread(target=video_to_bw(video_path=data_path,
threshold=threshold,
gpu=gpu)).start()
[docs]class CreateAverageFramePopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CREATE AVERAGE VIDEO FRAME", icon='average')
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.save_dir = FolderSelect(settings_frm, "AVERAGE FRAME SAVE DIRECTORY:", title="Select a video directory", lblwidth=35, lbl_icon='folder', tooltip_key='AVG_FRAME_SAVE_DIR')
self.section_start_time_eb = Entry_Box(settings_frm, fileDescription="SAMPLE START TIME:", labelwidth=35, value='00:00:00', img='play', tooltip_key='AVG_FRAME_START_TIME')
self.section_end_time_eb = Entry_Box(settings_frm, fileDescription="SAMPLE END TIME:", labelwidth=35, value='00:00:00', img='stop', tooltip_key='AVG_FRAME_END_TIME')
settings_frm.grid(row=0, column=0, sticky=NW, pady=10)
self.save_dir.grid(row=0, column=0, sticky=NW)
self.section_start_time_eb.grid(row=1, column=0, sticky=NW)
self.section_end_time_eb.grid(row=2, column=0, sticky=NW)
single_video_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="SINGLE VIDEO - CREATE AVERAGE FRAME", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video = FileSelect(single_video_frm, "VIDEO PATH:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file', tooltip_key='AVG_FRAME_VIDEO_PATH')
single_video_run = SimbaButton(parent=single_video_frm, txt="RUN - SINGLE VIDEO", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=False))
single_video_frm.grid(row=1, column=0, sticky="NW")
self.selected_video.grid(row=0, column=0, sticky="NW")
single_video_run.grid(row=1, column=0, sticky="NW")
multiple_videos_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="MULTIPLE VIDEOS - CREATE AVERAGE FRAMES", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.selected_video_dir = FolderSelect(multiple_videos_frm, "VIDEO DIRECTORY PATH:", title="Select a video directory", lblwidth=25, lbl_icon='folder', tooltip_key='AVG_FRAME_VIDEO_DIR_PATH')
multiple_videos_run = SimbaButton(parent=multiple_videos_frm, txt="RUN - MULTIPLE VIDEOS", img='rocket', txt_clr='blue', font=Formats.FONT_REGULAR.value, cmd=lambda: self.run(multiple=True))
multiple_videos_frm.grid(row=2, column=0, sticky="NW")
self.selected_video_dir.grid(row=0, column=0, sticky="NW")
multiple_videos_run.grid(row=1, column=0, sticky="NW")
self.main_frm.mainloop()
[docs] def run(self, multiple: bool):
start_time = self.section_start_time_eb.entry_get.strip()
end_time = self.section_end_time_eb.entry_get.strip()
save_dir = self.save_dir.folder_path
check_if_dir_exists(in_dir=save_dir)
if (start_time != '' and end_time == '') or (start_time == '' and end_time != ''):
raise InvalidInputError(msg=f'Both start time and end time have to be either time-stamps or blank.', source=self.__class__.__name__)
if start_time != '' and end_time != '':
check_if_string_value_is_valid_video_timestamp(value=start_time, name='start_time')
check_if_string_value_is_valid_video_timestamp(value=end_time, name='end_time')
check_that_hhmmss_start_is_before_end(start_time=start_time, end_time=end_time, name=self.__class__.__name__)
else:
start_time, end_time = None, None
if not multiple:
data_path = self.selected_video.file_path
check_file_exist_and_readable(file_path=data_path)
data_path = [data_path]
else:
data_path = self.selected_video_dir.folder_path
check_if_dir_exists(in_dir=data_path)
data_path = list(find_all_videos_in_directory(directory=data_path, as_dict=True, raise_error=True).values())
for video_cnt, video_path in enumerate(data_path):
_, video_name, _ = get_fn_ext(filepath=video_path)
save_path = os.path.join(save_dir, save_dir, f'{video_name}_avg_frm.png')
_ = get_video_meta_data(video_path=video_path)
if start_time != None and end_time != None:
check_if_hhmmss_timestamp_is_valid_part_of_video(timestamp=start_time, video_path=video_path)
check_if_hhmmss_timestamp_is_valid_part_of_video(timestamp=end_time, video_path=video_path)
threading.Thread(target=create_average_frm(video_path=video_path,
start_time=start_time,
end_time=end_time,
save_path=save_path,
verbose=True)).start()
#CreateAverageFramePopUp()
[docs]class ManualTemporalJoinPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="MANUAL TEMPORAL JOIN VIDEOS", icon='join_purple')
video_cnt_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="NUMBER OF VIDEOS TO JOIN", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.gpu_available = NORMAL if check_nvidea_gpu_available() else DISABLED
self.video_cnt_dropdown = SimBADropDown(parent=video_cnt_frm, label="NUMBER OF VIDEOS:", dropdown_options=list(range(2, 101, 1)), label_width=25, dropdown_width=30, img='abacus_2', value=2, command= lambda x: self.select(x))
self.quality_dropdown = SimBADropDown(parent=video_cnt_frm, label="OUTPUT VIDEO QUALITY %:", dropdown_options=list(range(10, 110, 10)), label_width=25, dropdown_width=30, img='pct', value=60)
self.out_format_dropdown = SimBADropDown(parent=video_cnt_frm, label="OUTPUT VIDEO FORMAT:", dropdown_options=Options.ALL_VIDEO_FORMAT_OPTIONS.value, label_width=25, dropdown_width=30, img='file_type', value='.mp4')
self.gpu_dropdown = SimBADropDown(parent=video_cnt_frm, label="USE GPU:", dropdown_options=['TRUE', 'FALSE'], label_width=25, dropdown_width=30, img='gpu_3', value='FALSE', state=self.gpu_available)
video_cnt_frm.grid(row=0, column=0, sticky=NW)
self.video_cnt_dropdown.grid(row=0, column=0, sticky=NW)
self.quality_dropdown.grid(row=1, column=0, sticky=NW)
self.out_format_dropdown.grid(row=2, column=0, sticky=NW)
self.gpu_dropdown.grid(row=3, column=0, sticky=NW)
self.select(x=2)
self.main_frm.mainloop()
[docs] def select(self, x):
video_cnt = int(self.video_cnt_dropdown.getChoices())
if hasattr(self, 'video_paths_frm'):
self.video_paths_frm.destroy()
self.run_frm.destroy()
self.video_paths_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="VIDEO PATHS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.video_paths_frm.grid(row=1, column=0, sticky=NW)
self.video_paths = {}
for video_cnt in range(video_cnt):
self.video_paths[video_cnt] = FileSelect(self.video_paths_frm, f"VIDEO PATH {video_cnt+1}:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file')
self.video_paths[video_cnt].grid(row=video_cnt, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
[docs] def run(self):
video_file_paths, meta = [], []
for cnt, video_file_select in self.video_paths.items():
video_path = video_file_select.file_path
check_file_exist_and_readable(file_path=video_path)
video_meta = get_video_meta_data(video_path=video_path)
video_file_paths.append(video_path)
meta.append(video_meta)
fps, resolutions = [v['fps'] for v in meta], [v['resolution_str'] for v in meta]
unique_fps, unique_res = list(set(fps)), list(set(resolutions))
format = self.out_format_dropdown.getChoices()
quality = self.quality_dropdown.getChoices()
gpu = str_2_bool(self.gpu_dropdown.get_value())
if len(unique_fps) > 1: raise FrameRangeError(msg=f'The selected videos contain more than one unique FPS: {unique_fps}', source=self.__class__.__name__)
if len(unique_res) > 1: raise ResolutionError(msg=f'The selected videos contain more than one unique resolutions: {unique_res}', source=self.__class__.__name__)
threading.Thread(temporal_concatenation(video_paths=video_file_paths,
save_format=format[1:],
quality=quality,
gpu=gpu)).start()
#ManualTemporalJoinPopUp()
[docs]class CrossfadeVideosPopUp(PopUpMixin):
def __init__(self):
PopUpMixin.__init__(self, title="CROSS-FADE VIDEOS", icon='crossfade')
crossfade_methods = get_ffmpeg_crossfade_methods()
settings_frm = CreateLabelFrameWithIcon(parent=self.main_frm, header="NUMBER OF VIDEOS TO JOIN", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.VIDEO_TOOLS.value)
self.video_path_1 = FileSelect(settings_frm, f"VIDEO PATH 1:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file', tooltip_key='CROSSFADE_VIDEO_PATH_1')
self.video_path_2 = FileSelect(settings_frm, f"VIDEO PATH 2:", title="Select a video file", lblwidth=25, file_types=[("VIDEO FILE", Options.ALL_VIDEO_FORMAT_STR_OPTIONS.value)], lbl_icon='file', tooltip_key='CROSSFADE_VIDEO_PATH_2')
self.quality_dropdown = SimBADropDown(parent=settings_frm, label="OUTPUT VIDEO QUALITY:", dropdown_options=list(range(10, 110, 10)), label_width=25, img='pct', dropdown_width=35, value=60, tooltip_key='OUTPUT_VIDEO_QUALITY')
self.out_format_dropdown = SimBADropDown(parent=settings_frm, label="OUTPUT VIDEO FORMAT:", dropdown_options=['mp4', 'avi', 'webm'], label_width=25, img='file_type', dropdown_width=35, value='mp4', tooltip_key='CROSSFADE_OUTPUT_FORMAT')
self.fade_method_dropdown = SimBADropDown(parent=settings_frm, label="CROSS-FADE METHOD:", dropdown_options=crossfade_methods, label_width=25, img='crossfade', dropdown_width=35, value='fade', tooltip_key='CROSSFADE_METHOD')
self.duration_dropdown = SimBADropDown(parent=settings_frm, label="CROSS-FADE DURATION:", dropdown_options=list(range(2, 22, 2)), label_width=25, img='timer', dropdown_width=35, value=6, tooltip_key='CROSSFADE_DURATION')
self.offset_eb = Entry_Box(settings_frm, fileDescription="CROSS-FADE OFFSET:", labelwidth=25, value='00:00:00', img='timer_2', entry_box_width=35, justify='center', tooltip_key='CROSSFADE_OFFSET')
settings_frm.grid(row=0, column=0, sticky=NW)
self.video_path_1.grid(row=0, column=0, sticky=NW)
self.video_path_2.grid(row=1, column=0, sticky=NW)
self.quality_dropdown.grid(row=2, column=0, sticky=NW)
self.out_format_dropdown.grid(row=3, column=0, sticky=NW)
self.fade_method_dropdown.grid(row=4, column=0, sticky=NW)
self.duration_dropdown.grid(row=5, column=0, sticky=NW)
self.offset_eb.grid(row=6, column=0, sticky=NW)
self.create_run_frm(run_function=self.run)
self.main_frm.mainloop()
[docs] def run(self):
video_1_path, video_2_path = self.video_path_1.file_path, self.video_path_2.file_path
quality = int(self.quality_dropdown.getChoices())
format = self.out_format_dropdown.getChoices()
fade_method = self.fade_method_dropdown.getChoices()
offset = self.offset_eb.entry_get
check_if_string_value_is_valid_video_timestamp(value=offset, name='offset')
duration = int(self.duration_dropdown.getChoices())
check_if_hhmmss_timestamp_is_valid_part_of_video(timestamp=offset, video_path=video_1_path)
offset = timestamp_to_seconds(timestamp=offset)
for video_path in [video_1_path, video_2_path]:
video_meta_data = get_video_meta_data(video_path=video_path)
if video_meta_data['video_length_s'] < duration:
raise FrameRangeError(msg=f'Video {video_meta_data["video_name"]} is shorter {video_meta_data["video_length_s"]} than the crossfade duration {duration}.', source=self.__class__.__name__)
if video_meta_data['video_length_s'] < offset:
raise FrameRangeError(msg=f'Video {video_meta_data["video_name"]} is shorter {video_meta_data["video_length_s"]} than the crossfade offset {offset}.',source=self.__class__.__name__)
threading.Thread(crossfade_two_videos(video_path_1=video_1_path,
video_path_2=video_2_path,
crossfade_duration=duration,
crossfade_method=fade_method,
crossfade_offset=offset,
out_format=format,
quality=quality)).start()
#CrossfadeVideosPopUp()
#_ = BrightnessContrastPopUp()
# FlipVideosPopUp()
# ClipMultipleVideosByFrameNumbers
# ClipMultipleVideosByFrameNumbers(data_dir='/Users/simon/Desktop/envs/simba/troubleshooting/beepboop174/project_folder/videos/test', save_dir='/Users/simon/Desktop/envs/simba/troubleshooting/beepboop174/project_folder/videos/clipped')