About video-analysis
A skill for inspecting video files with command-line tools, primarily ffprobe and mp4dump, with JSON output that can be filtered using jq. It is suited to workflows that need format, stream, packet, frame, or MP4 box details.
Key features
- 01Inspect formats and streams
- 02Read packet and frame metadata
- 03Query codec and dimensions
- 04Examine MP4 box structure
- 05Filter JSON output with jq
Use cases
- 01Check video duration and codecs
- 02Count frames or keyframes
- 03Inspect audio sample rate
- 04Determine whether an MP4 is fragmented
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ editframe/ skills --skill video-analysisAfter installing, type/video-analysisin Claude Code to confirm it loaded.
Details
From the project READMEVideo Analysis
Analyze MP4/video files using CLI tools. All commands output JSON for jq filtering.
FFprobe Basics
Format + Streams (most common)
ffprobe -v quiet -print_format json -show_format -show_streams FILE.mp4
Key fields: .format.duration, .streams[].codec_name, .streams[].codec_type
Stream selection
-select_streams v:0 # first video stream
-select_streams a:0 # first audio stream
-select_streams v # all video streams
Packets (sample-level data)
ffprobe -v quiet -print_format json -show_packets FILE.mp4
Key fields: .packets[].pts_time, .packets[].flags, .packets[].size
Flag meanings: K = keyframe, D = discard, _ = none
Keyframe packets only
ffprobe -v quiet -print_format json -show_packets -select_streams v:0 FILE.mp4 | \
jq '[.packets[] | select(.flags | test("K"))]'
Count keyframes
ffprobe -v quiet -print_format json -show_packets -select_streams v:0 FILE.mp4 | \
jq '[.packets[] | select(.flags | test("K"))] | length'
Frames (decoded frame info)
ffprobe -v quiet -print_format json -show_frames FILE.mp4
Key fields: .frames[].pict_type (I/P/B), .frames[].key_frame, .frames[].pts_time
Limit frame count (faster)
ffprobe -v quiet -print_format json -show_frames -read_intervals "%+#100" FILE.mp4
Reads first 100 frames only.
Common Queries
Duration
ffprobe -v quiet -show_entries format=duration -of csv=p=0 FILE.mp4
Frame count
ffprobe -v quiet -select_streams v:0 -show_entries stream=nb_frames -of csv=p=0 FILE.mp4
Codec info
ffprobe -v quiet -print_format json -show_streams FILE.mp4 | \
jq '.streams[] | {codec: .codec_name, type: .codec_type, profile: .profile}'
Video dimensions
ffprobe -v quiet -select_streams v:0 -show_entries stream=width,height -of csv=p=0 FILE.mp4
Sample rate / channels (audio)
ffprobe -v quiet -select_streams a:0 -show_entries stream=sample_rate,channels -of csv=p=0 FILE.mp4
MP4 Box Structure (mp4dump)
mp4dump --format json FILE.mp4
Key boxes
ftyp: file type/brandmoov: movie metadata (contains all track info)mvhd: movie header (duration, timescale)trak: track containermdhd: media header (per-track timescale/duration)stbl: sample table (stts, stss, stsz, stco)stss: sync sample table (keyframe positions)moof: movie fragment (fragmented MP4)mdat: media data
Find specific box
mp4dump --format json FILE.mp4 | jq '.. | objects | select(.name == "mvhd")'
Fragmented MP4 check
mp4dump --format json FILE.mp4 | jq '[.. | objects | select(.name == "moof")] | length'
Non-zero = fragmented.
JQ Patterns
Filter by field value
jq '.streams[] | select(.codec_type == "video")'
Extract specific fields
jq '.streams[] | {codec: .codec_name, duration: .duration}'
Count items
jq '.packets | length'
First N items
jq '.packets[:10]'
Sum values
jq '[.packets[].size | tonumber] | add'
CSV Output (for scripting)
ffprobe -v quiet -select_streams v:0 -show_entries packet=pts_time,flags,size -of csv=p=0 FILE.mp4
Output: 0.000000,1263,K__ (one line per packet)
Test Assets
Sample files in elements/test-assets/:
10s-bars.mp4- 10s color bars with audioframe-count.mp4- frame counting testbars-n-tone.mp4- multi-track test