Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (2024)

This post explores how to create your own WiFi camera, for realtime video streaming over the web, using a Raspberry Pi Zero W, a camera module, the Go programming language.

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (3)

In a previous post, I explored how to use the Go for Video Linux (Go4VL) package to create Go programs to capture video data from a Linux machine with an attached USB web camera gadget. This post shows how to build your own WiFi camera using the Raspberry Pi Zero W, a Pi camera module, and a Go program that serves the captured video using an HTTP web server.

For this project you will need the followings:

Before you plug the Raspberry Pi to a power source, attach the camera module. Regardless of your Pi model or camera model, you will attach your camera similarly to what is shown in the animation below (from these instructions).

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (4)

Note: remember the instructions here are for a headless setup (SSH only). After you follow the instruction to attach your camera to the board, return here to continue.

If you do not already have a Pi configured with a camera module, use the steps below to help with your Pi and camera configuration. The following steps assume that you will setup your Raspberry Pi without a desktop environment (or headless).

Flash the OS using the Pi Imager tool

Use the Raspberry Pi imager tool to flash the Raspberry Pi OS Lite on your SSD for headless use. Follow the advanced instructions to set up the followings:

  • Enable support for SSH
  • Specify a host name, if needed
  • Enable and configure Wifi

After flashing the SSD, boot up your Pi and continue to the next section.

Enable the camera module

Assuming your Raspberry Pi device is on the same network as your workstation or laptop, use these instructions to log into your Pi using SSH. Upon login, use the raspi-config tool to enable the camera.

sudo raspi-config

Use theInterface Options , to enable the camera interface as shown below.

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (5)

Once done, reboot the Raspberry Pi.

Validate your setup

Since this is a headless setup, it is a good idea to ensure that the camera is attached and working properly. SSH back into the Pi and install the v4l2-utils package

sudo apt-get install v4l-utils

Next, use the v4l2-ctl command (from the installed package) to list your attached devices:

v4l2-ctl --list-devices

You should see a list of several devices including a Broadcom BCM235 V4L2 device driver as shown below:

mmal service 16.1 (platform:bcm2835-v4l2-0):
/dev/video0

The /dev/video0 is the device name for the camera device that will be used for video capture. You can get more information about the device with the following v4l2-ctl command:

v4l2-ctl --info -d /dev/video0
Driver Info:
Driver name : bm2835 mmal
Card type : mmal service 16.1
Bus info : platform:bcm2835-v4l2-0
Driver version : 5.15.65
Capabilities : 0x85200005
Video Capture
Video Overlay
Read/Write
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x05200005
Video Capture
Video Overlay
Read/Write
Streaming
Extended Pix Format

Now that you have your Pi properly configured, it is time to write a simple program that will allow you to stream M-JPEG formatted videos to your web browser.

The source code

The following code is based on example Go4VL/examples/simplecam. First, let us examine the main function which is used to setup the camera device and start an HTTP server.

import(
"github.com/vladimirvivien/go4vl/device"
"github.com/vladimirvivien/go4vl/v4l2"
)

var (
frames <-chan []byte
)

func main() {
port := ":9090"
devName := "/dev/video0"

camera, err := device.Open(
devName,
device.WithPixFormat(v4l2.PixFormat{PixelFormat: v4l2.PixelFmtMJPEG, Width: 640, Height: 480}),
)
if err != nil {
log.Fatalf("failed to open device: %s", err)
}
defer camera.Close()

if err := camera.Start(context.TODO()); err != nil {
log.Fatalf("camera start: %s", err)
}

frames = camera.GetOutput()
http.HandleFunc("/stream", imageServ)
log.Fatal(http.ListenAndServe(port, nil))
}

In the previous snippet, note that function device.Open , from the go4vl package, is used to open device /dev/video0 and configure with the desired video format v4l2.PixFormat{PixelFormat: v4l2.PixelFmtMJPEG}. Once the device is opened, it is assigned to variable camera.

Method call camera.GetOutput() returns a channel of byte slices, assigned to variable frames, that contain the video frames captured from the camera device. Lastly, the code registers HTTP handler imageServ for path /stream.

The next code snippet defines HTTP handler function imageServ which is used to serve the video stream to a web client (i.e. your browser). The code sets up a for-range loop to continuously retrieve video frame data from the frames channel variable (setup earlier). Each retrieved frame is returned as a separate JPEG image back to the web client using a multi-part mime writer as shown in the snippet below.

func imageServ(w http.ResponseWriter, req *http.Request) {
mimeWriter := multipart.NewWriter(w)
w.Header().Set("Content-Type", fmt.Sprintf("multipart/x-mixed-replace; boundary=%s", mimeWriter.Boundary()))
partHeader := make(textproto.MIMEHeader)
partHeader.Add("Content-Type", "image/jpeg")

var frame []byte
for frame = range frames {
partWriter, err := mimeWriter.CreatePart(partHeader)
if err != nil {
log.Printf("failed to create multi-part writer: %s", err)
return
}

if _, err := partWriter.Write(frame); err != nil {
log.Printf("failed to write image: %s", err)
}
}
}

The Raspberry Pi Zero is a 32-bit ARM machine. There are several ways to build the Go code to create a 32-bit ARM binary, including cross-compilation.

Building on the Raspberry Pi Zero

The easiest way to build and run the program is to build it on theRaspberry Pi itself. First, download the Go tools for the ARMv6 architecture (i.e. go1.19.3.linux-armv6l.tar.gz). Then install the files with the following commands:

rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.3.linux-armv6l.tar.gz

Then you are ready to compile your source code:

go build ./simplecam

Cross compiling for the Raspberry Pi

Cross compiling Go programs (from a different architecture and/or OS with CGo included) to target the Raspberry Pi Zero is more involved (read complex). The steps vary depending on the host OS and architecture from which you will cross-compile your code to target the Raspberry Pi. In the interest of brevity, that exercise will be reserved for a future write up the subject.

After the source code is compiled successfully, the camera program can be started as shown below (output is from the example simplecam program):

./simplecam
2022/11/13 14:05:38 Serving images: [:9090/stream]

Accessing via a web browser

Next point your browser to the IP address (or host name) of the Raspberry Pi at http://<host-ip>:9090/stream to see the video feed as shown below.

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (6)

Accessing via VLC

You can also access the stream via any other client that can stream MJPEG over HTTP. For instance, if you have VLC, create new network source as shown below.

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (7)

Once connected, you will see your video stream displayed using the VLC application as shown.

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (8)

This writeup explores how to turn a Raspberry Pi Zero W, with an attached camera module, into a working WiFi camera using Go. The program uses the Go4VL package to create a simple, but functional, program that serves captured video buffers, from the camera, using an HTTP web server making the video accessible via a web browser.

In a future write up, we will explore how to extend this program to add camera control functionalities such as brightness and contrast to your Go camera project.

Build a WiFi Camera using the Raspberry Pi Zero W, a Camera module, and Go (2024)
Top Articles
Latest Posts
Article information

Author: The Hon. Margery Christiansen

Last Updated:

Views: 6042

Rating: 5 / 5 (70 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: The Hon. Margery Christiansen

Birthday: 2000-07-07

Address: 5050 Breitenberg Knoll, New Robert, MI 45409

Phone: +2556892639372

Job: Investor Mining Engineer

Hobby: Sketching, Cosplaying, Glassblowing, Genealogy, Crocheting, Archery, Skateboarding

Introduction: My name is The Hon. Margery Christiansen, I am a bright, adorable, precious, inexpensive, gorgeous, comfortable, happy person who loves writing and wants to share my knowledge and understanding with you.