Files
momentry_core/scripts/thumbnail_extractor.py
accusys 75edf0aa71 Initial commit: Momentry Core v0.1
- Rust-based digital asset management system
- Video analysis: ASR, OCR, YOLO, Face, Pose
- RAG capabilities with Qdrant vector database
- Multi-database support: PostgreSQL, Redis, MongoDB
- Monitoring system with launchd plists
- n8n workflow automation integration
2026-03-25 14:53:41 +08:00

98 lines
2.7 KiB
Python

#!/opt/homebrew/bin/python3.11
import sys
import os
import subprocess
import json
import argparse
def get_duration(video_path):
result = subprocess.run(
["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", video_path],
capture_output=True,
text=True,
)
data = json.loads(result.stdout)
return float(data["format"]["duration"])
def extract_thumbnails(video_path, uuid, output_dir, count=6):
"""Extract evenly-spaced thumbnails from video."""
if not os.path.exists(video_path):
print(f"Error: Video file not found: {video_path}", file=sys.stderr)
return None
duration = get_duration(video_path)
print(f"Video duration: {duration:.2f}s", file=sys.stderr)
# Output directory
thumb_dir = os.path.join(output_dir, uuid)
os.makedirs(thumb_dir, exist_ok=True)
# Calculate timestamps (skip first 10%, skip last 10%)
start_ts = duration * 0.1
end_ts = duration * 0.9
interval = (end_ts - start_ts) / (count - 1) if count > 1 else 0
extracted = []
for i in range(count):
if count == 1:
ts = duration / 2
else:
ts = start_ts + (interval * i)
output_file = os.path.join(thumb_dir, f"thumb_{i:03d}.jpg")
result = subprocess.run(
[
"ffmpeg",
"-y",
"-ss",
str(ts),
"-i",
video_path,
"-vframes",
"1",
"-q:v",
"2",
"-vf",
"scale=320:-1",
output_file,
],
capture_output=True,
)
if result.returncode == 0 and os.path.exists(output_file):
extracted.append(output_file)
print(f" Extracted: {output_file} at {ts:.1f}s", file=sys.stderr)
else:
print(f" Failed to extract frame at {ts:.1f}s", file=sys.stderr)
return extracted
def main():
parser = argparse.ArgumentParser(
description="Extract keyframe thumbnails from video"
)
parser.add_argument("video_path", help="Path to video file")
parser.add_argument("uuid", help="Video UUID")
parser.add_argument("-o", "--output", default="thumbnails", help="Output directory")
parser.add_argument(
"-c", "--count", type=int, default=6, help="Number of thumbnails"
)
args = parser.parse_args()
result = extract_thumbnails(args.video_path, args.uuid, args.output, args.count)
if result:
print(json.dumps({"uuid": args.uuid, "count": len(result), "files": result}))
else:
print(json.dumps({"error": "Failed to extract thumbnails"}))
sys.exit(1)
if __name__ == "__main__":
main()