def capture_video(video_path, capture_path, default_path): print("\n[전환장면 캡처 시작] 영상 내 전환 시점을 기준으로 이미지 추출을 시작합니다") video_manager = VideoManager([video_path]) stats_manager = StatsManager() scene_manager = SceneManager(stats_manager) # 가장 예민하게 잡아내도록 1~100 중 1로 설정 scene_manager.add_detector(ContentDetector(threshold=1)) video_manager.set_downscale_factor() video_manager.start() scene_manager.detect_scenes(frame_source=video_manager) scene_list = scene_manager.get_scene_list() print(">>>", f'{len(scene_list)} scenes detected!') # 전환 인식이 된 장면의 수 save_images(scene_list, video_manager, num_images=1, image_name_template='$SCENE_NUMBER', output_dir=capture_path) write_scene_list_html(default_path + 'SceneDetectResult.html', scene_list) captured_timeline_list = [] # 전환된 시점을 저장할 리스트 함수 for scene in scene_list: start, end = scene # 전환 시점 저장 captured_timeline_list.append(start.get_seconds()) print("[전환장면 캡처 종료] 영상 내 전환 시점을 기준으로 이미지 추출을 종료합니다\n") return captured_timeline_list
def find_scenes(self, video_folder, threshold=50.0): video_paths = os.listdir(video_folder) # self.data.set_index("id", inplace=True) ids = self.data["id"] sep_times = {} for i, vp in enumerate(video_paths): if i % 100 == 0: self.logger.critical("Extracting scene frames, at %d/%d" % (i, len(video_paths))) id = vp.split('.')[0] # row = self.data.loc[int(id)] sep_times[id] = [] video_path = os.path.join(video_folder, vp) # Create our videos & scene managers, then add the detector. video_manager = VideoManager([video_path], logger=self.logger) scene_manager = SceneManager() scene_manager.add_detector(ContentDetector(threshold=threshold)) # Improve processing speed by downscaling before processing. # video_manager.set_downscale_factor(2) # Start the videos manager and perform the scene detection. video_manager.start() scene_manager.detect_scenes(frame_source=video_manager) scene_list = scene_manager.get_scene_list() # Each returned scene is a tuple of the (start, end) timecode. save_images(scene_list, video_manager, image_name_template='%s-Scene-$SCENE_NUMBER' % id, num_images=1, output_dir=os.path.join(config.data_folder, 'scene_cover')) for scene in scene_list: sta_sec = scene[0].get_seconds() end_sec = scene[1].get_seconds() sep_times[id].append((sta_sec, end_sec)) # print(id) # for i, scene in enumerate(scene_list): # print(' Scene %2d: Start %s / Frame %d, End %s / Frame %d' % ( # i + 1, # 1000 * scene[0].get_seconds(), scene[0].get_frames(), # 1000 * scene[1].get_seconds(), scene[1].get_frames())) # separate_texts = json.loads(row["separated_text"]) # separate_timestamps = json.loads(row["separate_timestamps"]) # for text, timestamp in zip(separate_texts, separate_timestamps): # print(text, timestamp) # print('-' * 30) video_manager.release() sep_times_list = [json.dumps(sep_times[str(id)]) for id in ids] self.data["scene_times"] = sep_times_list
def test_save_images(test_video_file): """ Test scenedetect.scene_manager.save_images function. """ vm = VideoManager([test_video_file]) sm = SceneManager() sm.add_detector(ContentDetector()) image_name_glob = 'scenedetect.tempfile.*.jpg' image_name_template = 'scenedetect.tempfile.$SCENE_NUMBER.$IMAGE_NUMBER' try: video_fps = vm.get_framerate() start_time = FrameTimecode('00:00:05', video_fps) end_time = FrameTimecode('00:00:15', video_fps) vm.set_duration(start_time=start_time, end_time=end_time) vm.set_downscale_factor() vm.start() sm.detect_scenes(frame_source=vm) scene_list = sm.get_scene_list() assert scene_list image_filenames = save_images(scene_list=scene_list, video_manager=vm, num_images=3, image_extension='jpg', image_name_template=image_name_template) # Ensure images got created, and the proper number got created. total_images = 0 for scene_number in image_filenames: for path in image_filenames[scene_number]: assert os.path.exists(path) total_images += 1 assert total_images == len(glob.glob(image_name_glob)) finally: vm.release() for path in glob.glob(image_name_glob): os.remove(path)
def process_input(self): # type: () -> None """ Process Input: Processes input video(s) and generates output as per CLI commands. Run after all command line options/sub-commands have been parsed. """ self.logger.debug('Processing input...') if not self.options_processed: self.logger.debug( 'Skipping processing, CLI options were not parsed successfully.' ) return self.check_input_open() assert self.scene_manager.get_num_detectors() >= 0 if self.scene_manager.get_num_detectors() == 0: self.logger.error( 'No scene detectors specified (detect-content, detect-threshold, etc...),\n' ' or failed to process all command line arguments.') return # Display a warning if the video codec type seems unsupported (#86). if int(abs(self.video_manager.get(cv2.CAP_PROP_FOURCC))) == 0: self.logger.error( 'Video codec detection failed, output may be incorrect.\nThis could be caused' ' by using an outdated version of OpenCV, or using codecs that currently are' ' not well supported (e.g. VP9).\n' 'As a workaround, consider re-encoding the source material before processing.\n' 'For details, see https://github.com/Breakthrough/PySceneDetect/issues/86' ) # Handle scene detection commands (detect-content, detect-threshold, etc...). self.video_manager.start() start_time = time.time() self.logger.info('Detecting scenes...') num_frames = self.scene_manager.detect_scenes( frame_source=self.video_manager, frame_skip=self.frame_skip, show_progress=not self.quiet_mode) # Handle case where video fails with multiple audio tracks (#179). # TODO: Using a different video backend as per #213 may also resolve this issue, # as well as numerous other timing related issues. if num_frames <= 0: self.logger.critical( 'Failed to read any frames from video file. This could be caused' ' by the video having multiple audio tracks. If so, please try' ' removing the audio tracks or muxing to mkv via:\n' ' ffmpeg -i input.mp4 -c copy -an output.mp4\n' 'or:\n' ' mkvmerge -o output.mkv input.mp4\n' 'For details, see https://pyscenedetect.readthedocs.io/en/latest/faq/' ) return duration = time.time() - start_time self.logger.info( 'Processed %d frames in %.1f seconds (average %.2f FPS).', num_frames, duration, float(num_frames) / duration) # Handle -s/--statsfile option. if self.stats_file_path is not None: if self.stats_manager.is_save_required(): with open(self.stats_file_path, 'wt') as stats_file: self.logger.info('Saving frame metrics to stats file: %s', os.path.basename(self.stats_file_path)) base_timecode = self.video_manager.get_base_timecode() self.stats_manager.save_to_csv(stats_file, base_timecode) else: self.logger.debug( 'No frame metrics updated, skipping update of the stats file.' ) # Get list of detected cuts and scenes from the SceneManager to generate the required output # files with based on the given commands (list-scenes, split-video, save-images, etc...). cut_list = self.scene_manager.get_cut_list() scene_list = self.scene_manager.get_scene_list() # Handle --drop-short-scenes. if self.drop_short_scenes and self.min_scene_len > 0: scene_list = [ s for s in scene_list if (s[1] - s[0]) >= self.min_scene_len ] video_paths = self.video_manager.get_video_paths() video_name = self.video_manager.get_video_name() if scene_list: # Ensure we don't divide by zero. self.logger.info( 'Detected %d scenes, average shot length %.1f seconds.', len(scene_list), sum([(end_time - start_time).get_seconds() for start_time, end_time in scene_list]) / float(len(scene_list))) else: self.logger.info('No scenes detected.') # Handle list-scenes command. if self.scene_list_output: scene_list_filename = Template( self.scene_list_name_format).safe_substitute( VIDEO_NAME=video_name) if not scene_list_filename.lower().endswith('.csv'): scene_list_filename += '.csv' scene_list_path = get_and_create_path( scene_list_filename, self.scene_list_directory if self.scene_list_directory is not None else self.output_directory) self.logger.info('Writing scene list to CSV file:\n %s', scene_list_path) with open(scene_list_path, 'wt') as scene_list_file: write_scene_list(output_csv_file=scene_list_file, scene_list=scene_list, include_cut_list=not self.skip_cuts, cut_list=cut_list) if self.print_scene_list: self.logger.info( """Scene List: ----------------------------------------------------------------------- | Scene # | Start Frame | Start Time | End Frame | End Time | ----------------------------------------------------------------------- %s ----------------------------------------------------------------------- """, '\n'.join([ ' | %5d | %11d | %s | %11d | %s |' % (i + 1, start_time.get_frames(), start_time.get_timecode(), end_time.get_frames(), end_time.get_timecode()) for i, (start_time, end_time) in enumerate(scene_list) ])) if cut_list: self.logger.info( 'Comma-separated timecode list:\n %s', ','.join([cut.get_timecode() for cut in cut_list])) # Handle save-images command. if self.save_images: image_output_dir = self.output_directory if self.image_directory is not None: image_output_dir = self.image_directory image_filenames = save_images( scene_list=scene_list, video_manager=self.video_manager, num_images=self.num_images, frame_margin=self.frame_margin, image_extension=self.image_extension, encoder_param=self.image_param, image_name_template=self.image_name_format, output_dir=image_output_dir, show_progress=not self.quiet_mode, scale=self.scale, height=self.height, width=self.width) # Handle export-html command. if self.export_html: html_filename = Template( self.html_name_format).safe_substitute(VIDEO_NAME=video_name) if not html_filename.lower().endswith('.html'): html_filename += '.html' html_path = get_and_create_path( html_filename, self.image_directory if self.image_directory is not None else self.output_directory) self.logger.info('Exporting to html file:\n %s:', html_path) if not self.html_include_images: image_filenames = None write_scene_list_html(html_path, scene_list, cut_list, image_filenames=image_filenames, image_width=self.image_width, image_height=self.image_height) # Handle split-video command. if self.split_video: output_path_template = self.split_name_format # Add proper extension to filename template if required. dot_pos = output_path_template.rfind('.') extension_length = 0 if dot_pos < 0 else len( output_path_template) - (dot_pos + 1) # If using mkvmerge, force extension to .mkv. if self.split_mkvmerge and not output_path_template.endswith( '.mkv'): output_path_template += '.mkv' # Otherwise, if using ffmpeg, only add an extension if one doesn't exist. elif not 2 <= extension_length <= 4: output_path_template += '.mp4' output_path_template = get_and_create_path( output_path_template, self.split_directory if self.split_directory is not None else self.output_directory) # Ensure the appropriate tool is available before handling split-video. check_split_video_requirements(self.split_mkvmerge) if self.split_mkvmerge: split_video_mkvmerge(video_paths, scene_list, output_path_template, video_name, suppress_output=self.quiet_mode or self.split_quiet) else: split_video_ffmpeg(video_paths, scene_list, output_path_template, video_name, arg_override=self.split_args, hide_progress=self.quiet_mode, suppress_output=self.quiet_mode or self.split_quiet) if scene_list: self.logger.info( 'Video splitting completed, individual scenes written to disk.' )
stats_manager = StatsManager() scene_manager = SceneManager(stats_manager) scene_manager.add_detector(ContentDetector(threshold=50)) video_manager.set_downscale_factor() video_manager.start() scene_manager.detect_scenes(frame_source=video_manager) # result with open(stats_path, 'w') as f: stats_manager.save_to_csv(f, video_manager.get_base_timecode()) scene_list = scene_manager.get_scene_list() print(f'{len(scene_list)} scenes detected!') save_images(scene_list, video_manager, num_images=1, image_name_template='$SCENE_NUMBER', output_dir='scenes') write_scene_list_html('result.html', scene_list) for scene in scene_list: start, end = scene # your code print(f'{start.get_seconds()} - {end.get_seconds()}')