Skip to content

Instantly share code, notes, and snippets.

@LexSong
Created April 19, 2019 12:46
Show Gist options
  • Select an option

  • Save LexSong/a50985116b73d09970ab9054e8023543 to your computer and use it in GitHub Desktop.

Select an option

Save LexSong/a50985116b73d09970ab9054e8023543 to your computer and use it in GitHub Desktop.
Split scenes with ffmpeg
import subprocess
import sys
from pathlib import Path
def get_segment_times(video_file):
detect_scene_command = [
"ffmpeg",
"-i",
str(video_file),
"-filter_complex",
"select='gt(scene,0.2)',metadata=print:file=-",
"-f",
"null",
"-",
]
def parse_frame_info(line):
return dict([x.split(':') for x in line.split()])
def parse_frame_time(line):
x = parse_frame_info(line)
return float(x['pts_time'])
output = subprocess.check_output(detect_scene_command)
lines = output.decode().split('\n')
lines = [x for x in lines if x.startswith("frame")]
segment_times = [parse_frame_time(x) for x in lines]
return segment_times
def split_video(video_file, segment_times, target_files):
def segment_times_to_string(times):
return ','.join(str(x) for x in times)
segment_times_string = segment_times_to_string(segment_times)
segment_command = [
"ffmpeg",
"-i",
str(video_file),
"-force_key_frames:v",
segment_times_string,
"-f",
"segment",
"-segment_times",
segment_times_string,
"-reset_timestamps",
"1",
"-c:v",
"libx264",
"-c:a",
"copy",
"-crf",
"10",
str(target_files),
]
subprocess.call(segment_command)
input_dir = Path(sys.argv[1])
output_dir = Path(sys.argv[2])
for video in input_dir.glob('*.mp4'):
target_name = output_dir / f"{Path(video).stem}_%03d.mp4"
segment_times = get_segment_times(video)
split_video(video, segment_times, target_name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment