import cv2 import os import ffmpeg from tempfile import mkdtemp, NamedTemporaryFile from shutil import rmtree def convert_to_mov(input_file: str, output_file: str = None): # if there is no output file specified, create a temp file then return contents if output_file == None: tmpdir = mkdtemp() tmp = os.path.join(tmpdir, "vid.mov") convert_to_mov(input_file, tmp) with open(tmp, "rb") as tmpfile: contents = tmpfile.read() rmtree(tmpdir) return contents inp = ffmpeg.input(input_file) out = ffmpeg.output(inp, output_file, f='mov', vcodec='copy', acodec='copy') ffmpeg.run(out) def get_thumbnail_from_mov(input_file: str, output_file: str = None): # if there is no output file specified, create a temp file and then return contents if output_file == None: tmpdir = mkdtemp() tmp = os.path.join(tmpdir, "thumb.png") get_thumbnail_from_mov(input_file, tmp) with open(tmp, "rb") as tmpfile: contents = tmpfile.read() rmtree(tmpdir) return contents inp = ffmpeg.input(input_file, ss=0) out = ffmpeg.output(inp, output_file, vframes=1) ffmpeg.run(out) def get_thumbnail_from_contents(contents: bytes, output_file: str = None): with NamedTemporaryFile("rb+", suffix=".mov") as inp_file: inp_file.write(contents) contents = get_thumbnail_from_mov(inp_file.name, output_file) return contents def create_caml(video_path: str, output_file: str, auto_reverses: bool, update_label=lambda x: None): cam = cv2.VideoCapture(video_path) assets_path = os.path.join(output_file, "assets") frame_count = int(cam.get(cv2.CAP_PROP_FRAME_COUNT)) FRAME_LIMIT = 300 reverse = 0 if auto_reverses: reverse = 1 if frame_count > FRAME_LIMIT: raise Exception(f"Videos must be under {FRAME_LIMIT} fps to loop. Either reduce the frame rate or make it shorter.") try: # creating a folder named data if not os.path.exists(assets_path): os.makedirs(assets_path, exist_ok=True) # if not created then raise error except OSError: print ('Error: Creating directory of data') # frame currentframe = 0 width = int(cam.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cam.get(cv2.CAP_PROP_FRAME_HEIGHT)) with open(os.path.join(output_file, "main.caml"), "w") as caml: # write caml header fps = cam.get(cv2.CAP_PROP_FPS) duration = frame_count / fps caml.write(f""" """) # Release all space and windows once done cam.release() cv2.destroyAllWindows() # Write the other caml with open(os.path.join(output_file, "index.xml"), "w") as index: index.write(f""" assetManifest assetManifest.caml documentHeight {height} documentResizesToView documentWidth {width} dynamicGuidesEnabled geometryFlipped guidesEnabled interactiveMouseEventsEnabled interactiveShowsCursor interactiveTouchEventsEnabled loopEnd 0.0 loopStart 0.0 loopingEnabled multitouchDisablesMouse multitouchEnabled presentationMouseEventsEnabled presentationShowsCursor presentationTouchEventsEnabled rootDocument main.caml savesWindowFrame scalesToFitInPlayer showsTouches snappingEnabled timelineMarkers [(null)] touchesColor 1 1 0 0.8 unitsInPixelsInPlayer """)