2020-08-19 06:41:58 +00:00
|
|
|
#!/bin/env python
|
2020-06-09 15:09:20 +00:00
|
|
|
|
2020-10-13 13:18:52 +00:00
|
|
|
import sys
|
2020-10-11 22:32:24 +00:00
|
|
|
from subprocess import Popen
|
|
|
|
|
2021-01-09 20:37:01 +00:00
|
|
|
try:
|
|
|
|
from scenedetect.detectors import ContentDetector
|
|
|
|
from scenedetect.scene_manager import SceneManager
|
|
|
|
from scenedetect.video_manager import VideoManager
|
|
|
|
from scenedetect.frame_timecode import FrameTimecode
|
|
|
|
except ImportError:
|
2021-01-10 04:14:25 +00:00
|
|
|
ContentDetector = None
|
2020-06-27 19:21:00 +00:00
|
|
|
|
2020-12-25 15:32:45 +00:00
|
|
|
from av1an.logger import log
|
|
|
|
from av1an.utils import frame_probe
|
|
|
|
from av1an.vapoursynth import compose_vapoursynth_pipe
|
2020-06-09 15:09:20 +00:00
|
|
|
|
2020-10-13 13:18:52 +00:00
|
|
|
if sys.platform == "linux":
|
|
|
|
from os import mkfifo
|
|
|
|
|
2020-06-22 20:11:07 +00:00
|
|
|
|
2021-01-09 20:37:01 +00:00
|
|
|
def pyscene(video, threshold, min_scene_len, is_vs, temp, quiet):
|
2020-06-09 15:09:20 +00:00
|
|
|
"""
|
|
|
|
Running PySceneDetect detection on source video for segmenting.
|
|
|
|
Optimal threshold settings 15-50
|
|
|
|
"""
|
2020-06-22 16:33:14 +00:00
|
|
|
|
2021-01-10 04:14:25 +00:00
|
|
|
if ContentDetector is None:
|
2021-04-12 23:23:48 +00:00
|
|
|
log(
|
|
|
|
f"Unable to start PySceneDetect because it was not found. Please install scenedetect[opencv] to use"
|
|
|
|
)
|
2021-01-09 20:37:01 +00:00
|
|
|
return []
|
|
|
|
|
2021-04-12 23:23:48 +00:00
|
|
|
log(f"Starting PySceneDetect:")
|
|
|
|
log(f"Threshold: {threshold}")
|
|
|
|
log(f"Min scene length: {min_scene_len}")
|
|
|
|
log(f"Is Vapoursynth input: {is_vs}")
|
2020-10-11 22:32:24 +00:00
|
|
|
|
|
|
|
if is_vs:
|
|
|
|
# Handling vapoursynth, so we need to create a named pipe to feed to VideoManager.
|
|
|
|
# TODO: Do we clean this up after pyscenedetect has run, or leave it as part of the temp dir, where it will be cleaned up later?
|
2020-10-13 13:18:52 +00:00
|
|
|
if sys.platform == "linux":
|
2021-04-12 23:23:48 +00:00
|
|
|
vspipe_fifo = temp / "vspipe.y4m"
|
2020-10-13 13:18:52 +00:00
|
|
|
mkfifo(vspipe_fifo)
|
|
|
|
else:
|
|
|
|
vspipe_fifo = None
|
|
|
|
|
2020-10-11 22:32:24 +00:00
|
|
|
vspipe_cmd = compose_vapoursynth_pipe(video, vspipe_fifo)
|
|
|
|
vspipe_process = Popen(vspipe_cmd)
|
|
|
|
|
|
|
|
# Get number of frames from Vapoursynth script to pass as duration to VideoManager.
|
|
|
|
# We need to pass the number of frames to the manager, otherwise it won't close the
|
|
|
|
# receiving end of the pipe, and will simply sit waiting after vspipe has finished sending
|
|
|
|
# the last frame.
|
|
|
|
frames = frame_probe(video)
|
|
|
|
|
|
|
|
video_manager = VideoManager([str(vspipe_fifo if is_vs else video)])
|
2020-06-09 15:09:20 +00:00
|
|
|
scene_manager = SceneManager()
|
2021-02-01 03:07:07 +00:00
|
|
|
scene_manager.add_detector(
|
2021-04-12 23:23:48 +00:00
|
|
|
ContentDetector(threshold=threshold, min_scene_len=min_scene_len)
|
|
|
|
)
|
2020-06-09 15:09:20 +00:00
|
|
|
base_timecode = video_manager.get_base_timecode()
|
|
|
|
|
2021-04-12 23:23:48 +00:00
|
|
|
video_manager.set_duration(
|
|
|
|
duration=FrameTimecode(frames, video_manager.get_framerate()) if is_vs else None
|
|
|
|
)
|
2020-06-09 15:09:20 +00:00
|
|
|
|
|
|
|
# Set downscale factor to improve processing speed.
|
|
|
|
video_manager.set_downscale_factor()
|
2020-06-10 09:29:28 +00:00
|
|
|
|
2020-06-09 15:09:20 +00:00
|
|
|
# Start video_manager.
|
|
|
|
video_manager.start()
|
|
|
|
|
2021-04-12 23:23:48 +00:00
|
|
|
scene_manager.detect_scenes(frame_source=video_manager, show_progress=(not quiet))
|
2020-06-09 15:09:20 +00:00
|
|
|
|
2020-10-11 22:32:24 +00:00
|
|
|
# If fed using a vspipe process, ensure that vspipe has finished.
|
|
|
|
if is_vs:
|
|
|
|
vspipe_process.wait()
|
|
|
|
|
2020-06-09 15:09:20 +00:00
|
|
|
# Obtain list of detected scenes.
|
|
|
|
scene_list = scene_manager.get_scene_list(base_timecode)
|
|
|
|
|
2020-06-13 21:52:29 +00:00
|
|
|
scenes = [int(scene[0].get_frames()) for scene in scene_list]
|
2020-06-09 15:09:20 +00:00
|
|
|
|
2020-06-13 21:52:29 +00:00
|
|
|
# Remove 0 from list
|
2020-06-17 08:34:22 +00:00
|
|
|
if scenes[0] == 0:
|
2020-06-13 21:52:29 +00:00
|
|
|
scenes.remove(0)
|
2021-04-12 23:23:48 +00:00
|
|
|
log(f"Found scenes: {len(scenes)}")
|
2020-06-09 15:09:20 +00:00
|
|
|
|
2020-06-20 01:58:19 +00:00
|
|
|
return scenes
|