import os import cv2 import shutil import math import requests from modules.shared import state def get_frame_name(path): name = os.path.basename(path) name = os.path.splitext(name)[0] return name def vid2frames(video_path, video_in_frame_path, n=1, overwrite=True, extract_from_frame=0, extract_to_frame=-1, only_get_fps=False): # n = extract_nth_frame #get the name of the video without the path and ext if (extract_to_frame <= extract_from_frame) and extract_to_frame != -1: raise RuntimeError('extract_to_frame can not be highher than extract_from_frame') name = get_frame_name(video_path) if n < 1: n = 1 #HACK Gradio interface does not currently allow min/max in gr.Number(...) if video_path.startswith('http://') or video_path.startswith('https://'): response = requests.head(video_path) if response.status_code == 404 or response.status_code != 200: raise ConnectionError("Init video url or mask video url is not valid") else: if not os.path.exists(video_path): raise RuntimeError("Init video path or mask video path is not valid") vidcap = cv2.VideoCapture(video_path) video_fps = vidcap.get(cv2.CAP_PROP_FPS) if only_get_fps is False: input_content = [] if os.path.exists(video_in_frame_path) : input_content = os.listdir(video_in_frame_path) # check if existing frame is the same video, if not we need to erase it and repopulate if len(input_content) > 0: #get the name of the existing frame content_name = get_frame_name(input_content[0]) if not content_name.startswith(name): overwrite = True # grab the frame count to check against existing directory len frame_count = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT)) # raise error if the user wants to skip more frames than exist if n >= frame_count : raise RuntimeError('Skipping more frames than input video contains. extract_nth_frames larger than input frames') expected_frame_count = math.ceil(frame_count / n) # Check to see if the frame count is matches the number of files in path if overwrite or expected_frame_count != len(input_content): shutil.rmtree(video_in_frame_path) os.makedirs(video_in_frame_path, exist_ok=True) # just deleted the folder so we need to make it again input_content = os.listdir(video_in_frame_path) if len(input_content) == 0: vidcap.set(cv2.CAP_PROP_POS_FRAMES, extract_from_frame) # Set the starting frame success,image = vidcap.read() count = extract_from_frame t=1 success = True while success: if state.interrupted: return if (count <= extract_to_frame or extract_to_frame == -1) and count % n == 0: cv2.imwrite(video_in_frame_path + os.path.sep + name + f"{t:05}.jpg" , image) # save frame as JPEG file t += 1 success,image = vidcap.read() count += 1 print("Converted %d frames" % count) else: print("Frames already unpacked") vidcap.release() return video_fps def get_next_frame(outdir, video_path, frame_idx, mask=False): frame_path = 'inputframes' if (mask): frame_path = 'maskframes' return os.path.join(outdir, frame_path, get_frame_name(video_path) + f"{frame_idx+1:05}.jpg")