Last active
June 9, 2023 00:09
-
-
Save daitomanabe/f7ad9d115a12fd5f0e1966574d2023e0 to your computer and use it in GitHub Desktop.
video_splitter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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