geoffwilliams@home:~$

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

available parts

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.

soldering fun

Step 3: Pan/tilt assembly Part A

Eventually I gave up and thew this crap I’ve been saving for years in the bin

bad pan/tilt

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.

better pan/tilt

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.

pan/tilt in action

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:

webcam feed

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(?)

Post comment

Markdown is allowed, HTML is not. All comments are moderated.



Comments

2025-08-16 Extra special

Will this be available soon, I need to monitor my shared clothes line. I was wondering if you could make me a prototype xo