Skip to content

Instantly share code, notes, and snippets.

@daitomanabe
Last active June 9, 2023 00:09
Show Gist options
  • Save daitomanabe/f7ad9d115a12fd5f0e1966574d2023e0 to your computer and use it in GitHub Desktop.
Save daitomanabe/f7ad9d115a12fd5f0e1966574d2023e0 to your computer and use it in GitHub Desktop.
video_splitter
import argparse
import os
import datetime
import math
from moviepy.editor import VideoFileClip
def split_video(video_file, output_basename, bpm, first_clip_length=None, offset_4bar=None):
# Load the video file
video = VideoFileClip(video_file)
# Calculate the duration of a beat in seconds
beat_duration = 60.0 / bpm * 4.0 * 8
# Calculate the frame duration
frame_duration = 1.0 / video.fps
# Adjust the beat duration to align with the frame rate
beat_duration = round(beat_duration / frame_duration) * frame_duration
# If not specified, the first clip length equals to a beat duration
if offset_4bar is None:
offset_4bar = 0
else:
offset_4bar = 60.0 / bpm * 4 * 4
print("--------------offset------------", offset_4bar)
# If not specified, the first clip length equals to a beat duration
if first_clip_length is None:
first_clip_length = beat_duration
# Initialize the start and end of the first clip
start = 0 + offset_4bar
end = first_clip_length + offset_4bar
# Initialize the index for clip filenames
index = 1
# Get current timestamp for unique folder name
timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
output_dir = os.path.join(os.path.dirname(video_file), f"export_{timestamp}")
# Create output directory if not exists
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Determine the number of clips
num_clips = math.ceil(video.duration / beat_duration)
# Calculate the exact clip durations
clip_durations = [beat_duration] * num_clips
remaining_duration = video.duration - sum(clip_durations)
while remaining_duration > frame_duration:
for i in range(num_clips):
clip_durations[i] += frame_duration
remaining_duration -= frame_duration
if remaining_duration <= frame_duration:
break
# Split the video into clips
for clip_duration in clip_durations:
# Create a clip
clip = video.subclip(start, min(end, video.duration))
# Save the clip
clip_filename = os.path.join(output_dir, f"{output_basename}_{index}.mov")
clip.write_videofile(clip_filename, codec='libx264', bitrate='10000k')
# Update the start and end for the next clip
start = end
end += clip_duration
index += 1
def main():
# Parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("video_file", help="Path to the video file to be split.")
parser.add_argument("output_basename", help="Base name for output files.")
parser.add_argument("bpm", type=float, help="Beats per minute.")
parser.add_argument("--first_clip_length", type=float, default=None,
help="Length of the first clip in seconds.")
parser.add_argument("--offset_4bar", type=float, default=None,
help="Offset 4 bar")
args = parser.parse_args()
# Split the video
split_video(args.video_file, args.output_basename, args.bpm, args.first_clip_length, args.offset_4bar)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment