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
Beispiel #3
0
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)
Beispiel #4
0
    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.'
                )
Beispiel #5
0
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()}')