Live Video Streaming using Raspberry Pi

by Mar 31, 2020Raspberry Pi

As we know, your Raspberry Pi can be used for a plethora of things, one such application is live streaming video from your Raspberry Pi camera over the web.

This is a fun project to do for all ages, and implement in and around the house. And, if integrated with motion sensor can actually be used as a full-fledged surveillance camera. At the end of this article you will be able to write a code to stream the video, and access it on any device connected to the same network as that of your Raspberry Pi. However, video streaming over the web has its own difficulties, so in this code we will be using a simple format for the video called MJPEG. The source code for this program is part of the official PiCamera Package and can be accessed from their website as well.

What is MJPEG?

MJPEG or Motion JPEG is a video compression format wherein the video comprises of several compressed individual JPEGs in a sequence. This results in a high quality outcome which doesn’t affect the video quality even if one frame is dropped. It however, does consume more bandwidth and storage. But since we are only streaming and not storing the video it is of little disadvantage to us.

Hardware Requirements:

  1. Raspberry Pi (I used, model 3 B +) – make sure to have the OS installed and running
  2. Internet connection (either over WiFi or ethernet)
  3. Laptop, or mobile phone connected to the same network
  4. Camera module
  5. Power cable
  6. Monitor
  7. HDMI connector
  8. USB or Bluetooth mouse
  9. USB or Bluetooth keyboard

 

Setup:

Hardware

  1. Connect the Raspberry Pi camera module (for any help on that, check out our article on that https://iot4beginners.com/how-to-capture-image-and-video-in-raspberry-pi/ ).
  2. Use the HDMI cable to connect your Raspberry Pi to a display
  3. Connect your mouse and keyboard as well (through USB or Bluetooth)
  4. Connect your Raspberry Pi to the internet. Either over WiFi or ethernet.

Software:

After connecting your Raspberry Pi to the internet, find the IP address of the network it is connected to.

  1. Open the terminal
  2. type ifconfig
  3. next to wlan0 you will see the IP address, as in the image below next to inet
    IMG_20200212_161222

    image with the IP address that appeared for me.

    4. Either write down or copy that IP address somewhere, because you’re going to need it very soon!

Code:

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
<head>
<title>Raspberry Pi - Surveillance Camera</title>
</head>
<body>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="640" height="480"></center>
</body>
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
    if self.path == '/':
        self.send_response(301)
        self.send_header('Location', '/index.html')
        self.end_headers()
    elif self.path == '/index.html':
        content = PAGE.encode('utf-8')
        self.send_response(200)
        self.send_header('Content-Type', 'text/html')
        self.send_header('Content-Length', len(content))
        self.end_headers()
        self.wfile.write(content)
    elif self.path == '/stream.mjpg':
        self.send_response(200)
        self.send_header('Age', 0)
        self.send_header('Cache-Control', 'no-cache, private')
        self.send_header('Pragma', 'no-cache')
        self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
        self.end_headers()
        try:
            while True:
                with output.condition:
                    output.condition.wait()
                    frame = output.frame
                self.wfile.write(b'--FRAME\r\n')
                self.send_header('Content-Type', 'image/jpeg')
                self.send_header('Content-Length', len(frame))
                self.end_headers()
                self.wfile.write(frame)
                self.wfile.write(b'\r\n')
        except Exception as e:
            logging.warning(
                'Removed streaming client %s: %s',
                self.client_address, str(e))
    else:
        self.send_error(404)
        self.end_headers()

class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

Code Explanation:

First we import some libraries and functions needed for the code to run.

import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

We then write a code for the page on which the live stream will be displayed when you access it.

PAGE="""\
<html>
<head>
<title>Raspberry Pi - Surveillance Camera</title>
</head>
<body>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="640" height="480"></center>
</body>
</html>
"""

The first task is to define a class for the output stream.  This will be used throughout the program to be able to access the video and continuously stream it using the IP address.

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

We then have to write the code for the actual streaming process. This means now only for smooth streaming of the MJPEG video, but also writing the case in which an error occurs and the output message for that. This is a very important part of the code as it is the mainframe for the video to be streamed live with minimal delay and errors.

class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

Only in the next part of the code do we actually start the recording from the camera. As most of you know, we can assign a resolution, frame rate and format for the picamera, and instam of storing the output we simply assign the output to a variable.

If in case, while streaming you see that the video is tilted, uncomment the line as instructed below and type in the value(in degrees) that you want to see the video tilted by.

with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
    output = StreamingOutput()
    #Uncomment the next line to change your Pi's Camera rotation (in degrees)
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

Now run the program.

Once it is running, open your browser in any device connected to the same network, and in the address bar type http://<IP address>:8000/

For me, it was http://192.168.43.4:8000

Output:

camera

I initially connected a 10” inch screen to see how it would work on the Pi display itself

camera2

Here it is working on both the Pi display and my laptop

Sample output video:

Click to Download the Code

This program is a fun way to get into the real time application oriented projects using Raspberry Pi, as well as learn to integrate different domains of coding together. Although web streaming sounds hard and takes a while to wrap yourself around, atleast go through the code to see the flow of the program. This aids in understanding how to break down a goal into parts, which will help immensely when trying to write your own.

It is both fun to learn and understand, but more so to use! Go ahead try moving your setup around to see how far you can go away and still access it, what range you can cover in terms of area. Hope you have fun with this project, I sure did!

Creating a multiplication Skill in Alexa using python

Written By Jyotsna Rajaraman

Hi! I'm Jyotsna, an electronics and communication undergrad who likes reading, writing, talking and learning. So when it comes to teaching, all my favorite things come together! I hope my articles have helped and taught you something. 🙂

RELATED POSTS

How to Setup an NGINX Server on Raspberry Pi ?

How to Setup an NGINX Server on Raspberry Pi ?

What is NGINX ? NGINX is a popular lightweight web server application you can install on the Raspberry Pi to allow it to serve web pages. In its initial release, it functioned for HTTP web serving. It is a web server that can also be used as...

FM Radio Transmitter with Raspberry Pi

FM Radio Transmitter with Raspberry Pi

We’ve all listened to the radio and sang along to the songs, atleast in the car. But have you ever found yourself switching through several channels because you couldn’t find even one song that YOU like? In this article we will learn how to build a FM radio...

Raspberry Pi Camera and its Variety

Raspberry Pi Camera and its Variety

Choosing a suitable raspberry pi camera for your projects can get really difficult. RPI camera v1, RPI camera v2, RPI NOIR camera, and the list continues. Each one has different properties and should be used according to them. They have been used in various fields and...

WiFi extender using Raspberry Pi

WiFi extender using Raspberry Pi

It is always useful to know how to use your Raspberry Pi in pet projects that are actually useful around the house. Especially when you aren’t building something new – using your dormant Raspberry Pi to build useful devices around the house is a fun idea. If you are...

Using Raspberry Pi as various Servers

Using Raspberry Pi as various Servers

Raspberry Pi is a widely popular SoC, that is versatile and easy to use for even beginners. If you are new and are unfamiliar with Pi, take a look at these articles. Regardless of the model of Raspberry Pi you have, I am sure you have discovered a plethora of projects...

SQLite Database on Raspberry Pi

Welcome to another tutorial on Raspberry Pi. In this tutorial, we will see how to use the SQLite Database on Raspberry Pi. Apart from the installation and a few basic commands, in the end, we shall look at a simple project to log sensor data into an SQLite database....

Mosquitto MQTT Broker on Raspberry Pi

This tutorial will show you what is Mosquitto MQTT Broker and how to install it on Raspberry Pi. Contents What is MQTT?Installing Mosquitto MQTT on Raspberry PiCreating an MQTT Broker on Raspberry PiSubscribe to a TopicPublish a message to a TopicSample...

Evolution of the Raspberry Pi – A Comparison

Evolution of the Raspberry Pi – A Comparison

The Raspberry Pi is an inexpensive credit card-sized micro-computer. The Raspberry Pi was originally designed as a way to teach how computers work and the rest of computer science in general. It was originally developed in the UK by a team that included Eben Upton,...

Recording audio on your Raspberry Pi

Recording audio on your Raspberry Pi

Raspberry Pi can record and playback fairly good quality audio through its USB 2.0 ports. For recording audio and playback we need two peripheral devices, a USB microphone, and a speaker. You can choose to use a USB speaker, or a speaker with a 3.5mm sound jack....

Tutorial: Dropbox with Raspberry Pi

Tutorial: Dropbox with Raspberry Pi

Many Raspberry Pi projects require synchronization of files over more than just one device. Dropbox, which is a popular file-hosting service, can be used for this with ease. Synchronizing data between different devices may seem a little tricky, especially since the...

VIDEOS – FOLLOW US ON YOUTUBE

EXPLORE OUR IOT PROJECTS

IoT Smart Gardening System – ESP8266, MQTT, Adafruit IO

Gardening is always a very calming pastime. However, our gardens' plants may not always receive the care they require due to our active lifestyles. What if we could remotely keep an eye on their health and provide them with the attention they require? In this article,...

How to Simulate IoT projects using Cisco Packet Tracer

In this tutorial, let's learn how to simulate the IoT project using the Cisco packet tracer. As an example, we shall build a simple Home Automation project to control and monitor devices. Introduction Firstly, let's quickly look at the overview of the software. Packet...

All you need to know about integrating NodeMCU with Ubidots over MQTT

In this tutorial, let's discuss Integrating NodeMCU and Ubidots IoT platform. As an illustration, we shall interface the DHT11 sensor to monitor temperature and Humidity. Additionally, an led bulb is controlled using the dashboard. Besides, the implementation will be...

All you need to know about integrating NodeMCU with Ubidots over Https

In this tutorial, let's discuss Integrating NodeMCU and Ubidots IoT platform. As an illustration, we shall interface the DHT11 sensor to monitor temperature and Humidity. Additionally, an led bulb is controlled using the dashboard. Besides, the implementation will be...

How to design a Wireless Blind Stick using nRF24L01 Module?

Introduction Let's learn to design a low-cost wireless blind stick using the nRF24L01 transceiver module. So the complete project is divided into the transmitter part and receiver part. Thus, the Transmitter part consists of an Arduino Nano microcontroller, ultrasonic...

Sending Temperature data to ThingSpeak Cloud and Visualize

In this article, we are going to learn “How to send temperature data to ThingSpeak Cloud?”. We can then visualize the temperature data uploaded to ThingSpeak Cloud anywhere in the world. But "What is ThingSpeak?” ThingSpeak is an open-source IoT platform that allows...

Amaze your friend with latest tricks of Raspberry Pi and Firebase

Introduction to our Raspberry Pi and Firebase trick Let me introduce you to the latest trick of Raspberry Pi and Firebase we'll be using to fool them. It begins with a small circuit to connect a temperature sensor and an Infrared sensor with Raspberry Pi. The circuit...

How to implement Machine Learning on IoT based Data?

Introduction The industrial scope for the convergence of the Internet of Things(IoT) and Machine learning(ML) is wide and informative. IoT renders an enormous amount of data from various sensors. On the other hand, ML opens up insight hidden in the acquired data....

Smart Display Board based on IoT and Google Firebase

Introduction In this tutorial, we are going to build a Smart Display Board based on IoT and Google Firebase by using NodeMCU8266 (or you can even use NodeMCU32) and LCD. Generally, in shops, hotels, offices, railway stations, notice/ display boards are used. They are...

Smart Gardening System – GO GREEN Project

Automation of farm activities can transform agricultural domain from being manual into a dynamic field to yield higher production with less human intervention. The project Green is developed to manage farms using modern information and communication technologies....