Video Streaming with Raspberry Pi Camera

In this post we’re going to show you how you can do video streaming with a Raspberry Pi and a Raspberry Pi Camera – how to stream live video into a web page that you can access in any device that has a browser and is connected to the same network the Pi is. This is useful to apply to a home surveillance camera, for example.

Prerequisites:

Enable the Rasperry Pi Camera Module

If you’re using the Raspberry Pi Camera Module, you need to enable the camera software in your Raspberry Pi in order to use it. In the Desktop environment, go to the Raspberry Pi Configuration window under the Preferences menu, open the Interfaces tab and enable the Camera as shown in figure below.

Or, in the Terminal window, type the following command:

pi@raspberry:~ $ sudo raspi-config

You should see the Raspberry Pi software configuration tool. Select the Interfacing Options:

Learn Raspberry Pi, ESP8266, Arduino and Node-RED. This is a a step-by-step course to get you building a real world home automation system using open-source tools DOWNLOAD »

Learn Raspberry Pi, ESP8266, Arduino and Node-RED. This is a a step-by-step course to get you building a real world home automation system using open-source tools DOWNLOAD »

Enable the camera and reboot your Pi:

Find the Raspberry Pi IP address

To access your video streaming web server, you need to know your Raspberry Pi IP address. For that, use the following command:

pi@raspberry:~ $ ifconfig

You’ll be given a bunch of information, including your Raspberry Pi IP address. In my case, the RPi IP address is 192.168.1.112.

Connect the camera

Connecting the Raspberry Pi Camera Module is easy. With the Pi shutdown, connect the camera to the Pi CSI port as shown in the following figure. Make sure the camera is connected in the right orientation with the ribbon blue letters facing up as shown in the next figure.

Writing the script

The script for video streaming is shown below. You can find this script at the official PiCamera package documentation.

Create a new file called rpi_camera_surveillance_system.py:

pi@raspberrypi:~ $ nano rpi_camera_surveillance_system.py

Copy the following code to your newly created file:

# Web streaming example
# Source code from the official PiCamera package
# http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

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

View raw code

To save your file press Ctrl+X, type Y and Enter.

Download our Free eBooks and Resources

Accessing the video streaming

After writing the scrip, you can run it using Python 3. Run the next command:

pi@raspberrypi:~ $ python3 rpi_camera_surveillance_system.py

Once the script is running, you can access your video streaming web server at: http://<Your_Pi_IP_Address>:8000. Replace with your own Raspberry Pi IP address, in my case http://192.168.1.112:8000.

You can access the video streaming through any device that has a browser and is connected to the same network that your Pi.

You can use your Pi to monitor your home as a surveillance camera:

Wrapping up

I hope this project was useful! You could easily upgrade this home surveillance device to record video or notify you when motion is detected.

We also have a project on how to build a complete CCTV system with the Raspberry Pi using MotionEyeOS. Feel free to take a look.

Like home automation? Learn more about Node-RED, Raspberry Pi, ESP8266 and Arduino with my course: Build a Home Automation System for $100.

Do you have any questions? Leave a comment down below!

Thanks for reading. If you like this post probably you might like my next ones, so please support me by subscribing my blog.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

