Last active
April 24, 2025 11:04
-
-
Save m-szk/8c54ef1e8919cea81e07ca037da3fba4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 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