1. Introduction
“Video is the closest thing we have to teleportation.” – Steve Jobs once said that about FaceTime, but in the world of AI and Data Science, video processing is what bridges raw visual data to intelligent automation.
Why Video Processing Matters
I’ve worked with video data in multiple real-world applications—whether it was training AI models for autonomous vehicles or optimizing surveillance footage for motion detection. Video isn’t just a sequence of images; it’s a high-dimensional data stream that requires careful handling.
Here’s the thing: If you’re dealing with object detection, tracking, action recognition, or even simple video preprocessing for deep learning models, you need a reliable way to read, modify, and write video files efficiently. And that’s where OpenCV VideoWriter comes in.
What This Guide Covers
This isn’t going to be one of those “hello world” style tutorials. I’m skipping the fluff and jumping straight into practical applications of OpenCV VideoWriter—the how, why, and what of writing videos using Python.
Here’s what you’ll learn:
✔️ How to set up and use OpenCV VideoWriter like a pro
✔️ The best codecs and formats for speed vs. quality trade-offs
✔️ Advanced techniques like adding overlays, timestamps, and multi-threading for performance
If you’ve ever struggled with incorrect frame sizes, codec mismatches, or massive file sizes, I’ve been there too. This guide will walk you through every challenge and solution I’ve discovered over time.
2. Prerequisites
Before we start, let’s make sure your setup is ready. You don’t want to troubleshoot dependency issues while deep into the code.
Installing Dependencies
Here’s the minimal setup you need:
pip install opencv-python numpy
That’s it. No need for OpenCV-contrib unless you’re using advanced modules.
Understanding Codecs & Formats
Now, let’s talk codecs. If you’ve ever saved a video and noticed weird artifacts, incorrect colors, or absurdly large file sizes, chances are you picked the wrong codec.
Lossy vs. Lossless Codecs
- Lossy (H.264, VP9, MPEG-4) → Great for reducing file size, but at the cost of slight quality loss.
- Lossless (FFV1, HuffYUV, Lagarith) → Maintains perfect quality but results in massive files.
From my experience, H.264 (AVC) is your best bet for a balance between quality and compression. If you need extreme compression while maintaining decent quality, H.265 (HEVC) is worth exploring.
Choosing the Right Video Format (.avi, .mp4, .mov, etc.)
The file format isn’t just a name—it dictates how your video is stored and played across different platforms.
Format | Best For | Drawbacks |
---|---|---|
AVI | High quality, lossless encoding | Huge file sizes |
MP4 | Best for web and storage efficiency | May have compression artifacts |
MOV | High-quality Apple-friendly format | Not as widely supported as MP4 |
💡 Pro Tip: If you’re writing videos for deep learning applications, stick to MP4 with H.264—it’s widely supported and compresses well without much loss.
GPU-Accelerated Encoding (H.264, H.265)
This is where things get really interesting. If you’re dealing with high-resolution videos (1080p, 4K), software encoding will choke your CPU. Instead, you can offload encoding to your GPU using FFmpeg with OpenCV:
fourcc = cv2.VideoWriter_fourcc(*'H264') # Hardware-accelerated encoding
out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (1280, 720))
If you have an NVIDIA GPU, you can supercharge encoding with NVENC (NVIDIA Encoder):
ffmpeg -hwaccel nvdec -i input.mp4 -c:v h264_nvenc output.mp4
This can speed up encoding 10x compared to CPU-based encoding.
3. OpenCV VideoWriter – Quick Setup
“If you can’t explain it simply, you don’t understand it well enough.” – Einstein’s words apply to video processing too. If you’ve ever struggled to save videos in OpenCV, I’ve been there. But once you understand how VideoWriter works, it’s actually pretty straightforward.
Basic Usage – Creating a Simple Video from Images
Let’s start with the bare minimum—writing a video from randomly generated frames.
import cv2
import numpy as np
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID') # 'XVID' codec for AVI files
out = cv2.VideoWriter('output.avi', fourcc, 30.0, (640, 480))
# Generate 100 random frames and write to video
for i in range(100):
frame = np.random.randint(0, 256, (480, 640, 3), dtype=np.uint8) # Random noise frame
out.write(frame)
out.release()
cv2.destroyAllWindows()
Breaking it Down:
✅ VideoWriter_fourcc(*'XVID')
– Defines the codec (XVID for AVI).
✅ VideoWriter('output.avi', fourcc, 30.0, (640, 480))
– Creates a video file with 30 FPS and 640×480 resolution.
✅ The loop generates 100 random frames and writes them to the file.
At this point, you should have a random noise video saved as output.avi
. It’s not pretty, but it proves that VideoWriter is working.
Common Pitfalls & Debugging
Here’s where most people mess up (and trust me, I’ve made these mistakes myself):
❌ Video not saving?
- Double-check that frame size in
VideoWriter
exactly matches the frame you’re writing. - AVI format may require XVID or MJPG codecs, while MP4 often needs MP4V.
❌ Codec issues?
- Try different
fourcc
codes:
fourcc = cv2.VideoWriter_fourcc(*'MJPG') # Another common codec
- If
MP4V
doesn’t work for.mp4
, useH264
(requires FFmpeg).
❌ Huge file size?
- Switch to H.264 or H.265 for better compression.
- Lower FPS if your application doesn’t need ultra-smooth playback.
4. Advanced Video Writing Techniques
Now that we have the basics down, let’s get into real-world applications.
Recording from a Webcam & Writing to a File
I’ve often needed to capture live video and save it in real-time—whether for data collection, surveillance, or just debugging. Here’s how you can do it:
import cv2
cap = cv2.VideoCapture(0) # Open default webcam
fourcc = cv2.VideoWriter_fourcc(*'MP4V') # MP4 codec
out = cv2.VideoWriter('webcam_output.mp4', fourcc, 30.0, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break # Stop if no frame is captured
out.write(frame) # Save frame to file
cv2.imshow('Webcam', frame) # Display video in real-time
if cv2.waitKey(1) & 0xFF == ord('q'): # Press 'q' to exit
break
cap.release()
out.release()
cv2.destroyAllWindows()
What’s Happening Here?
cv2.VideoCapture(0)
opens your default webcam.while cap.isOpened()
keeps reading frames.- Frames are saved using VideoWriter and also displayed live.
- Pressing ‘q’ exits the loop.
⚡ Performance Tip: If you’re writing high-resolution videos, consider running frame capture and video writing in separate threads to avoid frame drops.
Adding Text, Overlays & Time Stamps
Here’s where we can get a bit creative. If you’re saving videos for analytics, security footage, or AI training data, adding metadata is a game-changer.
Let’s overlay text on the frames before saving:
import cv2
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
out = cv2.VideoWriter('annotated_output.mp4', fourcc, 30.0, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Get current timestamp
timestamp = cv2.getTextSize('Timestamp', cv2.FONT_HERSHEY_SIMPLEX, 1, 2)[0]
# Add text overlay
frame = cv2.putText(frame, 'OpenCV VideoWriter', (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
frame = cv2.putText(frame, f'Time: {cv2.getTickCount()}', (50, 100),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 2)
out.write(frame)
cv2.imshow('Webcam with Overlay', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
Pro Tip: Instead of cv2.getTickCount()
, you can use datetime.now()
from Python’s datetime module for an actual timestamp.
Resizing & Converting Color Formats Before Writing
I’ve run into situations where I needed to save grayscale videos or resize frames before writing. If you’re processing high-resolution videos, this can save a lot of storage space.
frame_resized = cv2.resize(frame, (1280, 720)) # Resize to HD
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Convert to grayscale
And if you want to write a grayscale video, remember to update your VideoWriter
:
out = cv2.VideoWriter('gray_output.avi', fourcc, 30.0, (640, 480), isColor=False)
5. Optimizing Video Writing Performance
“Fast is fine, but accuracy is everything.” – Wyatt Earp said this about gunfights, but it applies just as well to video processing. I’ve lost count of the times I’ve struggled with frame drops, lag, and massive file sizes when writing videos in OpenCV. The good news? There are some powerful optimizations you can use to fix these issues.
Let’s go beyond the basics and squeeze every last bit of performance out of OpenCV’s VideoWriter.
Multi-threading with OpenCV Video Capture & Write
Here’s the deal: capturing and writing video frames happen sequentially in most scripts. This means that if your writing process is slow, frames get delayed, leading to laggy or choppy videos. The fix? Multi-threading.
Single-threaded approach (Slow & Inefficient)
This is how most people do it, but it’s not ideal:
import cv2
cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('slow_output.avi', fourcc, 30.0, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
out.write(frame) # Writing happens in the same thread
cv2.imshow('Frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
❌ The Problem:
- Frame Capture & Writing happen in the same thread → If disk writing is slow, frames start buffering, causing lag or dropped frames.
Multi-threaded approach (Faster & Smoother)
I’ve personally used this in real-time video analytics projects, and the difference is night and day.
import cv2
import threading
import queue
frame_queue = queue.Queue()
def writer():
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('fast_output.avi', fourcc, 30.0, (640, 480))
while True:
frame = frame_queue.get()
if frame is None:
break
out.write(frame)
out.release()
cap = cv2.VideoCapture(0)
threading.Thread(target=writer, daemon=True).start()
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
frame_queue.put(frame) # Push frames into the queue
cv2.imshow('Frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
frame_queue.put(None) # Stop signal for the writer thread
cap.release()
cv2.destroyAllWindows()
✔️ Multi-threading decouples frame capture and writing → Smoother video, no dropped frames!
✔️ Ideal for high-resolution or high-FPS recording.
Writing Video in Chunks to Prevent Memory Overflow
If you’re recording long-duration videos, writing everything into a single file can lead to corruption if something crashes mid-way. I’ve learned this the hard way when hours of data were lost because the process crashed. The fix? Save in smaller chunks.
import cv2
import time
cap = cv2.VideoCapture(0)
chunk_duration = 60 # Save a new file every 60 seconds
start_time = time.time()
file_index = 1
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(f'output_{file_index}.avi', fourcc, 30.0, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
if time.time() - start_time > chunk_duration:
out.release()
file_index += 1
out = cv2.VideoWriter(f'output_{file_index}.avi', fourcc, 30.0, (640, 480))
start_time = time.time()
out.write(frame)
cv2.imshow('Frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
✔️ Creates multiple video files instead of one massive file.
✔️ Prevents data loss if a crash happens.
✔️ Works great for long-term surveillance, sports recording, or time-lapse videos.
Using GPU Acceleration with FFmpeg & OpenCV
Most people ignore hardware acceleration and end up with sluggish video processing. I’ve optimized video pipelines using FFmpeg with OpenCV, and the difference is like going from a bicycle to a sports car.
First, make sure FFmpeg is installed. Then, use H.264 (GPU-accelerated) encoding:
fourcc = cv2.VideoWriter_fourcc(*'H264') # Requires FFmpeg installed
out = cv2.VideoWriter('gpu_output.mp4', fourcc, 30.0, (1280, 720))
Why H.264?
✔️ 10x smaller file size than raw AVI.
✔️ Better compression without losing quality.
✔️ GPU-accelerated encoding (if supported).
⚡ Want even more speed? Use NVIDIA NVENC or Intel Quick Sync Video (QSV) for real-time encoding.
Choosing the Right Codec for Speed vs Quality Trade-offs
Different codecs have different strengths, and choosing the wrong one can kill performance or bloat file sizes. Here’s my go-to reference:
Codec | Pros | Cons |
---|---|---|
XVID (AVI) | Fast, widely supported | Large file size |
MJPG (AVI) | High quality, less compression | Large file size |
H.264 (MP4) | Best compression, small size, GPU-accelerated | Needs FFmpeg |
H.265 (MP4) | Even better compression | Slower encoding |
Rule of thumb:
👉 Fastest writing → MJPG
👉 Best compression → H.264
👉 Best for low bandwidth → H.265
Conclusion
We’ve covered a lot—from basic VideoWriter usage to multi-threading, chunk-based writing, and GPU acceleration. If you’ve ever struggled with slow, laggy, or oversized videos, these optimizations will make a huge difference.
Final Thoughts & Best Practices
✅ Use multi-threading to separate capture and writing.
✅ Write in chunks to avoid file corruption.
✅ Leverage hardware acceleration for H.264 encoding.
✅ Choose the right codec for your use case.
Further Reading

I’m a Data Scientist.