Ever found yourself with gigabytes of security camera footage and wondered if anything actually happened? If you're working with MJPEG stream files from IP cameras or surveillance systems, manually reviewing hours of footage is tedious and time-consuming. In this guide, I'll show you how to automate motion detection using a powerful bash script that extracts only the moments that matter.
The Problem with MJPEG Streams
MJPEG (Motion JPEG) streams are commonly used by security cameras and IP cameras. Unlike traditional video formats, MJPEG stores each frame as a separate JPEG image within a single file. While this format is simple and widely supported, it creates unique challenges:
- Massive file sizes: An hour of footage can easily exceed 1GB
- Difficult to analyze: Standard video tools may not recognize the format
- Time-consuming review: Scrubbing through hours of mostly static footage is impractical
The solution? Automated motion detection that extracts only the sequences where something actually happens.
How the Motion Detection Script Works
The script I've developed performs three key operations:
- Frame Extraction: Converts MJPEG streams into individual JPEG frames at your specified frame rate
- Motion Analysis: Compares consecutive frames to detect pixel changes using FFmpeg's sophisticated difference algorithms
- Sequence Generation: Bundles detected motion into separate video files and GIFs for easy review
Prerequisites
Before getting started, ensure you have FFmpeg installed on your Ubuntu system:
sudo apt update
sudo apt install ffmpeg
That's it! The script is pure bash with FFmpeg doing the heavy lifting.
Using the Script
Basic Usage
The simplest way to run the script is by navigating to your directory containing MJPEG files (named in HHMM-HHMM.jpeg format like 1045-1100.jpeg) and running:
./mjpeg_exctract_detected_motions.sh
This uses default settings:
- Motion threshold: 5% pixel change
- Minimum sequence length: 5 frames
- Extraction rate: 1 frame per second
Custom Parameters
The script accepts five parameters for fine-tuned control:
./mjpeg_exctract_detected_motions.sh [input_dir] [output_dir] [threshold] [min_frames] [fps]
Example 1: Process files in the current directory with a higher motion threshold:
./mjpeg_exctract_detected_motions.sh . motion_results 10 3 1
This sets:
- Input: Current directory (
.) - Output:
motion_resultsfolder - Threshold: 10% (less sensitive, catches bigger movements)
- Minimum sequence: 3 frames
- Extraction: 1 FPS
Example 2: High-sensitivity detection for subtle movements:
./mjpeg_exctract_detected_motions.sh /path/to/streams output 3 5 2
This configuration:
- Extracts 2 frames per second (more granular)
- Detects movements affecting just 3% of pixels
- Requires 5 consecutive frames to qualify as a sequence
Understanding the Output
After processing, you'll find several items in your output directory:
Directory Structure
motion_sequences/
├── extracted_frames/ # All individual frames
│ ├── frame_1004-1014_000001.jpg
│ ├── frame_1004-1014_000002.jpg
│ └── ...
├── sequence_1/ # Frames with motion detected
│ ├── frame_1004-1014_000023.jpg
│ └── ...
├── sequence_1.mp4 # Video compilation
├── sequence_1.gif # Animated preview
└── sequence_2.mp4
Video Files
Each detected motion sequence is compiled into an MP4 file playing at 2 FPS, making it easy to review what triggered the detection.
GIF Previews
Preview GIFs (480px width) let you quickly scan through sequences without opening video files.
Tuning Motion Detection
Getting optimal results depends on your specific use case:
For Busy Streets
- Threshold: 10-20%
- Min frames: 5-10
- FPS: 1
This filters out minor movements like swaying trees and focuses on people or vehicles.
For Indoor Monitoring
- Threshold: 3-8%
- Min frames: 3-5
- FPS: 2
More sensitive settings catch smaller movements in controlled environments.
For Wildlife Cameras
- Threshold: 5-15%
- Min frames: 3-7
- FPS: 0.5
Lower extraction rate saves processing time while still capturing animal activity.
Performance Considerations
Processing large MJPEG streams is resource-intensive. Here's what to expect:
- 1GB file: Approximately 5-10 minutes on a modern CPU
- Disk space: Extracted frames require 2-3x the original file size temporarily
- Memory: Minimal impact, FFmpeg handles streaming efficiently
The script automatically cleans up temporary files after processing.
Advanced Tips
Batch Processing Multiple Days
Create a simple loop to process multiple directories:
for dir in /media/recordings/2024-*/; do
./mjpeg_exctract_detected_motions.sh "$dir" "${dir}/motion_detected" 8 5 1
done
Skip Frame Extraction (Reprocessing)
If you've already extracted frames and want to adjust detection parameters, modify the script to skip Step 1 and reuse existing frames.
Custom FFmpeg Filters
For specialized scenarios (night vision, specific areas of interest), you can modify the FFmpeg filter chain around line 98 to add:
- Brightness normalization
- Region-of-interest masking
- Noise reduction
Troubleshooting
"Not a JPEG file" error: Your files are MJPEG streams, which is correct. The script handles this automatically.
No motion detected: Try lowering the threshold or check if your camera is capturing significant pixel changes.
Out of disk space: The script needs temporary space equal to 2-3x your input file size.
Conclusion
Automated motion detection transforms how you work with surveillance footage. Instead of reviewing hours of static images, you get condensed clips of actual events. Whether you're monitoring a storefront, tracking wildlife, or analyzing traffic patterns, this script saves time and storage space.
The best part? It's completely free, open-source, and runs on any Linux system with FFmpeg. No cloud services, no subscription fees, just efficient local processing.
Download the script, adjust the parameters to your needs, and let automation handle the tedious work of finding what matters in your MJPEG streams.
The source code is available at GitHub
Bash Script GitHub Download
Follow my work on GitHub!
Need an Android Developer or a full-stack website developer?
I specialize in Kotlin, Jetpack Compose, and Material Design 3. For websites, I use modern web technologies to create responsive and user-friendly experiences. Check out my portfolio or get in touch to discuss your project.


