def push_frames_for_copy_to_queue(self, source_video_parent_file_id, destination_video_parent_file_id): """ Give the current data at self.input, get the video frame of the existing file and push them to the ProcessMedia Queue. :return: """ source_video_frames = WorkingDirFileLink.image_file_list_from_video( session=self.session, video_parent_file_id=source_video_parent_file_id, order_by_frame=True) frame_completion_controller = FrameCompletionControl() for frame in source_video_frames: frame_completion_controller.add_pending_frame(frame.frame_number) for frame in source_video_frames: ### HOW TOD AVOID DETACHED SESSION ### Must only pass IDs and not pass any other objects # Actually the add remove link thing could be different too... # Careful the file id is the newly copied video # The previous video id should come from the NEW file id not the previous one frame_input = Input.new( parent_input_id=self.input.id, sequence_map=self.input.sequence_map, file_id=frame.id, # existing video_parent_length=len(source_video_frames), directory_id=self.input.directory_id, source_directory_id=self.input.source_directory_id, remove_link=self.input.remove_link, add_link=self.input.add_link, copy_instance_list=self.input.copy_instance_list, parent_file_id=destination_video_parent_file_id, # This is the parent video file where all data is going to be copied. project_id=self.input.project_id, mode='copy_file', type=None, media_type='frame', ) item = process_media.PrioritizedItem( input=frame_input, frame_completion_controller=frame_completion_controller, total_frames=source_video_frames[len(source_video_frames) - 1].frame_number, num_frames_to_update=len(source_video_frames), media_type=frame_input. media_type, # declaring here helps with routing priority=100 + frame.frame_number, # Process in frame priority frame_number=frame. frame_number # Careful, downstream process currently expects it ) process_media.add_item_to_queue(item) return source_video_frames
def __push_formatted_frame_to_queue(self, input: Input): item = process_media.PrioritizedItem( input=input, media_type=input.media_type, # declaring here helps with routing priority=100 + input.frame_number, # Process in frame priority frame_number=input. frame_number # Careful, downstream process currently expects it ) process_media.add_item_to_queue(item)
def add_frame_to_queue(self, frame, index: int, original_filename: str, project: Project, directory_id, video, length, video_parent_file: File, global_frame_number=None, initial_global_frame=None): """ Where frame is: a HxWxN np.array, where N=1 for mask clips and N=3 for RGB clips. https://zulko.github.io/moviepy/ref/VideoClip/VideoClip.html Careful we don't have self. context here Cautions * We purposely do not not pass the job id, since we only want to original video to be added to the job Question, is it correct we create input class in part to maintain same concepts / format even for video frames? Answer: For example see frame_end_number is used to pass information Makes more sense to have it all in there then the PrioritizedItem() thing long term Also thinking in terms of logging And yes of course, then it's complete reuse of the component Jan 20, 2020 Note we purposely do NOT commit this as it creates unneeded db overhead, so instead we only use it as a local object to maintain consistency of design which means we do NOT want to add to add it a sesion ie self.session.add(input) """ input = Input() # Use input for class attributes, # but don't add it to the session for video? # TODO use File.new() for consistency here (ie as we add new things) # Single frame naming input.original_filename = original_filename + "_" + str(index) input.extension = ".jpg" input.media_type = "frame" input.temp_dir = tempfile.mkdtemp() input.project = project input.directory_id = directory_id input.parent_file_id = video_parent_file.id input.frame_packet_map = self.input.frame_packet_map # caution length is estimated. frame_count # is calculated as we roll through this so can't use it yet # Question: clarity on difference between numbers. # (I know estimate but still.) input.video_parent_length = length input.parent_input_id = self.input.id input.project_id = self.project.id # This is a temporary usage thing only # Note database persisted # Context of needing it to be defined so existing instances # Can use it (vs having to get video from db each time, # prior we defined this on first frame. input.root_blob_path_to_frames = video.root_blob_path_to_frames input = self.get_instance_list_from_packet_map( input=input, frame_number=index, global_frame_number=global_frame_number, initial_global_frame=initial_global_frame, from_video_split=self.input.type == 'from_video_split') """ For frame priority, the original genesis was doing the last frame last but, I think it also makese sense to process in order in general. An alternative would be to say put a flag on the last frame but using order feels like a more general solution, assuming no suprises or extra overhead. Storing frames Maybe don't attach video_parent_file because it leads to not bound errors in ORM fairly easily. """ # TODO, consider sending data as a "raw" blob # to cloud storage, then setting "processing deferred" to True here. # Process frames of videos started before new videos item = process_media.PrioritizedItem( priority=100 + index, # Process in frame priority input=input, raw_numpy_image=frame, file_is_numpy_array=True, video_id=video.id, frame_number=index, global_frame_number=global_frame_number, media_type=input.media_type) process_media.add_item_to_queue(item)