claude-video-analyze — Video Analysis and Quality Assessment
All analysis operations are read-only and safe to auto-execute without confirmation.
Quick Info (Most Common)
Full metadata dump (resolution, codec, duration, bitrate, audio, chapters):
ffprobe -v error -print_format json -show_format -show_streams -show_chapters "$INPUT"
One-liner summary (human-readable):
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,bit_rate,pix_fmt \
-show_entries format=duration,size,bit_rate,format_name -of default "$INPUT"
Specific Properties
Resolution:
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 "$INPUT"
Duration (seconds):
ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$INPUT"
Codec:
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$INPUT"
Framerate:
ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=nw=1:nk=1 "$INPUT"
Bitrate (video stream):
ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=nw=1:nk=1 "$INPUT"
Pixel format:
ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of default=nw=1:nk=1 "$INPUT"
Audio info:
ffprobe -v error -select_streams a -show_entries stream=codec_name,channels,sample_rate,bit_rate -of json "$INPUT"
HDR Detection
ffprobe -v quiet -select_streams v:0 -show_entries stream=color_transfer,color_primaries,color_space \
-of default=nw=1 "$INPUT"
| color_transfer | Meaning |
|---|---|
| smpte2084 | HDR10 / Dolby Vision |
| arib-std-b67 | HLG |
| bt709 | SDR |
| Unknown/empty | Likely SDR |
Keyframe Analysis
List all keyframe timestamps:
ffprobe -v error -select_streams v:0 -skip_frame nokey \
-show_entries frame=pkt_pts_time -of csv=p=0 "$INPUT"
Count keyframes:
ffprobe -v error -select_streams v:0 -skip_frame nokey \
-show_entries frame=pkt_pts_time -of csv=p=0 "$INPUT" | wc -l
GOP structure (I/P/B frame distribution):
ffprobe -v error -select_streams v:0 -show_entries frame=pict_type -of csv=p=0 "$INPUT" | \
sort | uniq -c | sort -rn
Scene Detection
FFmpeg native (fast, basic):
ffmpeg -i "$INPUT" -vf "scdet=s=1:t=14" -f null - 2>&1 | grep "lavfi.scd.time"
PySceneDetect (professional-grade, 5 algorithms):
# Adaptive detection (recommended for most content)
scenedetect -i "$INPUT" detect-adaptive -t 3.0 list-scenes
# Content-aware detection
scenedetect -i "$INPUT" detect-content -t 27.0 list-scenes
# Save scene images and split video
scenedetect -i "$INPUT" detect-adaptive -t 3.0 save-images split-video list-scenes
Audio Loudness Measurement
ffmpeg -i "$INPUT" -af loudnorm=I=-14:TP=-1.5:LRA=11:print_format=json -f null - 2>&1 | tail -12
Returns: input_i (integrated loudness), input_tp (true peak), input_lra (loudness range).
Quality Assessment
VMAF (Netflix perceptual quality, 0-100)
Compares distorted (encoded) vs reference (original):
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi "libvmaf=model=version=vmaf_v0.6.1:log_fmt=json:log_path=vmaf_results.json" -f null -
| VMAF Score | Quality |
|---|---|
| 93-100 | Excellent (indistinguishable from source) |
| 80-93 | Good (minor artifacts visible on close inspection) |
| 60-80 | Fair (noticeable quality loss) |
| <60 | Poor |
SSIM and PSNR
# All three metrics at once
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi "libvmaf=feature=name=psnr:feature=name=float_ssim:log_fmt=json:log_path=quality.json" -f null -
| Metric | Good | Excellent |
|---|---|---|
| PSNR | >30 dB | >40 dB |
| SSIM | >0.95 | >0.98 |
Optimal CRF Finder
Encode at multiple CRF values, measure VMAF for each, find the quality-size sweet spot:
for CRF in 18 20 22 24 26 28 30; do
ffmpeg -y -i "$INPUT" -c:v libx264 -crf $CRF -preset medium "/tmp/crf_test_${CRF}.mp4"
SIZE=$(stat -c%s "/tmp/crf_test_${CRF}.mp4")
VMAF=$(ffmpeg -i "/tmp/crf_test_${CRF}.mp4" -i "$INPUT" \
-lavfi "libvmaf=log_fmt=json:log_path=/tmp/vmaf_${CRF}.json" -f null - 2>&1 | \
grep -oP 'VMAF score: \K[\d.]+')
echo "CRF $CRF: ${SIZE} bytes, VMAF: $VMAF"
rm -f "/tmp/crf_test_${CRF}.mp4" "/tmp/vmaf_${CRF}.json"
done
Bitrate Analysis
Average bitrate:
ffprobe -v error -show_entries format=bit_rate -of default=nw=1:nk=1 "$INPUT" | awk '{printf "%.1f Mbps\n", $1/1000000}'
Per-frame bitrate (for variable bitrate analysis):
ffprobe -v error -select_streams v:0 -show_entries packet=size,pts_time -of csv=p=0 "$INPUT" | head -100
Chapter Detection
ffprobe -v error -print_format json -show_chapters "$INPUT"
Generate Comprehensive Report
For a full video report, run all of the above and format the output. Key sections:
- File info (name, size, container format)
- Video stream (codec, resolution, framerate, bitrate, pixel format, HDR status)
- Audio stream(s) (codec, channels, sample rate, bitrate, loudness)
- Chapters (if present)
- Keyframe structure (GOP length, keyframe interval)
- Recommendations (codec efficiency, loudness compliance, compatibility issues)
Reference
Load references/analyze.md for VMAF/SSIM/PSNR quality metric details, scene detection parameters, and advanced FFprobe recipes.