simple, lightweight video surveillance application
Go to file
zii e72feb40ee server 1.2:
- removed -r command line option and renamed it to -s. then
   added -l as what -s used to be.

 - added detect_uri option to camera parameters so stream
   snapshots can now run a secondary stream that differs
   from the recording stream. also added sync logic so the
   recording loop and detection loop will run synchronously
   while still running in seperate threads.

 - live_secs renamed to live_mins. the amount of live
   footage to buffer in buffer_path is now based on minutes
   instead of seconds.

 - added live_clip_secs parameter so the amount of seconds
   each hls video clip should have is now adjustable.

 - remove max_event_secs. events are now transfered to
   rec_path based on minute increments.

 - added sec_per_image to make the amount of seconds
   between stream snapshots pulled from detect_uri
   adjustable.

 - added img_ext so the image snapshot format from
   detect_uri and then ultimately to img_comp_cmd can now
   be configured instead of being hardcoded to bmp.

 - added gray_image as a boolean parameter so the snapshots
   from detect_uri can be pulled in grayscale format or
   remain in color if desired.

 - removed img_scale since this parameter was not doing
   anything.

overview:

   use of QFileSystemWatcher on the detection loop has
   been eliminated and thus eliminated use of functions
   such as listFacingFiles(), backwardFacingFiles() and
   forwardFacingFiles(). Instead, the detection and
   recording loops will now run synchronously and use
   predictable up-to-the-minute file naming scheme.

client v1.1:

 - the build script will now include all imageformat
   plugins from the QT lib directory, adding support for
   jpg, svg, ico and gif image formats.

 - switched to 2 number versioning.

 - this client app will now support the server's new
   up-to-the-minute directory structure for live and
   recorded footage.

 - the version number is now be displayed on the main
   interface.
2025-10-11 08:05:51 -04:00
client server 1.2: 2025-10-11 08:05:51 -04:00
server server 1.2: 2025-10-11 08:05:51 -04:00
.gitignore v1.0 2025-06-26 12:06:41 -04:00
build.py v1.0 2025-06-26 12:06:41 -04:00
install.py v1.0 2025-06-26 12:06:41 -04:00
LICENSE.md v1.0 2025-06-26 12:06:41 -04:00
README.md server 1.2: 2025-10-11 08:05:51 -04:00

JustMotion

JustMotion is a simple, lightweight video surveillance application utilizing the server-client model that doesn't try to re-invent the wheel. The source code for both server and client are available in this repository and can be compliled and/or installed separately.

JustMotion-Server

JustMotion-Server is the server portion of this appication that monitors the video feeds of any IP or local cameras and records footage that contains motion to permanent storage. The main advantage of this is reduced storage requirements as opposed to continuous recording because only video footage of interest is kept in storage.

The server implements the principle of doing the least as needed. As a result it is extremely lightweight with the fact it doesn't attempt to re-implement much of it's functions internally but will instead rely on external applications that already implement the functions very well.

It doesn't have a builtin user interface so instead external applications are more than welcome to interface with the buffer/footage directories to implement a user interface of any flavor.

JustMotion-Client

JustMotion-Client is the client portion of this application that actually implement a user interface. Utilizing the same principle of doing the least as needed, it uses an external video player to play m3u8 playlist files located at the server's buffer/footage directories. It mounts the server as an ssh filesystem to access such directories so no need to open any addtional ports if your server already has working ssh access.

Usage (server)

Usage: jmotion <argument>

-h : display usage information about this application.
-d : all valid config files found in /etc/jmotion will be used to
     create camera instances. (this is blocking, meant to run with systemd)
-v : display the current version.
-u : uninstall the entire server from your system, including the service. all
     recorded footage and config files will remain.
-f : force an action without pausing for user confirmation.
-l : view the status of all camera instances.
-q : kill all camera instances.
-s : same as -d except it is non-blocking for starting all camera instances
     via systemd. same as 'sudo systemctl start jmotion'

Config File (server)

The config file is a simple text file that contain parameters that dictate the behavior of the server for each camera located in the /etc/jmotion directory.

