Python
Video Processing
Frame Extraction
OpenCV
Image Analysis

Python - Extracting and Saving Video Frames

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Extracting video frames is a common preprocessing step for computer vision, dataset creation, and media debugging. In Python, the most common tool is OpenCV because it gives direct programmatic control over reading, sampling, and saving frames. The main design decisions are whether to save every frame or sample at intervals, and how to name output files predictably.

Read a Video with OpenCV

Start with cv2.VideoCapture. Always verify that the file opened successfully before trying to read frames.

python
1from pathlib import Path
2import cv2
3
4def extract_all_frames(video_path: str, output_dir: str) -> int:
5    out_dir = Path(output_dir)
6    out_dir.mkdir(parents=True, exist_ok=True)
7
8    cap = cv2.VideoCapture(video_path)
9    if not cap.isOpened():
10        raise RuntimeError(f"Cannot open video: {video_path}")
11
12    count = 0
13    while True:
14        ok, frame = cap.read()
15        if not ok:
16            break
17
18        frame_path = out_dir / f"frame_{count:06d}.jpg"
19        cv2.imwrite(str(frame_path), frame)
20        count += 1
21
22    cap.release()
23    return count
24
25print(extract_all_frames("input.mp4", "frames"))

This saves every decoded frame in order.

Save Every Nth Frame Instead

For long videos, saving every frame can create huge storage costs. Sampling every Nth frame is often a better default.

python
1from pathlib import Path
2import cv2
3
4def extract_every_n(video_path: str, output_dir: str, step: int = 10) -> int:
5    if step <= 0:
6        raise ValueError("step must be positive")
7
8    out_dir = Path(output_dir)
9    out_dir.mkdir(parents=True, exist_ok=True)
10
11    cap = cv2.VideoCapture(video_path)
12    if not cap.isOpened():
13        raise RuntimeError("Cannot open video")
14
15    saved = 0
16    index = 0
17
18    while True:
19        ok, frame = cap.read()
20        if not ok:
21            break
22
23        if index % step == 0:
24            cv2.imwrite(str(out_dir / f"sample_{saved:05d}.png"), frame)
25            saved += 1
26
27        index += 1
28
29    cap.release()
30    return saved
31
32print(extract_every_n("input.mp4", "samples", step=30))

That is useful when you only need a lightweight preview set or a sparse labeling dataset.

Sample by Time Instead of Frame Count

Sometimes the requirement is “one frame per second” rather than “every Nth frame.” In that case, use the FPS metadata to derive the sampling interval.

python
1import cv2
2
3cap = cv2.VideoCapture("input.mp4")
4fps = cap.get(cv2.CAP_PROP_FPS)
5cap.release()
6
7print("fps:", fps)

If the FPS is valid, a one-second interval is roughly round(fps) frames. Be careful, though: some video files report poor metadata, so it is worth validating with test clips.

Organize Output Predictably

Video extraction jobs can generate thousands of files. Good naming and directory structure matter:

  • zero-padded filenames sort correctly
  • one output folder per source video prevents collisions
  • JPEG saves space, PNG preserves more detail

A useful layout looks like this:

text
1frames/
2  input_video/
3    frame_000000.jpg
4    frame_000001.jpg

This becomes important quickly once you process multiple videos.

Validate the Result

After extraction, verify that frames actually exist and can be decoded.

python
1from pathlib import Path
2
3frame_files = sorted(Path("frames").glob("*.jpg"))
4print("count:", len(frame_files))
5print("first:", frame_files[0] if frame_files else "none")

For larger pipelines, add image-read checks or checksums so silent corruption is caught early.

When FFmpeg Is Better

If the job is simple bulk extraction with no Python-side frame logic, FFmpeg is often faster than OpenCV.

Extract all frames:

bash
ffmpeg -i input.mp4 frames/frame_%06d.jpg

Extract one frame per second:

bash
ffmpeg -i input.mp4 -vf fps=1 frames/frame_%06d.jpg

OpenCV is better when your extraction condition depends on frame content or custom processing. FFmpeg is better when you just need fast mechanical extraction.

Common Pitfalls

The most common mistake is ignoring storage costs. A long HD video can produce an unexpectedly large number of frame files.

Another issue is failing to release VideoCapture, especially in scripts that process many videos in one run. That can leave resources open and cause later reads to fail.

Developers also often trust FPS metadata without verifying it. If the video reports incorrect FPS, time-based sampling will be wrong.

Summary

  • Use OpenCV when frame extraction needs programmatic control.
  • Save every Nth frame instead of every frame when storage matters.
  • Use zero-padded filenames and one folder per input video.
  • Validate frame counts and output readability after extraction.
  • Consider FFmpeg when the job is simple bulk extraction rather than frame-by-frame Python logic.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.