Skip to content

Instantly share code, notes, and snippets.

@plembo
Last active November 6, 2024 18:56
Show Gist options
  • Save plembo/2ab5ff9fbb8cf8aea5966eb25448412f to your computer and use it in GitHub Desktop.
Save plembo/2ab5ff9fbb8cf8aea5966eb25448412f to your computer and use it in GitHub Desktop.
Motioneye for home security

Motioneye for home security

NOTE: This is an old post. After moving on from motion to the docker-wyze-bridge with podman and a systemd user service, newer, incompatible Wyze hardware sent me down the path of replacing Wyze altogether. I'm still on track to do that next year (2025). Ultimately, the closed, proprietary nature of everything in the security camera space will probably lead me to just rely on some motion sensors and a backyard nature cam.

OK, so the "home security" part is probably overdone, but lately I've been experimenting with motioneye as the motion capture backend to the small flotilla of wifi cameras we have outside. All but one are Wyze v2 models, not rated for the outdoors but doing well in spite of that. Up until recently I largely relied on Wyze's own motion capture and cloud (AWS) storage arrangement, but decided moving to my own infrastructure would make the basis for a nice data science project. That, and the fact that eventually Wyze will stop supporting these cameras or disappear to leave me to cobble together a solution in a hurry. Ten years later, the abandonment by Seagate of that great little media box they used to sell still darkens my attitude towards IoT devices.

I've deployed motion (the base for motioneye) on Linux servers before, and found it to be frustratingly underdocumented and time consuming. The best experience was running motioneye OS on a Pi, but over the last couple of years I've been trying to consolidate as many services as possible on the home file server. This is a Ubuntu Server box with a first gen 6-core, 12-thread Ryzen CPU, 32 GB RAM and 6 TB of spinning rust. The O/S loads from a small SSD, and it's overall a good performer.

This time around I decided to use the handy motioneye docker container published by motioneye's maintainer himself. That's worked out well for me, so the rest of this note will consist of a script and some config files that I hope others will find helpful. High CPU utilization and bandwidth consumption on the LAN continue to be a thing, even with this setup.

First, the script I use to for my initial instantiation of motioneye on docker:

#!/bin/bash
# Install and run motioneye in docker
docker volume create motioneye_config

docker run -d \
 --name motioneye \
 --hostname motioneye \
 -p 8765:8765 \
 -p 8281-8285:8281-8285 \
 -v /etc/localtime:/etc/localtime:ro \
 -v /data3/cameras:/var/lib/motioneye \
 -v motioneye_config:/etc/motioneye \
 -v motioneye_run:/var/run/motioneye \
 -v motioneye_run:/var/run/motion \
 --restart unless-stopped \
ccrisan/motioneye:python3-amd64

In the above "/data3" is a mountpoint to one of the ext4 disks on my file server.

This is the nginx proxy config for "https://cameras.example.com", that serves as the frontend for viewing live streams and configuring the motioneye service:

server {
    listen 80;
    # listen [::]:80;
    server_name cameras.example.com;
    access_log /data1/logs/nginx/cameras-access.log;
    error_log /data1/logs/nginx/cameras-error.log;
    root /data1/www/html;
    index index.html;
    location / {
        proxy_pass http://localhost:8765/;
    }
    return 307 https://$host$request_uri;
}
server {
    listen 443 ssl;
    # listen [::]:443 ssl;
    server_name cameras.example.com;
    access_log /data1/logs/nginx/cameras-access.log;
    error_log /data1/logs/nginx/cameras-error.log;
    ssl_certificate /etc/ssl/certs/_.example.com-chained.crt;
    ssl_certificate_key /etc/ssl/private/_.example.com.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;
    root /data1/www/html;
    index index.html;
    location / {
        proxy_pass http://localhost:8765/;
    }

}

Here again, "/data1" is a mountpoint for an ext4 disk. I use letsencrypt to maintain wildcard SSL certs for my internal network, which show up here with the "_.example.com" prefix.

Following is one of the camera-specific configuration files. In my setup these are all identical except for the camera hostnames:

# @enabled on
# @id 1
# @storage_device custom-path
# @network_server 
# @network_share_name 
# @network_smb_ver 1.0
# @network_username 
# @network_password 
# @upload_enabled off
# @upload_picture on
# @upload_movie on
# @upload_service ftp
# @upload_server 
# @upload_port 
# @upload_method post
# @upload_location 
# @upload_subfolders on
# @upload_username 
# @upload_password 
# @clean_cloud_enabled off
# @webcam_resolution 100
# @webcam_server_resize off
# @motion_detection on
# @preserve_pictures 1
# @manual_snapshots on
# @preserve_movies 1
# @manual_record off
# @working_schedule 
# @working_schedule_type outside


netcam_url rtsp://webcam1.casalembo.com:554/live
netcam_userpass motion:xxxxxxxxxxxxxxxxx
netcam_keepalive off
netcam_tolerant_check on
width 800
height 480
camera_name Camera1
auto_brightness on
framerate 5
rotate 0
target_dir /var/lib/motioneye/Camera1
stream_localhost off
stream_port 8281
stream_maxrate 10
stream_quality 85
stream_motion off
stream_auth_method 0
text_left 
text_right 
text_scale 1
text_changes off
locate_motion_mode off
locate_motion_style redbox
threshold 6000
threshold_maximum 0
threshold_tune off
noise_tune off
noise_level 31
lightswitch_percent 0
despeckle_filter EedDl
minimum_motion_frames 2
smart_mask_speed 9
mask_file 
movie_output_motion off
picture_output_motion off
pre_capture 1
post_capture 60
picture_output best
picture_filename %Y-%m-%d/%H-%M-%S
emulate_motion off
event_gap 10
snapshot_interval 0
snapshot_filename %Y-%m-%d/%H-%M-%S
picture_quality 85
movie_filename %Y-%m-%d/%H-%M-%S
movie_max_time 0
movie_output on
movie_passthrough on
movie_codec mp4:h264_omx
movie_quality 75
on_event_start /usr/local/lib/python3.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" start %t
on_event_end /usr/local/lib/python3.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" stop %t
on_movie_end /usr/local/lib/python3.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" movie_end %t %f
on_picture_save /usr/local/lib/python3.7/dist-packages/motioneye/scripts/relayevent.sh "/etc/motioneye/motioneye.conf" picture_save %t %f
stream_authentication motion:

Lastly, the main motion.conf file, which is entirely controlled by motioneye but included here for reference:

# @admin_username admin
# @normal_username motion
# @enabled on
# @admin_password mounthelicon
# @normal_password 


setup_mode off
webcontrol_port 7999
webcontrol_interface 1
webcontrol_localhost on
webcontrol_parms 2

camera camera-1.conf
camera camera-2.conf
camera camera-3.conf
camera camera-4.conf
camera camera-5.conf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment