Motion
Lightweight motion-detection video surveillance daemon
Motion is a program that monitors video signals from cameras and detects movement. It can record video, capture snapshots, and trigger external scripts when motion is detected, all with a small footprint.
Key features
- Motion detection
- Snapshot and video capture
- External script triggers
- Very low resource use
Pros & cons
Strengths
- Tiny footprint
- Highly scriptable
Trade-offs
- No built-in web UI
- Configuration via files
Motion replaces
Last reviewed Sep 13, 2026 · 803 words
Motion watches a camera, decides whether pixels changed, and then does whatever you told it to do: save a JPEG, write an MP4, run a shell script. It has been doing this since 2000, which means most of the friendlier surveillance software you will meet, motionEye included, is a coat of paint over it. Running Motion directly makes sense when you have 1 to 4 cameras, a weak machine, and a specific reaction in mind for each event. It makes no sense if you want a dashboard, because there is not one.
Configuration is a text file and that is the whole interface
The install on Debian, Ubuntu or Raspberry Pi OS is apt install motion. Everything after that happens in /etc/motion/motion.conf, with optional per-camera files. The dozen settings that matter:
netcam_url rtsp://user:[email protected]:554/stream2
framerate 5
threshold 1500
minimum_motion_frames 2
event_gap 30
target_dir /var/lib/motion
picture_output best
movie_output on
movie_max_time 120
stream_port 8081
webcontrol_port 8080
threshold is the number of changed pixels that counts as motion; 1500 is the default and is too sensitive for an outdoor camera with trees. event_gap is how many quiet seconds end an event. framerate 5 on a substream, not the 4K main stream, is what keeps CPU usage sane. Motion decodes every frame it analyses, so a 1080p 25 fps stream on a Raspberry Pi 4 saturates a core, while a 640x360 substream at 5 fps idles at a few percent.
There is a raw MJPEG stream on 8081 and a bare-bones control page on 8080. Neither is a UI in any modern sense; they exist so other software can consume them. Bind both to localhost unless you enjoy unauthenticated camera feeds on your LAN.
Scripts are why people still choose it
Every stage of an event has a hook: on_event_start, on_event_end, on_picture_save, on_movie_end, on_camera_lost. Each takes a command with substitution variables for the file path, camera number and timestamp. This is the feature that has kept Motion relevant against prettier tools. Some real examples from installs I have run or seen:
on_event_start curl -s -X POST http://homeassistant:8123/api/webhook/driveway_motion
on_movie_end rclone move %f b2:cameras/driveway/
on_picture_save /usr/local/bin/notify.sh %f
The first turns motion into a Home Assistant trigger without any integration code. The second ships clips off-site the second they finish. Nothing else in this category makes that as direct: with Motion the reaction is a line in a file, not a plugin.
It sees motion, not objects
Motion's detection is pixel difference with masking and noise filtering. It cannot tell a cat from a courier from a headlight sweep. You mitigate with mask_file to blank out the road and the trees, despeckle_filter, and a higher minimum_motion_frames, and you still get false positives in rain and at dusk. If the events you care about are "a person is at the door", that is object detection, and Frigate does it with a Coral or a GPU while consuming far more of everything. Frigate is the bigger, safer project for anyone starting fresh with more than a couple of cameras; Motion is the tool for people who know exactly what they want it to do and want it to cost 256 MB of RAM.
Storage fills up on schedule
Motion never deletes anything. movie_max_time 120 caps clip length but not disk. Plan a cron job from day one:
find /var/lib/motion -type f -mtime +14 -delete
Use picture_output best rather than on unless you want a JPEG per frame, which is how a 32 GB SD card dies in a fortnight. Writing to an SD card at all is the other slow killer on a Pi; point target_dir at a USB SSD or an NFS share.
Docker is fine, bare metal is better here
Motion is packaged in every major distro and has near-zero dependencies, so containerising it buys little and costs you device passthrough for USB webcams. For IP cameras over RTSP either works. On bare metal the systemd unit ships with the package; systemctl enable --now motion and you are running.
What I'd do
For one or two RTSP cameras on a Pi or a small VM where the goal is "record clips and poke a webhook", Motion on bare metal with a substream, a mask file, a 14-day cleanup cron, and on_event_start pointing at Home Assistant. If you want to click on things, put motionEye over it: same engine, tolerable UI. If you want to know whether the thing that moved was a person, skip both and set up Frigate, because no amount of threshold tuning gets pixel differencing there. The rest of the category is in video surveillance.
Compare Motion
10 head-to-head comparisons.
Similar video surveillance apps
MediaMTX
Video SurveillanceReady-to-use media server and RTSP/WebRTC proxy
Replaces Wowza
go2rtc
Video SurveillanceUltimate camera streaming gateway with low latency
Replaces Nest Cam
OpenALPR
Video SurveillanceAutomatic license plate recognition library
Replaces Rekor Scout, Plate Recognizer
CompreFace
Video SurveillanceSelf-hosted face recognition service with REST API
Replaces Amazon Rekognition
OpenCvSharp
Video Surveillance.NET wrapper for OpenCV computer vision
Replaces Commercial vision SDKs
ZoneMinder
Video SurveillanceFull-featured closed-circuit television software suite
Replaces Blue Iris, Milestone XProtect