Skip to content

Instantly share code, notes, and snippets.

@m-szk
Last active April 24, 2025 11:04
Show Gist options
  • Save m-szk/8c54ef1e8919cea81e07ca037da3fba4 to your computer and use it in GitHub Desktop.
Save m-szk/8c54ef1e8919cea81e07ca037da3fba4 to your computer and use it in GitHub Desktop.
import argparse
import os
import sys
import subprocess
# 定数
SUPPORTED_EXTENSIONS = (".mp4", ".mov")
BLACKDETECT_FILTER = 'blackdetect=d=0.0:pic_th=0.00'
def validate_directory(directory, dir_type="input"):
"""ディレクトリの存在を確認"""
if not directory or not os.path.isdir(directory):
print(f"Does not exist {dir_type} directory: {directory}")
sys.exit(1)
def get_video_files(input_dir):
"""指定されたディレクトリ内の動画ファイルを取得"""
for root, _, files in os.walk(input_dir):
for file in sorted(files):
if file.endswith(SUPPORTED_EXTENSIONS):
yield os.path.join(root, file)
def validate_frames(input_path):
"""動画内の画面が認識できるフレームの開始・終了時間を検出"""
result = subprocess.run(
['ffmpeg', '-i', input_path, '-vf', BLACKDETECT_FILTER, '-an', '-f', 'null', '-'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
for line in result.stderr.split('\n'):
if 'black_start' in line:
video_start = line.split('black_start:')[1].split(' ')[0]
video_end = line.split('black_end:')[1].split(' ')[0]
return float(video_start), float(video_end)
return None, None
def trim_video(input_path, video_start, output_path):
"""動画をトリミング"""
try:
subprocess.run(
['ffmpeg', '-i', input_path,
'-vf', f"trim=start_frame={video_start},setpts=PTS-STARTPTS",
'-af', f"atrim=start_sample={video_start},asetpts=PTS-STARTPTS",
output_path],
check=True
)
except subprocess.CalledProcessError as e:
print(f"Error trimming video {input_path}: {e}")
sys.exit(1)
def process_videos(input_dir, output_dir):
"""動画ファイルを処理"""
validate_directory(input_dir, "input")
validate_directory(output_dir, "output")
for input_path in get_video_files(input_dir):
video_start, video_end = validate_frames(input_path)
if video_start is not None:
output_path = os.path.join(output_dir, os.path.basename(input_path))
print(f"Processing {input_path} (start: {video_start}, end: {video_end})")
trim_video(input_path, video_start, output_path)
else:
print(f"No valid frames detected in {input_path}")
def main():
parser = argparse.ArgumentParser(description="Video trimming")
parser.add_argument("input_dir", type=str, help="Input directory containing videos")
parser.add_argument("output_dir", type=str, help="Output directory for trimmed videos")
args = parser.parse_args()
process_videos(args.input_dir, args.output_dir)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment