Raspberry Pi IP camera
I want to keep an eye on my 3D prints and also the plants, so lets build a very simple IP camera with streaming video and pan/tilt controls in under a day using things I have lying about the house.
Part I - Hardware
Step 1: Supplies
From the parts pile, I selected:
- Raspberry Pi 4
- Raspberry Pi 4 authentic power supply (for headache reduction)
- Sparkfun Servo Hat
- Razor Kiyo Webcam USB (bad choice - too heavy for my servos)
- Cheap no-brand pan/tilt assembly
- Ultra cheap 9g servos (another bad choice - need to buy better ones for anything beyond supporting own weight)
- Assorted hardwares
Step 2: Some soldering required
Just the female headers on the servo hat need doing thankfully. I ended up bumping the temperature to 340. Remember to use the correct amount of flux.
Step 3: Pan/tilt assembly Part A
Eventually I gave up and thew this crap I’ve been saving for years in the bin
Step 4: Pan/tilt assembly Part B
Found a new pan/tilt mechanism on printables. Its not perfect, I had to melt a hole for servo wires with my old soldering iron but its still way better then the one I threw out and doesn’t have the bottom motor dangling on its own either.
Step 5: Webcam
Just plug-in the USB. I did think about cable tieing this to the pan/tilt base but its just too heavy.
For now, the hardware build is complete enough to let me look at the software side and maybe fix up the hardware properly one day.
Software
Raspberry Pi
- Install Raspberry Pi lite 64 bit using Raspberry Pi Imager
- Fast SD card fine for this build and I have spare USB SSDs if I change my mind
- Intention would be video in the cloud - eventually
- Apply all updates, reboot, etc
- Important: Enable I2C in
raspi-config
or servo hat won’t work
Pan/Tilt control
The servo hat hookup guide has a bunch of sample codes I was able to run to make the servos twitch and move around. To use this low level library, you are required to do a bunch of maths to work out the PWM pulses you want to send to the motor.
Having proved both servos were working, I switched to adafruit circuit python which lets me just punch in the angles I wanted to use. My very basic pan/tilt test script looks like this:
#!/usr/bin/env python
import time
import time
import board
import busio
from adafruit_pca9685 import PCA9685
from adafruit_motor import servo
# Create the I2C bus interface
i2c = busio.I2C(board.SCL, board.SDA)
# Create the PCA9685 instance
pca = PCA9685(i2c)
pca.frequency = 50 # Standard servo frequency
# Servo on channel 0
servo_pan = servo.Servo(pca.channels[0])
# Servo on channel 1
servo_tilt = servo.Servo(pca.channels[1])
def sweep(servo, max_angle):
print("sweep out...")
# Sweep motion
for angle in range(0, max_angle + 1, 1): # 0 to max_angle in steps of 1
servo.angle = angle
time.sleep(0.01)
print("sweep back...")
for angle in range(max_angle, -1, -1): # back down
servo.angle = angle
time.sleep(0.01)
def main():
# Sweep motion
print("pan...")
sweep(servo_pan, 180)
time.sleep(5)
print("tilt...")
sweep(servo_tilt, 120)
print("bye")
pca.deinit()
if __name__ == "__main__":
main()
This works very nicely, and could be modified to store the pan/tilt angles of interesting things to look at. Since my mount can’t take the weight of the camera I’m calling this good for now.
Video
Since the webcam I’m using is USB, it appears as /dev/video0
as a V4L2 device
There are a few different schools of thought around how to deal with video. In the past, I’ve done stuff with M-JPEG to make some basic streaming videos. I did not get great results with this method.
Another way would be to write some more python and access video hardware directly. You can do things like image/face detection, timelapse, etc this way.
In the end, I decided to pick the simplest option to avoid the need to do more programming: Just use video-native tools to prepare an RTSP stream and then watch it with WebRTC in a browser.
Below is how I got this running very quickly with no authentication, bootup services, etc - its just for testing.
MediaMTX
MediaMTX (formerly rtsp-simple-server
, MIT license), is a media streaming server which has a ton of capabilities. You must use a media server supporting RTSP to receive data from FFMPEG as the built-in FFMPEG RTSP server (AKA listen mode) has been removed in recent versions. If you read the manual for MediaMTX you will understand why.
Grab the binary and start it:
wget https://github.com/bluenviron/mediamtx/releases/download/v1.14.0/mediamtx_v1.14.0_linux_arm64.tar.gz
tar zxvf mediamtx_v1.14.0_linux_arm64.tar.gz
./mediamtx
FFMPEG
With a media server running, we can stream data to it. Read the notes here which go into a lot of detail on hardware acceleration and settings.
My webcam does not support H264 on its own and there is no hardware acceleration Raspberry Pi OS version of FFMPEG, so I tweaked the command to get it to run. This registers a stream called stream
in MediaMTX:
# can be improved, adapted from page above very quickly as no VAAPI on raspberry pi ;)
ffmpeg -f v4l2 -input_format yuyv422 -video_size 1920x1080 -framerate 30 -use_wallclock_as_timestamps 1 -fflags +genpts -i /dev/video0 -an -vf 'format=nv12' -vcodec h264 -bf 0 -f rtsp rtsp://127.0.0.1:8554/stream
Browser
Since I have not configured authentication, TLS, or anything else, I can just point a web browser at MediaMTX and read the WebRTC stream directly from port 8889
:
The resulting stream is really nice quality, smooth video. For some reason it only plays in chrome. Probably this is to do with the ffmpeg
command I’m using.
Future Plans
Interestingly, most of this build was to do with getting hardware to work nicely. As it stands, I’m able to control the servos but not able to mount the camera, and I have some good test scripts.
I learned a lot about how video streaming works in 2025. Probably if your wanting to do timelapses and keep the ability to watch a live video feed you would want to run MediaMTX somewhere and stream video to it. You could then connect other apps to this service and pull frames for analysis, etc.
This may take a while:
Task I - Functional and secure IP camera
- Design my own pan/tilt mechanism and 3D print it
- This may also need some better servos
- Simple python REST API for pan/tilt control:
- Authentication and TLS for MediaMTX, run as a service on boot
- Run FFMPEG on boot, with retries for if MediaMTX unreachable
- Simple static web page to glue together the pan/tilt controls and video feed
- Release as free software/instructions
Task II
- Cloud recording - upload video feeds to the cloud
Task III - Smart features
- Integrate with Zigbee smart home sensors already available on MQTT - eg proximity sensor, door sensor, etc
- Integrate with LORA plant watering system - another big todo item
- 3D print time-lapse videos
- Integrate with Prusa app on phone/some other app(?)