video-frame-extraction
Extract frames from video files and save them as images using OpenCV
Install / Use
npx skills add benchflow-ai/skillsbench --skill video-frame-extractionInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
AI & Machine LearningSupported Platforms
Our assessment of video-frame-extraction
video-frame-extraction scores 91/100 on our quality scale, 254th of 875 AI & Machine Learning skills we index (top 30%).
Its SKILL.md is 14 KB long, well organised into 33 sections with 16 code examples: a thorough specification that gives an agent plenty to work with.
With 1,813 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated about 2 months ago, so video-frame-extraction is actively maintained.
- It is released under the Apache-2.0 license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
video-frame-extraction compared with similar skills
All 4 of these similar skills score higher than video-frame-extraction; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| video-frame-extraction (this skill)by benchflow-ai | 91 | 1.8k | 2mo ago | SKILL.md |
| claude-memby thedotmack | 100 | 95.0k | today | CLAUDE.md |
| Understand-Anythingby Egonex-AI | 100 | 84.8k | 2d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 74.2k | today | CLAUDE.md |
| CowAgentby zhayujie | 100 | 47.2k | today | CLAUDE.md |
Frequently asked questions
- How do I install video-frame-extraction?
- Run
npx skills add benchflow-ai/skillsbench --skill video-frame-extraction. The install tabs above show the steps for each supported agent. - Which AI agents does video-frame-extraction work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is video-frame-extraction safe to use?
- It is Apache-2.0-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is video-frame-extraction still maintained?
- The repository was last updated about 2 months ago, so video-frame-extraction is actively maintained.
Skill content
View source on GitHubname: video-frame-extraction description: Extract frames from video files and save them as images using OpenCV
Video Frame Extraction Skill
Purpose
This skill enables extraction of individual frames from video files (MP4, AVI, MOV, etc.) using OpenCV. Extracted frames are saved as image files in a specified output directory. It is suitable for video analysis, creating training datasets, thumbnail generation, and preprocessing video content for further processing.
When to Use
- Extracting frames for machine learning training data
- Creating image sequences from video content
- Generating video thumbnails or preview images
- Preprocessing videos for object detection or tracking
- Converting video segments to image collections for analysis
- Sampling frames at specific intervals for time-lapse effects
Required Libraries
The following Python libraries are required:
import cv2
import os
import json
from pathlib import Path
Input Requirements
- File formats: MP4, AVI, MOV, MKV, WMV, FLV, WEBM
- Video codec: Must be readable by OpenCV (most common codecs supported)
- File access: Read permissions on source video
- Output directory: Write permissions on destination folder
- Disk space: Ensure sufficient space for extracted frames (uncompressed images)
Output Schema
All extraction results must be returned as valid JSON conforming to this schema:
{
"success": true,
"source_video": "sample.mp4",
"output_directory": "/path/to/frames",
"frames_extracted": 150,
"extraction_params": {
"interval": 1,
"start_frame": 0,
"end_frame": null,
"output_format": "jpg"
},
"video_metadata": {
"total_frames": 300,
"fps": 30.0,
"duration_seconds": 10.0,
"resolution": [1920, 1080]
},
"output_files": [
"frame_000001.jpg",
"frame_000002.jpg"
],
"warnings": []
}
Field Descriptions
success: Boolean indicating whether frame extraction completedsource_video: Original video filenameoutput_directory: Path where frames were savedframes_extracted: Total number of frames successfully savedextraction_params.interval: Frame sampling interval (1 = every frame, 2 = every other frame, etc.)extraction_params.start_frame: First frame index extractedextraction_params.end_frame: Last frame index extracted (null if extracted to end)extraction_params.output_format: Image format used for saving framesvideo_metadata.total_frames: Total frame count in source videovideo_metadata.fps: Frames per second of source videovideo_metadata.duration_seconds: Video duration in secondsvideo_metadata.resolution: Video dimensions as [width, height]output_files: List of generated frame filenameswarnings: Array of issues encountered during extraction
Code Examples
Basic Frame Extraction
import cv2
import os
def extract_all_frames(video_path, output_dir):
"""Extract all frames from a video file."""
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
filename = os.path.join(output_dir, f"frame_{frame_count:06d}.jpg")
cv2.imwrite(filename, frame)
frame_count += 1
cap.release()
return frame_count
Interval-Based Frame Extraction
import cv2
import os
def extract_frames_at_interval(video_path, output_dir, interval=1):
"""Extract frames at specified intervals."""
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
frame_index = 0
saved_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_index % interval == 0:
filename = os.path.join(output_dir, f"frame_{saved_count:06d}.jpg")
cv2.imwrite(filename, frame)
saved_count += 1
frame_index += 1
cap.release()
return saved_count
Full Extraction with JSON Output
import cv2
import os
import json
from pathlib import Path
def extract_frames_to_json(video_path, output_dir, interval=1,
start_frame=0, end_frame=None, output_format="jpg"):
"""Extract frames and return results as JSON."""
video_name = os.path.basename(video_path)
warnings = []
output_files = []
try:
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise ValueError(f"Cannot open video: {video_path}")
# Get video metadata
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
duration = total_frames / fps if fps > 0 else 0
# Set end frame if not specified
if end_frame is None:
end_frame = total_frames
# Seek to start frame
if start_frame > 0:
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
frame_index = start_frame
saved_count = 0
while frame_index < end_frame:
ret, frame = cap.read()
if not ret:
if frame_index < end_frame:
warnings.append(f"Video ended early at frame {frame_index}")
break
if (frame_index - start_frame) % interval == 0:
filename = f"frame_{saved_count:06d}.{output_format}"
filepath = os.path.join(output_dir, filename)
cv2.imwrite(filepath, frame)
output_files.append(filename)
saved_count += 1
frame_index += 1
cap.release()
result = {
"success": True,
"source_video": video_name,
"output_directory": str(output_dir),
"frames_extracted": saved_count,
"extraction_params": {
"interval": interval,
"start_frame": start_frame,
"end_frame": end_frame,
"output_format": output_format
},
"video_metadata": {
"total_frames": total_frames,
"fps": fps,
"duration_seconds": round(duration, 2),
"resolution": [width, height]
},
"output_files": output_files,
"warnings": warnings
}
except Exception as e:
result = {
"success": False,
"source_video": video_name,
"output_directory": str(output_dir),
"frames_extracted": 0,
"extraction_params": {
"interval": interval,
"start_frame": start_frame,
"end_frame": end_frame,
"output_format": output_format
},
"video_metadata": {
"total_frames": 0,
"fps": 0,
"duration_seconds": 0,
"resolution": [0, 0]
},
"output_files": [],
"warnings": [f"Extraction failed: {str(e)}"]
}
return result
# Usage
result = extract_frames_to_json("video.mp4", "./frames", interval=10)
print(json.dumps(result, indent=2))
Time-Based Frame Extraction
import cv2
import os
def extract_frames_by_seconds(video_path, output_dir, seconds_interval=1.0):
"""Extract frames at specific time intervals (in seconds)."""
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_interval = int(fps * seconds_interval)
if frame_interval < 1:
frame_interval = 1
frame_index = 0
saved_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_index % frame_interval == 0:
filename = os.path.join(output_dir, f"frame_{saved_count:06d}.jpg")
cv2.imwrite(filename, frame)
saved_count += 1
frame_index += 1
cap.release()
return saved_count
Batch Processing Multiple Videos
import cv2
import os
import json
from pathlib import Path
def process_video_directory(video_dir, output_base_dir, interval=1):
"""Process all videos in a directory and extract frames."""
video_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm'}
results = []
for video_file in sorted(Path(video_dir).iterdir()):
if video_file.suffix.lower() in video_extensions:
video_output_dir = os.path.join(
output_base_dir,
video_file.stem
)
result = extract_frames_to_json(
str(video_file),
video_output_dir,
interval=interval
)
results.append(result)
print(f"Processed: {video_file.name} -> {result['frames_extracted']} frames")
return results
Extraction Configuration Options
Output Image Formats
# JPEG format (default, good balance of quality and size)
cv2.imwrite("frame.jpg", frame)
# PNG format (lossless, larger files)
cv2.imwrite("frame.png", frame)
# JPEG with custom quality (0-100)
cv2.imwrite("frame.jpg", frame, [cv2.IMWRITE_JPEG_QUALITY, 95])
# PNG with compression level (0-9)
cv2.imwrite("frame.png", frame, [cv2.IMWRITE_PNG_COMPRESSION, 3])
Frame Seeking Methods
# Seek by frame number
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
# Seek by milliseconds
cap.set(cv2.CAP_PROP_POS_MSEC, milliseconds)
# Seek by ratio (0.0 to 1.0)
cap.set(cv2.CAP_PROP_POS_AVI_RATIO, 0.5) # Middle of video
Frame Resizing
def extract_resized_frames(video_path, output_dir, target_size=(640, 480)):
"""Extract and resize frames to specified dimensions."""
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
break
resized = cv2.resize(frame, target_size)
filename = os.path.join(output_dir, f"frame_{frame_count:06d}.jpg")
cv2.imwrite(filename, resized)
frame_count += 1
cap.release()
return frame_count
Video Metadata Retrieval
Extract video properties before processing:
def get_video_info(video_path):
"""Retrieve video metadata."""
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
return None
info = {
"total_frames": int(cap.get(cv2.CAP_PROP_FRAME_COUNT)),
"fps": cap.get(cv2.CAP_PROP_FPS),
"width": int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
"height": int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),
"codec": int(cap.get(cv2.CAP_PROP_FOURCC)),
"duration_seconds": cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
}
cap.release()
return info
Specific Frame Extraction
For extracting frames at exact positions:
def extract_specific_frames(video_path, output_dir, frame_numbers):
"""Extract specific frames by their indices."""
os.makedirs(output_dir, exist_ok=True)
cap = cv2.VideoCapture(video_path)
extracted = []
for frame_num in sorted(frame_numbers):
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)
ret, frame = cap.read()
if ret:
filename = os.path.join(output_dir, f"frame_{frame_num:06d}.jpg")
cv2.imwrite(filename, frame)
extracted.append(frame_num)
cap.release()
return extracted
Erro
Truncated for display — read the full file on GitHub.
Related Skills
claude-mem
95.0kPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode + More
Understand-Anything
84.8kGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.
headroom
74.2kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
CowAgent
47.2kOpen-source personal AI assistant & Agent Harness. Plans tasks, runs tools and skills, self-evolves with memory and knowledge. Multi-agent, multi-model, multi-channel. Lightweight, extensible, one-line install.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
