Summary
Currently there appears to be a lack of options for home cameras that meet my current needs/expectations. As a result I set out to build my own cameras to fill this need. The intent is to build basic home security cameras that meet the following needs:
- Ethernet
- POE/POE+
- A “moderate” or better camera quality (think 1080 or higher resolution)
- No microphone
- No PTZ functions
- No “cloud” functions
- Frigate compatible
Justifications
The majority of these needs are driven by a need for privacy/security.
No PTZ/Mic
Lacking a PTZ function and microphone ensures should someone access the device they would not be able to hear conversations or rotate the camera to view areas they should not. With a custom solution, in an IOT network lacking NAT, this is not a likely scenario however I do not wish to rely on a camera that needs access to the internet for updates, in my case the RPi image can either be rebuilt or pointed to an internal mirror.
POE/Ethernet
As a general principle I keep things off WiFi if at all possible, especially in this case as this will be streaming video and too many cameras over WiFi I predict would become troublesome quickly. The WiFi in my current location is also relatively congested, with everything from the school nearby to Buicks and Toyotas (apparently, this is new to me) all screaming into the ether.
The image above may not accurately reflect the number of devices as many of them overlap and can not be seen.
No “cloud” functions
While I feel like this really should not need a justification I will post two below:
Louis Rossman
China
Collecting the materials
As you can already tell from the title I ended up choosing to build my own camera using a raspberry pi. This will fit all of my requirements and I ended up with the following hardware:
Be warned, I have tested two POE+ hats from two different resellers and it appears if the RPi does not draw enough power it will make a horrible high pitched coil like whine. Thankfully its very easy to consume just enough power to stop this, but if the system idles the noise will return.
Assembling the materials
In general the assembly is very obvious but there are a few things to take note of. When connecting the camera to the raspberry pi take note of the direction the ribbon cable is facing. Ensure the side of the cable with blue tape is facing towards the USB ports. See the picture below or checkout the RPi site here:
Notice how the exposed metal is facing away from the USB ports, and on the opposite side of the “moving” part of the connector.
Building the RPi image
Overall I attempted to build an image with both Armbian and Rocky and in both cases I was unable to get the camera working. I can not find any details on what drivers I could use, or if there was a package, etc there is not a lot of info on the camera drivers. Either way nothing is set in stone so the OS could always be revisited at a later date, the preferred option would be Rocky but after a few nights of testing, it really was time to just push forward and create an “MVP” of sorts. With that out of the way, at this time (2023-12-02) raspbian lite running debian bookworm (12) does not work, so I needed to roll with bullseye instead.
Build the image
As stated above I had issues with pretty much every OS except for rapsbian based on debian 11. So I collected the image from their site, burned the image to my microsd, and got to setting up my image. After doing so I setup my user and the OS like so:
- Setup OS
apt update -y apt upgrade -y apt install ssh zsh libcamera-apps qv4l2 htop git -y
- Setup User
sh -c "$(wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)" git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k sed -i 's/robbyrussell/powerlevel10k\/powerlevel10k/g' ~/.zshrc
The snippet above is not needed but I do like having zsh with the powerlevel10k theme. I would also copy your ssh key to this image so it will be available on any clones created later.
Setting up the RTSP service
I spent some time looking into possible RTSP applications, mainly VLC, and this ended up becoming cumbersome. I ended up finding MediaMTX (formerly rtsp-simple-server) which appears to fit the bill VERY well. The RTSP server will run as a separate user that we will create and a systemd service.
- Setup MediaMTX: Below we will download
mediamtx
and create a usercd /tmp/ wget https://github.com/bluenviron/mediamtx/releases/download/v1.3.1/mediamtx_v1.3.1_linux_arm64v8.tar.gz tar -xvf ./mediamtx_v1.3.1_linux_arm64v8.tar.gz mv ./mediamtx /bin/ useradd mediamtx -r -d /srv/mediamtx -s /usr/sbin/nologin -c "Mediamtx service user" -G video mkdir /srv/mediamtx touch /srv/mediamtx/mediamtx.yml chown -R mediamtx:mediamtx /srv/mediamtx chmod 400 /srv/mediamtx/mediamtx.yml
- Create service file: Write file to
/lib/systemd/system/mediamtx.service
[Unit] Description=Mediamtx RTSP Server After=network.target [Service] ExecStart=/bin/mediamtx /srv/mediamtx/mediamtx.yml Type=simple Restart=always [Install] WantedBy=multi-user.target
- Enable the new service: Don’t start the service yet, the config file has not been written yet.
systemctl daemon-reload systemctl enable mediamtx
- Write the config: The config will need to be tweaked to your needs, however the following is what I will be using. The key take away is that I have stripped the majority of the file and its comments below I only need RTSP, and wanted a time overlay. Technically this file can be placed anywhere the new user has access to but in the systemd service file created above I set it to
/srv/mediamtx/mediamtx.yml
. Make sure to adjust the location in the systemd file if you change this yourself.logLevel: info logDestinations: [stdout] readTimeout: 10s writeTimeout: 10s writeQueueSize: 512 udpMaxPayloadSize: 1472 api: no rtsp: yes protocols: [udp, multicast, tcp] encryption: "no" rtspAddress: :8554 rtmp: false hls: false webrtc: false srt: false pathDefaults: source: publisher sourceOnDemand: no sourceOnDemandStartTimeout: 10s sourceOnDemandCloseAfter: 10s maxReaders: 0 record: no rtspTransport: automatic rpiCameraCamID: 0 rpiCameraWidth: 1920 rpiCameraHeight: 1080 rpiCameraHFlip: false rpiCameraVFlip: false rpiCameraBrightness: 0 rpiCameraContrast: 1 rpiCameraSaturation: 1 rpiCameraSharpness: 1 rpiCameraExposure: normal rpiCameraAWB: auto rpiCameraDenoise: "off" rpiCameraShutter: 0 rpiCameraMetering: centre rpiCameraGain: 0 rpiCameraEV: 0 rpiCameraHDR: false rpiCameraFPS: 30 rpiCameraIDRPeriod: 60 rpiCameraBitrate: 1000000 rpiCameraProfile: main rpiCameraLevel: '4.1' rpiCameraAfMode: continuous rpiCameraAfRange: normal rpiCameraAfSpeed: normal rpiCameraLensPosition: 0.0 rpiCameraTextOverlayEnable: true rpiCameraTextOverlay: '%Y-%m-%d %H:%M:%S - Office South' paths: cam: source: rpiCamera
Finishing the image
If you intend on re-using your image now is the time to delete the ssh keys, these can be found in /etc/ssh/
. If you choose to delete the host keys, they will need to be rebuilt the next time the RPi boots, this can be done with sudo dpkg-reconfigure openssh-server
do note though SSH will not be available so the RPi will need to be accessed locally. At this point your uSD can be imaged and re-used later.
Adjusting the camera
At this point your RPi is assembled with the POE+ hat somewhat squashing your cameras ribbon cable. Take the time now to adjust your camera, adjustments will most likely be needed later when the system and its camera are transferred into a case however at this point it would be best to make sure everything works. Make sure you can adjust the camera focus and aperture. You will need to unscrew the focus ring a good bit, you should begin to see a silver ring pictured below:
Also don’t forget to use the back focus adjustment ring to dial it in. Take note of the diagram below:
There are two separate ring/adapters in this diagram that can be adjusted. If, like me, you purchased the 6mm lens the largest one (C-CS adapter) must be discarded, that leaves the smallest ring, the “Back focus adjustment ring”, make sure yours can move. In my case this required a significant amount of force (think pliers + rage) even with the lock screw fully removed. This adjustment ring can move and most likely will need to in order to get the image focused correctly.
At the time of writing this post the lens appears to have been a bad choice. I am unable to focus the camera at a distant object. The picture quality is great but only within a short distance, i.e. ~10 feet or so, any further and the image becomes blurry again. Other lenses may be a better option.
When the image is still blurry but mostly there that final ring can be adjusted to get the final bit of clarity from the image. Keep in mind this may take a good while.
Closing Notes
At this point the main meat and potatoes has all been shown to work, and a very simple RTSP server is available. There are still many improvements that need to be made, for example:
- The system needs a case
- The image can not be focused on distant objects
- Think street lights at 50 meters
- The host OS is fine however I have a preference for RHEL based distros
- While the OS does not need to be RHEL based SELinux would be a nice addition
- Currently the cameras will exist in an IOT network, this network does not have NAT available so some sort of package proxy would be nice for updates.
There is more work to here for sure. Next step is to print a case for the system, which will be its own ordeal. I anticipate future steps being of note and as such there most likely will be a “part 2” to this.