Python Split Video into Separate Clips By Shot Changes – Python Tutorial

By | May 30, 2023

In this tutorial, we will introduce how to split a video file into some separate clips by shot changes using python. You can learn how to do by our steps.

Preliminary

In order to get the shot changes in a video, we can use PySceneDetect. We can use pip to install it.

pip install --upgrade scenedetect[opencv]

How to get video scenes by detecting shot changes in PySceneDetect?

We can use detect() function to get video scenes.

Here is an example:

from scenedetect import detect, ContentDetector
video_file = r'lsx_a2_0518_final.mp4'
scene_list = detect(video_file, ContentDetector())

for i, scene in enumerate(scene_list):
    print('Scene %2d: Start %s / Frame %d, End %s / Frame %d' % (
        i+1,
        scene[0].get_timecode(), scene[0].get_frames(),
        scene[1].get_timecode(), scene[1].get_frames(),))

In this code, video_file is a video file that we plan to detect shot changes. ContentDetector() is an instance that detects shot changes in a video. It is defined as:

def __init__(
        self,
        threshold: float = 27.0,
        min_scene_len: int = 15,
        weights: 'ContentDetector.Components' = DEFAULT_COMPONENT_WEIGHTS,
        luma_only: bool = False,
        kernel_size: Optional[int] = None,
    ):

threshold: Threshold the average change in pixel intensity must exceed to trigger a cut.

min_scene_len: Once a cut is detected, this many frames must pass before a new one can be added to the scene list.

We can set threshold and min_scene_len to change ContentDetector()

Run this code, we may see:

Scene  1: Start 00:00:00.000 / Frame 0, End 00:00:01.760 / Frame 44
Scene  2: Start 00:00:01.760 / Frame 44, End 00:00:09.240 / Frame 231
Scene  3: Start 00:00:09.240 / Frame 231, End 00:00:11.480 / Frame 287
Scene  4: Start 00:00:11.480 / Frame 287, End 00:00:14.080 / Frame 352
Scene  5: Start 00:00:14.080 / Frame 352, End 00:01:05.280 / Frame 1632
Scene  6: Start 00:01:05.280 / Frame 1632, End 00:01:11.200 / Frame 1780

How to get video clips based on shot changes?

After we have got the shot changes, we can use scene[0].get_timecode() and scene[1].get_timecode() to get clips by python moviepy. Here is the tutorial:

Best Practice to Python Clip Big Video to Small Video by Start Time and End Time – Python Tutorial

Finally, we may see these clips.

Python Split Video into Separate Clips By Shot Changes - Python Tutorial

Here we use moviepy to create a function to extract clip.

def split_video(video_file, clip_video_file, start_time, end_time):
    clip = VideoFileClip(video_file)
    newclip = clip.subclip(start_time, end_time)
    newclip.write_videofile(clip_video_file)
    newclip.close()
    clip.close()

Then, we can get clip as follows:

split_video(video_file, str(i)+".mp4", scene[0].get_timecode(), scene[1].get_timecode())