Files
playbook/antigravity-awesome-skills/skills/gemini-omni-flash-api/scripts/video/inspect_video.py
T
2026-07-01 16:02:41 +00:00

198 lines
6.2 KiB
Python

#!/usr/bin/env python3
import argparse
import json
import os
import subprocess
import sys
def format_size(size_bytes):
"""Formats file size in bytes to a human-readable string."""
try:
size_bytes = int(size_bytes)
except (ValueError, TypeError):
return "Unknown size"
for unit in ['B', 'KB', 'MB', 'GB']:
if size_bytes < 1024.0:
return f"{size_bytes:.2f} {unit}"
size_bytes /= 1024.0
return f"{size_bytes:.2f} TB"
def parse_fps(fps_str):
"""Parses fractional frame rates like '30/1' or '24000/1001' into floats."""
if not fps_str:
return "Unknown"
if "/" in fps_str:
try:
num, den = map(float, fps_str.split("/"))
if den != 0:
val = num / den
if val.is_integer():
return f"{int(val)} fps"
return f"{val:.2f} fps"
except (ValueError, ZeroDivisionError):
pass
try:
val = float(fps_str)
if val.is_integer():
return f"{int(val)} fps"
return f"{val:.2f} fps"
except ValueError:
return fps_str
def inspect_video(file_path, raw=False):
"""Runs ffprobe on the video file and returns parsed metadata dictionary."""
if not os.path.exists(file_path):
raise FileNotFoundError(f"File not found: {file_path}")
# Check if ffprobe is available
try:
subprocess.run(["ffprobe", "-version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
except (subprocess.SubprocessError, FileNotFoundError):
raise RuntimeError("ffprobe is not installed or not found in system PATH.")
cmd = [
"ffprobe",
"-v", "error",
"-show_format",
"-show_streams",
"-of", "json",
file_path
]
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
data = json.loads(result.stdout)
if raw:
return data
# Extract format level details
fmt = data.get("format", {})
duration = fmt.get("duration")
size_bytes = fmt.get("size")
bitrate = fmt.get("bit_rate")
# Format files size
size_str = format_size(size_bytes) if size_bytes else "Unknown"
# Parse duration
try:
duration_val = float(duration) if duration else 0.0
duration_str = f"{duration_val:.2f}s"
except ValueError:
duration_str = "Unknown"
duration_val = None
# Parse bitrate
try:
bitrate_kbps = f"{int(float(bitrate) / 1000)} kbps" if bitrate else "Unknown"
except ValueError:
bitrate_kbps = "Unknown"
video_streams = [s for s in data.get("streams", []) if s.get("codec_type") == "video"]
audio_streams = [s for s in data.get("streams", []) if s.get("codec_type") == "audio"]
has_video = len(video_streams) > 0
has_audio = len(audio_streams) > 0
video_info = {}
if has_video:
v = video_streams[0]
width = v.get("width")
height = v.get("height")
codec = v.get("codec_name", "Unknown").upper()
r_fps = parse_fps(v.get("r_frame_rate"))
avg_fps = parse_fps(v.get("avg_frame_rate"))
# Prefer r_frame_rate but fallback to avg
fps = r_fps if r_fps != "0 fps" and r_fps != "Unknown" else avg_fps
video_info = {
"resolution": f"{width}x{height}" if width and height else "Unknown",
"width": width,
"height": height,
"fps": fps,
"codec": codec,
"duration": v.get("duration")
}
audio_info = {}
if has_audio:
a = audio_streams[0]
codec = a.get("codec_name", "Unknown").upper()
channels = a.get("channels", "Unknown")
sample_rate = a.get("sample_rate")
sample_rate_khz = f"{float(sample_rate)/1000:.1f} kHz" if sample_rate else "Unknown"
audio_info = {
"codec": codec,
"channels": channels,
"sample_rate": sample_rate_khz
}
return {
"file_name": os.path.basename(file_path),
"file_size": size_str,
"size_bytes": size_bytes,
"duration": duration_str,
"duration_seconds": duration_val,
"bitrate": bitrate_kbps,
"has_video": has_video,
"video": video_info,
"has_audio": has_audio,
"audio": audio_info
}
def print_terminal_report(info):
"""Prints an aligned terminal report."""
print(f"\nVideo Inspection Report: {info['file_name']}")
print("=" * 50)
print(f"File Size : {info['file_size']}")
print(f"Duration : {info['duration']}")
print(f"Bitrate : {info['bitrate']}")
print("\nVideo Stream Details:")
if info["has_video"]:
v = info["video"]
print(f" * Resolution : {v['resolution']}")
print(f" * Frame Rate : {v['fps']}")
print(f" * Codec : {v['codec']}")
else:
print(" * No Video Stream Found.")
print("\nAudio Stream Details:")
if info["has_audio"]:
a = info["audio"]
print(" * Status : Audio Present")
print(f" * Codec : {a['codec']}")
print(f" * Channels : {a['channels']}")
print(f" * Sample Rate: {a['sample_rate']}")
else:
print(" * Status : No Audio Stream Present")
print()
def main():
parser = argparse.ArgumentParser(description="Inspect video details (duration, frame rate, resolution, audio presence) using ffprobe.")
parser.add_argument("file", help="Path to the video file to inspect")
parser.add_argument("--json", action="store_true", help="Output parsed summary in JSON format")
parser.add_argument("--raw", action="store_true", help="Output raw unmodified ffprobe JSON data")
args = parser.parse_args()
try:
if args.raw:
info = inspect_video(args.file, raw=True)
print(json.dumps(info, indent=2))
else:
info = inspect_video(args.file, raw=False)
if args.json:
print(json.dumps(info, indent=2))
else:
print_terminal_report(info)
except Exception as e:
print(f"Error inspecting video: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()