# Motion Watch config file
#
# note all lines in this config file that starts with a '#' are ignored.
# also note to avoid using empty lines. if you're going to need an empty
# line, start it with a '#'
#
recording_uri = rtsp://1.2.3.4:554/h264
# this is the uri to the main stream of the IP camera that will be used
# to record footage. it can be a url to an rtsp stream or a direct device
# path such as /dev/video0.
#
detect_uri = rtsp://1.2.3.4:554/h264cif
# this is the uri to the secondary stream of the IP camera that will be
# used to take image snapshots that will be used with img_comp_cmd to
# detect any events of intrest. it can be a url to an rtsp stream or a 
# direct device path such as /dev/video0. If the camera doesn't have a
# secondary stream, you can just use the same as recording_uri.
#
buffer_path = /tmp/jmotion
# this is the work directory the app will use to store live footage and
# image frames. it's recommended to use a ram disk for this since there
# will be large amounts of io occuring here. 1GB of space per camera is
# a good rule of thumb.
#
rec_path = /var/jmotion/footage
# this is video output directory that will be used to store any footage
# that contain any detected events.
#
live_mins = 60
# this is the maximum amount minutes worth of live video clips to record 
# to the buffer_path before deleting the oldest video clips. values less
# than 1 is considered invalid and will cause the app to default to 60.
#
live_clip_secs = 5
# this is the amount of seconds each video clip recorded from recording_uri
# can be. values between 1-59 are valid. anything outside of that range will
# cause the app to default to 5. 
#
cam_name = cam-1
# this is the optional camera name parameter to identify the camera. this
# name will also be used as the base directory in buffer_path and rec_path. 
# if not defined, the name of the config file will be used.
#
max_events_bytes = 10G
# this is the maximum amount of disk space of video footage that can be 
# recorded in the rec_path directory.
#
img_comp_cmd = compare -metric FUZZ &prev& &next& /dev/null
# this is the command line template this application will use when calling 
# the external image comparison application. the external application is
# expected to compare snapshots from the video stream to determine how 
# different the images are from each other. it needs to output a numeric 
# score with the higher values meaning very different while low values 
# mean similar images. magick is the default if not defined in the config 
# file. this parameter can also be set to 'null' as a means to turn off 
# motion/event detection.
#
sec_per_image = 4
# this is the amount of seconds between video stream snap shots to take 
# from detect_uri that will then be passed on to img_comp_cmd via the &prev&
# and &next& parameters. values between 1-59 are valid. anything outside of 
# that range will cause the app to default to 4.
# 
img_comp_out = stderr
# this is the standard output stream the app defined in img_comp_cmd will
# use to output the comparison score. this can only be stderr or stdout,
# any other stream name is considered invalid. it will default to 'stderr'
# if the parameter is invalid.
#
vid_codec = copy
# this is the encoding codec to use when recording footage from the camera. 
# the list of supported codecs entirely depend on the hosts' ffmpeg 
# installation. run 'ffmpeg -codecs' to determine this list. if not 
# defined, 'copy' will be used as in it will just copy the codec format 
# from the camera itself without re-encoding.
#
aud_codec = copy
# this is the audio encoding codec to use when recording from the camera.
# the list of supported audio codes can be determined by running 'ffmpeg
# -codecs' on the host machine. if not defined, 'copy' will be used as in
# it will directly copy the audio stream from the camera if present.
#
stream_ext = .mkv
# this is the file extension that will be used to when recording footage
# from the camera in buffer_path. ffmpeg will also use this to determine 
# what format container to use for the video clips.
#
img_ext = .jpg
# this is the file extension that will be used with detect_uri to take 
# snapshots of the video stream. make sure the app defined in img_comp_cmd
# supports the image format defined here.
#
thumbnail_ext = .jpg
# this the image format that will be used when creating the thumbnails
# for the videos clips recorded to rec_path.
#
rec_ext = .mkv
# this the the file extension that will be used when storing motion footage 
# to rec_path. ffmpeg will also use this to determine what format container 
# to use for the video clips. 
#
img_thresh = 8000
# this parameter defines the score threshold from img_comp_cmd that will
# be considered an event of any kind. any video clips found with events
# are queued up to be copied to rec_path.
#
gray_image = y
# this is a boolean 'y' or 'n' parameter that enables or disable grayscale
# color formatting for the images pulled from the camera stream via the
# detect_uri. recommend turning this off if the img_comp_cmd already does
# this internally.
#
post_secs = 60
# this is the amount of seconds to wait before running the command 
# defined in post_cmd. the command will not run if an event was detected 
# in the space before post_secs elapsed.
#
post_cmd = move_the_ptz_camera.py
# this an optional command to run with post_secs. one great use for this
# is to move a ptz camera to the next position of it's patrol pattern.
# note: the call to this command will be delayed if an event was detected.
# also, event detection is paused while this command is running.
#
rec_fps = 30
# this sets the recording frames per second for the footage recorded 
# from the camera. this has no affect if using 'copy' as the vid_codec.
#
rec_scale = 1280:720
# this sets the pixel scale of the recorded footage from the camera. it
# uses width, height numeric strings seperated by a colon, eg W:H. this
# has no affect of using 'copy' as the vid_codec.
#

Build/Install

This application is currently only compatible with a Linux based operating systems that are capable of installing python3 and the QT API (QT6.X.X or better).

./build.py    <--run this first
./install.py  <--run this next
note 1: the build script will search for the QT api installed in your 
        system. if not found, it will ask you where it is. either way
        it is recommended to install the QT API before running this
        script.
note 2: both scripts assume python3 is already installed.