71 thoughts on “Video Streaming with Raspberry Pi Camera”

  1. Excellent article guiding the new builder . I successfully built the project at one attempt and monitoring my house.
    Thank you

  2. Exceptionally easy. I have this running on a Raspberry Pi Zero w/ Wifi, it will be installed into a Pine Wood Derby Car to stream its run live to a computer set up during the race. I think the scouts are going to love this. What is even cooler, is that the car will be within the 5 oz needed to race! Even better, there is very little Lag on the fed. I am very impressed!!!!

  3. Can you please guide me as to how I’d make a separate html file, in the code the html code is written with the python code. I want to add style.css so I can make my website cool. I’ve been trying myself but I can not link the html file with the py file

    • Hi. I’ll suggest something, but I’m not sure if it will work. I haven’t tested this method with this example. I’ve only tested using Python. It worked fine.
      – Create your html text in a separated file. For example test.html. The file should be located on the same folder that your python script.
      – Then, in your Python code, read the content of the html file and save it into the PAGE variable (which is the variable that contains the html content in the code). Here’s a snippet example that reads the content of a file and saves it in the text variable.

      file = open(‘test.html’, ‘r’)
      text = file.read().strip()
      file.close()

      I hope this helps.

  4. This looks great, about to try it on my pi, but what about a password? Because if I have this monitoring my home, will someone with a password be able to see my live feed?

  5. Great tutorial! I used it and it worked like a charm.

    Can you recommend how can I stream audio as well? I have a USB Microphone, how can I also stream audio over HTTP?

  6. hello,
    It works for me but for a short time. After that message WARNING:root:Removed streaming client and the camera stops working
    any idea ?

  7. Hi i’m South Korea student
    I am so appriciate for you content!
    Owing to you, I can finish my senior project perfectfully!
    Speclially,
    i doesn’t know that how can connect python with http.
    God bless you!!!

  8. Hi, great tutorial for Streaming, I want to be able to view it remotely when connected to another network, for example, if I have it set up at home and want to view it at work, any recommendations on how I would go about doing this using this script. Thanks in advance.

  9. It did not work for me. It shows,

    mmal: mmal_vc_port_enable: failed to enable port vc.null_sink:in:0(OPQV): ENOSPC
    mmal: mmal_port_enable: failed to enable connected port (vc.null_sink:in:0(OPQV))0x14e95e0 (ENOSPC)
    mmal: mmal_connection_enable: output port couldn’t be enabled
    Traceback (most recent call last):
    File “rpi_camera_surveillance_system.py”, line 84, in
    with picamera.PiCamera(resolution=’640×480′, framerate=24) as camera:
    File “/usr/lib/python3/dist-packages/picamera/camera.py”, line 433, in __init__
    self._init_preview()
    File “/usr/lib/python3/dist-packages/picamera/camera.py”, line 513, in _init_preview
    self, self._camera.outputs[self.CAMERA_PREVIEW_PORT])
    File “/usr/lib/python3/dist-packages/picamera/renderers.py”, line 558, in __init__
    self.renderer.inputs[0].connect(source).enable()
    File “/usr/lib/python3/dist-packages/picamera/mmalobj.py”, line 2212, in enable
    prefix=”Failed to enable connection”)
    File “/usr/lib/python3/dist-packages/picamera/exc.py”, line 184, in mmal_check
    raise PiCameraMMALError(status, prefix)
    picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources

    • Hi Gerald.
      I’m sorry for taking so long to get back to you.
      I was trying to find an answer to your question.
      Accordingly to this discussion: github.com/waveform80/picamera/issues/488
      It seems that your camera is already being used on the background.
      You need to close the camera instance by using: camera.close()
      Take a look at this link, I think this may be the solution:
      raspberrypi.org/forums/viewtopic.php?t=155304
      Then, to prevent this from happening again, I suggest adding the camera.close() at the end of the camera streaming script.
      I hope this helps.
      Regards,
      Sara 🙂

    • Hi Rossano.
      Which board do you want to use to build the robot? Raspberry Pi?
      We have a tutorial on how to control LEDs using Flask on a Raspberry Pi. That allows you to insert buttons and perform different actions depending on the request URL.
      Here’s the tutorial: Raspberry Pi Web Server using Flask to Control GPIOs
      The example shows how to control LEDs, but you can easily control a DC motor using the gpiozero library for raspberry pi: gpiozero.readthedocs.io/en/stable/api_output.html?highlight=motor#motor
      I hope this helps.
      Regards,
      Sara 🙂

    • Hi.
      Just add the following line to your code:
      camera.rotation = 180
      On line 87: github.com/RuiSantosdotme/Random-Nerd-Tutorials/blob/master/Projects/rpi_camera_surveillance_system.py
      Regards,
      Sara 🙂

  10. Running the Python script, I get the following error.
    It would be nice if you could give me a hint what to do.

    pi@Schuur-PiZero:~/webcam $ sudo python3 rpi_camera_surveillance_system.py
    File “rpi_camera_surveillance_system.py”, line 65
    frame = output.frame
    ^
    IndentationError: unindent does not match any outer indentation level

  11. Hi,

    Got it working at once 🙂 just wondered if I can change from network cable to usb wifi dongel instead without making change in code?

  12. Is it any way to change port to 80? When i change it in code i am getting an error:
    ” Traceback (most recent call last):
    File “rpi_camera.py”, line 84, in
    with picamera.PiCamera(resolution=’640×480′, framerate=24) as camera:
    File “/usr/lib/python3/dist-packages/picamera/camera.py”, line 433, in __init__
    self._init_preview()
    File “/usr/lib/python3/dist-packages/picamera/camera.py”, line 513, in _init_preview
    self, self._camera.outputs[self.CAMERA_PREVIEW_PORT])
    File “/usr/lib/python3/dist-packages/picamera/renderers.py”, line 558, in __init__
    self.renderer.inputs[0].connect(source).enable()
    File “/usr/lib/python3/dist-packages/picamera/mmalobj.py”, line 2212, in enable
    prefix=”Failed to enable connection”)
    File “/usr/lib/python3/dist-packages/picamera/exc.py”, line 184, in mmal_check
    raise PiCameraMMALError(status, prefix)
    picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources “

    • Hi Stefano.
      Accordingly to this discussion: github.com/waveform80/picamera/issues/488
      It seems that your camera is already being used on the background.
      You need to close the camera instance by using: camera.close()
      Take a look at this link, I think this may be the solution:
      raspberrypi.org/forums/viewtopic.php?t=155304
      Then, to prevent this from happening again, I suggest adding the camera.close() at the end of the camera streaming script.
      I hope this helps. Let me know if it solves your problem.
      Regards,
      Sara 🙂

    • I’ve seen this problem before, check if you are using Python 2.x or Python 3.x the name of the library you are trying to import is different. The library in Python2 is SocketServer, while the library in Python3 is socketserver. By default, a raspberry pi running on Raspbian would use python 2.
      SOLUTIONS:
      1. when running the script, type python3 .py
      2. change all instances of socketserver in the program to SocketServer

  13. Hi, whenever I try to run your code through the Python 3 IDLE I get the response that the syntax is invalid. Here is exactly what is in my code:

    Python 3.5.3 (default, Jan 19 2017, 14:11:04)
    [GCC 6.3.0 20170124] on linux
    Type “copyright”, “credits” or “license()” for more information.
    >>> # Web streaming example
    # Source code from the official PiCamera package
    # http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

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

    PAGE=”””\

    Raspberry Pi – Surveillance Camera

    Raspberry Pi – Surveillance Camera

    “””

    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=’640×480′, 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()

    Thanks

  14. Hello

    I got the camera working good, but the day after the camera is not available. I have to run python3 rpi_camera_surveillance_system.py through putty to get it going again. Is it possible to get it to run 24/7?

  15. Hello I am going to try this solution since I want to use to raspberris one for live transmission and other for whatching it …… However I don-t have the raspi cam any suggestion about using a usb web cam?? I can already read the webcam using openCV4 but what change should I do in this code to read that cam instead of raspi cam? Thanks

  16. i try it but if i want shoot a photo when object move around a pir the camerapi ontrol in nodered not respond the problem is a pyton that take complete control of cam
    but for me is interesting take a photo with a person move around my pir
    any idea?

  17. Nice script, works great. Has anyone tried H.264 as a stream? My camera is capable of it but I have not tried it yet. I was just going to change output from mjpeg to h264. Thanks for your time.

  18. Fantastic!
    This is amazing for a dinosaur like me to get into. I really need to get into more Python coding though, and to think everything was done in assembly code a long time ago. Things have changed so much.
    Well done!!

  19. hello can you help me, Im getting an error
    mmal: mmal_vc_port_enable: failed to enable port vc.null_sink:in:0(OPQV): ENOSPC
    mmal: mmal_port_enable: failed to enable connected port (vc.null_sink:in:0(OPQV))0x1a6f8d0 (ENOSPC)
    mmal: mmal_connection_enable: output port couldn’t be enabled
    Traceback (most recent call last):
    File “rpi_camera_surveillance_system.py”, line 84, in
    with picamera.PiCamera(resolution=’640×480′, framerate=24) as camera:
    File “/usr/lib/python3/dist-packages/picamera/camera.py”, line 433, in __init__
    self._init_preview()
    File “/usr/lib/python3/dist-packages/picamera/camera.py”, line 513, in _init_preview
    self, self._camera.outputs[self.CAMERA_PREVIEW_PORT])
    File “/usr/lib/python3/dist-packages/picamera/renderers.py”, line 558, in __init__
    self.renderer.inputs[0].connect(source).enable()
    File “/usr/lib/python3/dist-packages/picamera/mmalobj.py”, line 2212, in enable
    prefix=”Failed to enable connection”)
    File “/usr/lib/python3/dist-packages/picamera/exc.py”, line 184, in mmal_check
    raise PiCameraMMALError(status, prefix)
    picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources

    • Hi Rey.

      Accordingly to this discussion: github.com/waveform80/picamera/issues/488
      It seems that your camera is already being used on the background.
      You need to close the camera instance by using: camera.close()
      Take a look at this link, I think this may be the solution:
      raspberrypi.org/forums/viewtopic.php?t=155304
      Then, to prevent this from happening again, I suggest adding the camera.close() at the end of the camera streaming script.
      I hope this helps.
      Regards,
      Sara 🙂

    • Hi.
      For adjusting the exposure using the picamera library, take a look at the following documentation:
      – picamera.readthedocs.io/en/release-1.10/api_camera.html#picamera.camera.PiCamera.exposure_mode
      – picamera.readthedocs.io/en/release-1.13/recipes1.html#capturing-consistent-images
      Regards,
      Sara

  20. Thank you for the great tutorial
    i also want to ask “how can i display sensor data(ex . temperature) along side the camera feed?” . i am still new to python programming dont know much about the libraries used in program .

    • Hi.
      Thank you for following our tutorials.
      Unfortunately, we don’t have information about what you’re looking for.
      I think the information on the following link is a good starting point
      raspberrypi.org/forums/viewtopic.php?t=35487
      I hope this helps.
      Regards,
      Sara

  21. First of all I would like to thank you for giving such a helpful content. I wanted to add led light (powered by the raspberry pi) in front of the pi camera, but I do not know how to turn on and off using the webpage. I need help to control the led from the same page (streaming webpage) by adding some buttons.
    thank you in advance.

  22. hi, it worked very well in the first attempt, after trying for hours with other codes.
    thank you. but, can u help me with how the code works?

    • Hi Tharun.
      Thank you for your interest, but we we don’t have any code explanation for this specific project.
      Regards,
      Sara

  23. hey.. i want a code which can perform video streaming meanwhile save the videos of previous days i.e; the picamera has to save the videos daily while its streaming…..

  24. Worked like a charm !!

    The only change I had to make was on this line:

    # removing the parameters.
    with picamera.Camera() as camera:

    Thank you for the excellent tutorial !

  25. Hi Rui/Sara

    Great tutorial as many others, i dabble about with raspberry pi’s alot, but i am not very techie or coder.
    I installed your rpi_camera_surveillance_system.py and is working great, but my question is can i add to the script to have email notification with a picture as if a button was pressed like a doorbell.

    I have tried motion and motioneye but did not get on with them.

    Regards
    Tony

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.