1
ewconfig/scripts/blink-timelapse
2023-11-29 21:04:28 -05:00

86 lines
2.5 KiB
Python
Executable File

#! /usr/bin/env python3
import argparse
import sys
import logging
import subprocess
from datetime import datetime
from pathlib import Path
logger = logging.getLogger(__name__)
def main() -> int:
# Handle program arguments
ap = argparse.ArgumentParser(
prog="blink-timelapse",
description="Generates timelapses from blink image captures",
)
ap.add_argument("--camera-id", help="Camera ID", default="155295")
ap.add_argument("--image-dir", help="Image directory", default="~/Pictures/blink")
ap.add_argument(
"--output-dir", help="Output directory", default="~/Videos/BlinkTimelapse"
)
ap.add_argument(
"--delete-frames", help="Delete frames after processing", action="store_true"
)
ap.add_argument("--frame-rate", help="Frame rate", default="5")
ap.add_argument(
"-v", "--verbose", help="Enable verbose logging", action="store_true"
)
args = ap.parse_args()
# Configure logging
logging.basicConfig(
level=logging.DEBUG if args.verbose else logging.INFO,
format="%(levelname)s: %(message)s",
)
# Find all frames
image_dir = Path(args.image_dir).expanduser()
frames = image_dir.glob(f"camera_{args.camera_id}.*.jpg")
frames = sorted(frames, key=lambda frame: frame.stat().st_mtime)
logger.info(f"Found {len(frames)} frames")
logger.info(
f"Oldest frame is from: {datetime.fromtimestamp(frames[0].stat().st_mtime)}"
)
logger.info(
f"Newest frame is from: {datetime.fromtimestamp(frames[-1].stat().st_mtime)}"
)
# Create output directory
output_dir = Path(args.output_dir).expanduser()
output_file = output_dir / f"camera_{args.camera_id}.{datetime.now().strftime('%Y%m%d-%H%M%S')}.mp4"
output_dir.mkdir(parents=True, exist_ok=True)
# Generate timelapse
logger.info(f"Generating timelapse: {output_file}")
subprocess.run(
[
"ffmpeg",
"-r",
args.frame_rate,
"-pattern_type",
"glob",
"-i",
f"{str(image_dir)}/camera_{args.camera_id}.*.jpg",
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
str(output_file),
],
check=True,
)
# Delete frames if needed
if args.delete_frames:
logger.info("Deleting frames")
for frame in frames:
frame.unlink()
return 0
if __name__ == "__main__":
sys.exit(main())