Módulo de Cámara de Raspberry Pi

» Más ejemplos

Te mostramos el código en Python y la configuración necesaria para hacer streaming de video con el Módulo de Cámara de Raspberry Pi. Esto es posible con todos los modelos que tengan el puerto de conexión de la cámara.

  • Los modelos Raspberry Pi 3, 4 Model B
  • El modelo más pequeño, la Raspberry Pi Zero W
Streaming con El Módulo de Cámara de Raspberry Pi
Streaming con El Módulo de Cámara de Raspberry Pi

Configurar la Raspberry Pi

Si vas a usar el módulo de cámara Raspberry Pi, debes habilitarlo antes en la Raspberry. En el entorno de escritorio, debes abrir la ventana de Configuración de Raspberry Pi en el menú Preferencias, abrir la pestaña «Interfaces» y habilitar la Cámara como se muestra en la siguiente figura:

Raspberry Configuración de Cámara
Raspberry Configuración de Cámara desde Escritorio

O bien puedes hacerlo desde consola usando el comando «raspi-config«:

pi@raspberry:~ $ sudo raspi-config

Te aparecerá el panel de configuración de Raspberry que puedes navegar con la ayuda de las teclas arriba y abajo. Selecciona Interface Options.

Configuración de Raspberry Pi – Interface Options

Posteriormente selecciona «P1 Camera» y habilita la conexión con la cámara.

Configuración de Raspberry Pi – Camera
Configuración de Raspberry Pi – Camera

El Código para hacer Streaming en Raspberry

Te mostramos y explicamos el código en Python.

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

#decodigo.com

PAGE="""\
<html>
<head>
<title>Raspberry Pi - Stream de Video</title>
</head>
<body>
<center><h1>Raspberry Pi - Streaming de Video</h1></center>
<center>Surveillance Camera</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'):
            #Frame nuevo, copia el contenido existente del buffer y notifica a todos los clientes que esta disponible
            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('Removiendo al cliente de streaming %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()
    #Si es necesario rotar la imagen de la camara, descomenta la siguiente linea
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

En la primera sección del código definimos la página HTML en la variable PAGE, esto permitirá mostrar el streaming de video de la cámara.

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

Creamos una clase StreamingOutput que nos permita hacer streaming de video.

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'):
            #Frame nuevo, copia el contenido existente del buffer y notifica a todos los clientes que esta disponible
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

La clase StreamingHandler nos permite dar respuesta a las peticiones del navegador:

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('Removiendo al cliente de streaming %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

La clase StreamingServer nos permite crear hilos de ejecución para cada petición del usuario desde el navegador:

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

Finalmente, inicializamos la cámara y levantamos nuestro servidor Web para comenzar con el streaming.

with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
    output = StreamingOutput()
    #Si es necesario rotar la imagen de la camara, descomenta la siguiente linea
    #camera.rotation = 90
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()

Ejecutar el script y visualizar el resultado en el Navegador

Antes de ejecutar el script asegúrate de saber la IP de tu Raspberry, ejecutando el comando ‘ifconfig‘:

pi@raspberry:~ $ ifconfig

En mi caso he llamado a mi archivo camara_stream.py, al ejecutar el script con Python nuestro Servidor Web comenzará a ejecutarse indefinidamente.

pi@raspberrypi:~/Documents/inicio $ python3 camara_stream.py

El resultado cuando escribas la URL en el navegador ‘http://la_ip_de_tu_raspberry:8000/‘ reemplazando la IP de la Raspberri Pi es el siguiente:

Imagen de Video Streaming con la cámara de la Raspberry Pi

El Módulo de Cámara de Raspberry Pi es muy fácil de instalar y de usar. Aunque no es de la mejor calidad, es posible darle usos bastante prácticos.

Más información en la página oficial: https://projects.raspberrypi.org/en/projects/getting-started-with-picamera