You dont have javascript enabled! Please enable it!

Caso práctico: MJPEG con cámara CSI en Raspberry Pi Zero W

Caso práctico: MJPEG con cámara CSI en Raspberry Pi Zero W — hero

Objetivo y caso de uso

Qué construirás: Un servidor web MJPEG que transmite video en tiempo real desde una Raspberry Pi Zero W con Camera Module v2.

Para qué sirve

  • Transmisión de video en tiempo real para monitoreo remoto de espacios.
  • Integración en sistemas de domótica para visualización de cámaras de seguridad.
  • Proyectos de robótica donde se requiere streaming de video en vivo.
  • Aplicaciones de telemedicina que permiten la supervisión visual de pacientes.

Resultado esperado

  • Latencia de transmisión menor a 100 ms.
  • Capacidad de manejar al menos 5 conexiones simultáneas sin pérdida de calidad.
  • FPS (fotogramas por segundo) estables en 30 FPS durante la transmisión.
  • Consumo de ancho de banda de aproximadamente 1.5 Mbps por flujo de video.

Público objetivo: Desarrolladores y entusiastas de la tecnología; Nivel: Avanzado

Arquitectura/flujo: Raspberry Pi Zero W con Camera Module v2 -> Servidor Flask -> Transmisión MJPEG a través de HTTP.

Nivel: Avanzado

Prerrequisitos

Este caso práctico está verificado y documentado específicamente para el modelo “Raspberry Pi Zero W + Camera Module v2 (IMX219)”, orientado a montar un servidor web que publique un stream MJPEG (multipart/x-mixed-replace) vía CSI. Se asume que trabajas con la pila actual basada en libcamera (sin el stack “legacy”).

  • Sistema operativo
  • Raspberry Pi OS Bookworm Lite (32-bit, armhf). El Pi Zero W no soporta 64-bit; Bookworm 32-bit incluye Python 3.11 por defecto.
  • Imagen recomendada (ejemplo): 2024-10-22 o posterior.
  • Kernel Linux: 6.6.x (cualquiera de la serie estable incluida con la imagen anterior).
  • Toolchain y versiones probadas (recomendadas para reproducibilidad)
  • Python: 3.11.2 (Bookworm)
  • Pip: 23.2.1
  • Venv: 3.11 (módulo estándar)
  • GCC: 12.2.0 (Debian 12)
  • CMake: 3.25.1
  • libcamera: 0.0.5+ (paquetes de Raspberry Pi OS Bookworm; ver sección de validación para comprobar versión local)
  • libcamera-apps: 0.0.5+ (rpi)
  • python3-picamera2: 0.3.16–0.3.17 (del repo Raspberry Pi OS)
  • Flask: 2.3.3 (pip)
  • Pillow: 10.3.0 (pip, vía piwheels)
  • Waitress: 2.1.2 (pip, servidor WSGI puro Python, apto para stream chunked)
  • Red y acceso
  • Wi‑Fi configurado (2.4 GHz), IP accesible desde tu PC.
  • Acceso SSH habilitado o terminal local con teclado/monitor.
  • Conocimientos previos
  • Linux y shell en Raspberry Pi.
  • Python 3.11, virtualenvs, pip.
  • Conceptos básicos de HTTP y streaming MJPEG.

Comando para verificar versiones (ejecútalos y anota tu entorno real):

python3 --version
pip3 --version
gcc --version | head -n1
cmake --version | head -n1
apt-cache policy libcamera0 libcamera-apps python3-picamera2 | sed -n '1,6p'

Materiales

  • Raspberry Pi Zero W (modelo exacto).
  • Camera Module v2 (sensor Sony IMX219, con cable CSI de 15 pines).
  • Tarjeta microSD (≥ 16 GB, clase A1/A2 preferible).
  • Fuente de alimentación: 5 V / 2 A micro-USB.
  • Cable plano CSI adecuado para Pi Zero W (el conector es de tamaño “corto”, suele venir con la cámara; si no, compra el cable específico para Zero).
  • Adaptador micro-USB OTG (opcional, para teclado/USB si no usas SSH).
  • PC para flashear la imagen de Raspberry Pi OS Bookworm Lite (32-bit).

Nota: Este proyecto no requiere hardware adicional de E/S GPIO; todo el flujo es CSI → ISP/libcamera → servidor HTTP.

Preparación y conexión

Preparación del sistema

  1. Flashea Raspberry Pi OS Bookworm Lite (32-bit) en la microSD con Raspberry Pi Imager.
  2. Selecciona: Raspberry Pi OS Lite (32-bit) — Bookworm.
  3. Configura en Imager (opciones avanzadas): hostname, usuario, contraseña, Wi‑Fi y SSH.
  4. Inserta la microSD en la Raspberry Pi Zero W.
  5. Conecta la alimentación y espera el primer arranque.

Conexión de la cámara CSI

  • Apaga completamente la Raspberry Pi antes de manipular la cámara.
  • Localiza el conector CSI de la Raspberry Pi Zero W (interfaz de cámara).
  • Inserta el cable plano:
  • Contactos del cable hacia los contactos del conector CSI.
  • Bloquea la pestaña con cuidado para que no se suelte.
  • Conecta el otro extremo al Camera Module v2 respetando la orientación (contactos a contactos).
  • Enciende la Raspberry Pi.

Tabla de puertos y orientación (Pi Zero W + Camera Module v2)

Elemento Conector/Ubicación Detalle/Orientación
CSI (cámara) ZIF 15 pines (lado cámara) Alinear contactos del cable con los del ZIF; cerrar pestaña de bloqueo
Alimentación micro-USB (PWR IN) 5 V / 2 A recomendado
USB OTG (periféricos) micro-USB (USB) Para teclado/mouse/USB (opcional)
Tarjeta microSD Ranura microSD Insertar con la cara de contactos hacia la placa
LED estado PCB Útil para ver actividad del sistema

Habilitar interfaces y cámara (Bookworm)

En Bookworm con libcamera, normalmente no es necesario habilitar “Legacy Camera”. Aun así, verifica:

  • Opción A: raspi-config
  • sudo raspi-config
  • Interface Options:
    • I2C: Enable (útil para periféricos; no estrictamente necesario para libcamera, pero conveniente).
    • Legacy Camera: Disabled (para mantener libcamera).
  • Localisation Options: ajusta zona horaria y teclado si lo necesitas.
  • Finish y reboot.

  • Opción B: edición de /boot/firmware/config.txt

  • sudo nano /boot/firmware/config.txt
  • Asegúrate de tener (o añade) las líneas:
    camera_auto_detect=1
    # Forzar overlay del sensor si fuese necesario:
    # dtoverlay=imx219
  • Guarda y reinicia: sudo reboot

Comprobación rápida de la cámara con libcamera:

libcamera-hello -t 2000

Deberías ver en consola que se abre la cámara (en Pi Zero W sin pantalla HDMI, la aplicación igualmente informa si detecta el sensor). Si falla, revisa Troubleshooting.

Código completo

Implementaremos un servidor web Python que:
– Inicializa Picamera2 con una configuración “video-like” a baja resolución para la CPU del Pi Zero W.
– Captura frames periódicamente como arrays RGB.
– Codifica cada frame a JPEG con Pillow (calidad ajustable).
– Expone:
– /stream.mjpg → MJPEG multipart (para navegadores y VLC).
– /snapshot.jpg → fotograma actual (single shot).
– /health → estado simple.

Notas de diseño:
– Elegimos 640×480 a ~8–10 fps para un equilibrio entre CPU/latencia/calidad en el Zero W.
– Creamos un hilo productor que inserta frames JPEG en una cola bounded (drop-old) para evitar backlog.
– Usamos Flask por sencillez y Waitress como servidor WSGI robusto en producción ligera (ambos Python puro).

Estructura del proyecto

  • ~/mjpeg-csi/
  • app.py
  • .env (opcional, variables de configuración)
  • venv/ (virtualenv con paquetes pip)
  • run.sh (opcional, arranque)
  • servicio systemd (descrito más adelante)

app.py

#!/usr/bin/env python3
import io
import os
import signal
import threading
import time
from queue import Queue, Full, Empty
from typing import Generator, Optional

from flask import Flask, Response, jsonify, stream_with_context
from PIL import Image
from picamera2 import Picamera2

# Configuración desde entorno (con valores por defecto seguros para Pi Zero W)
WIDTH = int(os.getenv("MJPEG_WIDTH", "640"))
HEIGHT = int(os.getenv("MJPEG_HEIGHT", "480"))
FPS = float(os.getenv("MJPEG_FPS", "8"))  # 8 fps razonable en Zero W
JPEG_QUALITY = int(os.getenv("MJPEG_QUALITY", "70"))  # 50-80 recomendado
BOUNDARY = os.getenv("MJPEG_BOUNDARY", "frameboundary")
PORT = int(os.getenv("MJPEG_PORT", "8080"))
HOST = os.getenv("MJPEG_HOST", "0.0.0.0")
QUEUE_SIZE = int(os.getenv("MJPEG_QUEUE_SIZE", "2"))
CAPTURE_SLEEP = float(os.getenv("MJPEG_CAPTURE_SLEEP", str(1.0 / FPS)))

app = Flask(__name__)

# Cola de frames JPEG
frame_queue: "Queue[bytes]" = Queue(maxsize=QUEUE_SIZE)
shutdown_event = threading.Event()


def camera_thread():
    """
    Hilo productor:
    - Inicializa Picamera2
    - Captura arrays RGB a la resolución dada
    - Codifica a JPEG con Pillow
    - Inserta frames a la cola con política drop-old
    """
    picam2 = Picamera2()

    # Configuración "video" con salida RGB888 para codificar fácilmente a JPEG
    video_config = picam2.create_video_configuration(
        main={"size": (WIDTH, HEIGHT), "format": "RGB888"},
        transform=None  # sin rotación
    )
    picam2.configure(video_config)

    # Ajustes de control (opcionales)
    # Nota: En Zero W, mantener autoexposición/awb suele ser suficiente
    # picam2.set_controls({"AwbEnable": True, "AeEnable": True})

    picam2.start()
    try:
        while not shutdown_event.is_set():
            # Captura frame como array RGB
            frame = picam2.capture_array("main")

            # Codifica a JPEG
            with io.BytesIO() as buf:
                # Pillow espera array en RGB ordenado (ya lo tenemos)
                Image.fromarray(frame).save(
                    buf, format="JPEG", quality=JPEG_QUALITY, optimize=True
                )
                jpg = buf.getvalue()

            # Inserta en la cola, descartando el más antiguo si está llena
            try:
                frame_queue.put(jpg, timeout=0.01)
            except Full:
                try:
                    frame_queue.get_nowait()
                except Empty:
                    pass
                # Reintenta tras descartar
                try:
                    frame_queue.put_nowait(jpg)
                except Full:
                    pass

            # Ritmo de captura
            if CAPTURE_SLEEP > 0:
                time.sleep(CAPTURE_SLEEP)
    finally:
        picam2.stop()


def mjpeg_generator() -> Generator[bytes, None, None]:
    """
    Generador de stream MJPEG en formato multipart/x-mixed-replace.
    Cada iteración produce:
    --BOUNDARY
    Content-Type: image/jpeg
    Content-Length: <n>

    <bytes JPEG>
    """
    boundary_bytes = BOUNDARY.encode("ascii")
    while not shutdown_event.is_set():
        try:
            jpg = frame_queue.get(timeout=1.0)
        except Empty:
            continue

        header = (
            b"--" + boundary_bytes + b"\r\n"
            b"Content-Type: image/jpeg\r\n"
            b"Content-Length: " + str(len(jpg)).encode("ascii") + b"\r\n\r\n"
        )
        yield header + jpg + b"\r\n"


@app.route("/stream.mjpg")
def stream():
    return Response(
        stream_with_context(mjpeg_generator()),
        mimetype=f"multipart/x-mixed-replace; boundary={BOUNDARY}",
    )


@app.route("/snapshot.jpg")
def snapshot():
    # Toma el último frame disponible (o espera un poco)
    try:
        jpg = frame_queue.get(timeout=2.0)
    except Empty:
        return Response(status=503)
    return Response(jpg, mimetype="image/jpeg")


@app.route("/health")
def health():
    return jsonify(
        status="ok",
        width=WIDTH,
        height=HEIGHT,
        fps=FPS,
        quality=JPEG_QUALITY,
        queue_size=QUEUE_SIZE,
        boundary=BOUNDARY,
    )


def handle_sigterm(signum, frame):
    shutdown_event.set()


def main():
    # Inicia el hilo de cámara
    t = threading.Thread(target=camera_thread, name="camera-thread", daemon=True)
    t.start()

    # Señales para apagado limpio
    signal.signal(signal.SIGTERM, handle_sigterm)
    signal.signal(signal.SIGINT, handle_sigterm)

    # Servidor WSGI
    use_waitress = os.getenv("USE_WAITRESS", "1") == "1"
    if use_waitress:
        try:
            from waitress import serve
            # threads controla peticiones concurrentes (streams simultáneos)
            serve(app, host=HOST, port=PORT, threads=4)
        except Exception as e:
            print(f"[waitress] Error: {e}; usando servidor Flask de desarrollo.")
            app.run(host=HOST, port=PORT, threaded=True)
    else:
        app.run(host=HOST, port=PORT, threaded=True)

    shutdown_event.set()
    t.join(timeout=2.0)


if __name__ == "__main__":
    main()

Puntos clave del código:
– create_video_configuration con formato RGB888 simplifica la compresión JPEG con Pillow. Para el Zero W, bajar resolución o FPS si ves CPU alta.
– Cola bounded con política drop-old para minimizar latencia en el stream.
– Endpoints claros y reusables en validación.
– Waitress para servir responses “chunked” eficientes y estables; en caso de fallo, usa el servidor de desarrollo de Flask.

Compilación/flash/ejecución

A continuación, pasos reproducibles, exactos y ordenados.

1) Actualización de sistema y paquetes base

sudo apt update
sudo apt full-upgrade -y
sudo reboot

2) Instalar dependencias del sistema

  • libcamera y herramientas, Picamera2, Python 3.11, venv y utilidades:
sudo apt install -y \
  libcamera-apps \
  python3-picamera2 \
  python3-pip \
  python3-venv \
  python3-numpy \
  git \
  gcc \
  cmake

Comprobación rápida de cámara:

libcamera-hello -t 2000

Si ves que abre la cámara sin error, continúa.

3) Preparar directorio de proyecto y virtualenv

mkdir -p ~/mjpeg-csi
cd ~/mjpeg-csi
python3 -m venv --system-site-packages venv
source venv/bin/activate

Usamos –system-site-packages para que el venv vea python3-picamera2 instalado por apt.

4) Configurar piwheels y pip

Piwheels acelera instalación en Raspberry Pi y ofrece ruedas para ARMv6 (Zero W).

pip install --upgrade pip==23.2.1
pip config set global.index-url https://www.piwheels.org/simple

5) Instalar dependencias Python (pinned)

pip install \
  Flask==2.3.3 \
  Pillow==10.3.0 \
  waitress==2.1.2

Comprueba versiones:

python -c "import flask, PIL; import waitress; \
print('Flask', flask.__version__); \
print('Pillow', PIL.__version__); \
import pkgutil; import waitress; print('Waitress', waitress.__version__)"

6) Crear el archivo app.py

Copia el contenido de la sección anterior en:

nano app.py
# pega el código, guarda con Ctrl+O y sal con Ctrl+X

Dale permisos de ejecución:

chmod +x app.py

7) Ejecutar en modo desarrollo (prueba rápida)

source venv/bin/activate
export USE_WAITRESS=0
python app.py

Abre desde tu PC:
– Stream MJPEG: http://:8080/stream.mjpg
– Snapshot: http://:8080/snapshot.jpg
– Salud: http://:8080/health

Para detener: Ctrl+C.

8) Ejecutar con Waitress (recomendado para uso continuado)

source venv/bin/activate
export USE_WAITRESS=1
python app.py

Si todo funciona, automatiza con systemd.

9) Systemd service para autoarranque

Crea el servicio:

sudo tee /etc/systemd/system/mjpeg-csi.service >/dev/null <<'EOF'
[Unit]
Description=Servidor MJPEG (Picamera2) en Raspberry Pi Zero W
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/mjpeg-csi
Environment="USE_WAITRESS=1"
Environment="MJPEG_WIDTH=640"
Environment="MJPEG_HEIGHT=480"
Environment="MJPEG_FPS=8"
Environment="MJPEG_QUALITY=70"
Environment="MJPEG_PORT=8080"
Environment="MJPEG_HOST=0.0.0.0"
Environment="MJPEG_QUEUE_SIZE=2"
Environment="MJPEG_BOUNDARY=frameboundary"
Environment="MJPEG_CAPTURE_SLEEP=0.125"
ExecStart=/home/pi/mjpeg-csi/venv/bin/python /home/pi/mjpeg-csi/app.py
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Recarga, habilita e inicia:

sudo systemctl daemon-reload
sudo systemctl enable --now mjpeg-csi.service
systemctl status mjpeg-csi.service --no-pager

Valida en el navegador: http://:8080/stream.mjpg

Validación paso a paso

  1. Comprobación de hardware CSI:
  2. Cámara correctamente conectada (cable firme, pestañas ZIF cerradas).
  3. Reinicio tras conexión.

  4. Comprobación libcamera:

  5. libcamera-hello -t 2000 no debe mostrar “No cameras available”.
  6. libcamera-hello --version muestra versión de libcamera-apps. Ejemplo:

    • libcamera-apps version 1.1.x (en Bookworm, varía según build de RPi OS).
  7. Comprobación de Picamera2 en Python:

  8. Inicia Python: python -c "from picamera2 import Picamera2; print('OK picamera2')".

  9. Arranque de servidor:

  10. systemctl status mjpeg-csi.service → “active (running)”.
  11. Logs iniciales en journalctl -u mjpeg-csi.service -n 50 --no-pager.

  12. Conectividad:

  13. curl -sI http://<IP>:8080/health → HTTP/1.1 200 OK y JSON con parámetros.
  14. curl -sI http://<IP>:8080/stream.mjpg → Content-Type: multipart/x-mixed-replace; boundary=frameboundary.
  15. curl -o /dev/null http://<IP>:8080/snapshot.jpg -v → Content-Type: image/jpeg.

  16. Visualización:

  17. Navegador (Chrome/Firefox): abrir http://:8080/stream.mjpg; deberías ver vídeo fluido (~8 fps).
  18. VLC: Medio → Abrir ubicación de red → http://:8080/stream.mjpg.
  19. ffplay (opcional en PC): ffplay -fflags nobuffer -flags low_delay -framedrop http://<IP>:8080/stream.mjpg.

  20. Rendimiento en el Zero W:

  21. top o htop: CPU del proceso Python entre 60–95% según calidad/fps/resolución.
  22. Ajusta variables (anchura, altura, FPS, calidad) si observas throttling o cortes.

  23. Persistencia:

  24. Reinicia el Pi: sudo reboot.
  25. Valida que el servicio levanta automáticamente y el stream responde.

Troubleshooting

1) Error: “No cameras available” con libcamera-hello
– Causas:
– Cable CSI mal orientado o suelto.
– Cámara defectuosa.
– dt/config no detecta el sensor.
– Soluciones:
– Apaga, reconecta cable CSI en ambos extremos; verifica orientación de contactos.
– En /boot/firmware/config.txt añade: camera_auto_detect=1 y, si persiste, fuerza dtoverlay=imx219.
– Actualiza firmware: sudo apt update && sudo apt full-upgrade -y && sudo reboot.

2) ImportError: No module named ‘picamera2’
– Causas: Falta el paquete apt o no se ve desde el venv.
– Solución:
sudo apt install -y python3-picamera2
– Crea el venv con --system-site-packages y actívalo de nuevo.
– Comprueba en Python: from picamera2 import Picamera2.

3) “Address already in use” al arrancar el servidor
– Causa: Puerto 8080 ocupado.
– Solución:
– Cambia MJPEG_PORT (p. ej., 8081) en el servicio systemd y systemctl daemon-reload && systemctl restart mjpeg-csi.service.
– Verifica puertos: ss -ltnp | grep :8080.

4) Latencia alta o stream entrecortado
– Causas: CPU saturada (Zero W es limitado).
– Ajustes:
– Reduce resolución: MJPEG_WIDTH=426, MJPEG_HEIGHT=240.
– Baja FPS: MJPEG_FPS=6 (y MJPEG_CAPTURE_SLEEP acorde ~0.166).
– Baja calidad JPEG: MJPEG_QUALITY=60.
– Verifica Wi‑Fi (RSSI) y evita congestión 2.4 GHz.

5) Imagen muy oscura/borrosa
– Causas: Iluminación insuficiente, exposiciones largas.
– Soluciones:
– Mejora iluminación.
– Baja FPS (para permitir mayor exposición) o considera fijar controles en Picamera2 (AeEnable=True, ISO).
– Limpia el protector/óptica.

6) Waitress no responde al stream tras varios clientes
– Causas: Límite de threads insuficiente en Waitress vs. clientes simultáneos.
– Solución:
– Incrementa threads en el servicio (p. ej., 6–8).
– Recuerda que más clientes aumentan la carga en CPU.

7) El stream no abre en Safari/iOS
– Causas: Implementación MJPEG y/o caché.
– Soluciones:
– Asegura cabecera correcta multipart con boundary constante (ya lo hace el código).
– Prueba otra app (VLC) o un navegador alternativo; Safari a veces interrumpe MJPEG en ciertas condiciones de red.

8) “Broken pipe” o desconexiones frecuentes
– Causas: Cortes Wi‑Fi, clientes que cierran y servidor aún enviando frames.
– Soluciones:
– Estas excepciones suelen ser benignas; observa logs y mantén la red estable.
– Reduce FPS/Quality para ahorrar ancho de banda.

Mejoras/variantes

  • Encoder alternativo con MJPEGEncoder de Picamera2:
  • Implementar un Output personalizado que reciba frames JPEG directos del encoder, reduciendo CPU. Requiere profundizar en la API de encoders/outputs de Picamera2.
  • Doble endpoint con distintas calidades:
  • /stream_small.mjpg (426×240 @ 8 fps, Q=60)
  • /stream_large.mjpg (640×480 @ 8 fps, Q=75) si la CPU lo permite.
  • Autenticación básica:
  • Añade un decorador simple o usa un reverse proxy Nginx con auth.
  • HTTPS:
  • Coloca Nginx delante (TLS) y haz proxy_pass a 127.0.0.1:8080.
  • Control de cámara:
  • Endpoints para cambiar parámetros en vivo (FPS, calidad), guardándolos en un archivo .env.
  • Grabación puntual:
  • Endpoint /record?n=10 para capturar N segundos a JPEGs o MKV con ffmpeg (ojo con carga del Zero W).
  • Métricas:
  • Exponer /metrics con tiempos de frame, colas, uso de CPU (psutil).

Checklist de verificación

  • [ ] Hardware:
  • [ ] Raspberry Pi Zero W con fuente 5 V/2 A estable.
  • [ ] Camera Module v2 con cable CSI bien orientado y pestillos cerrados.
  • [ ] microSD con Raspberry Pi OS Bookworm Lite (32-bit).
  • [ ] Sistema:
  • [ ] sudo apt update && sudo apt full-upgrade -y ejecutado sin errores.
  • [ ] libcamera-hello -t 2000 detecta la cámara.
  • [ ] Toolchain / Paquetes:
  • [ ] python3-picamera2 instalado por apt.
  • [ ] venv creado con –system-site-packages.
  • [ ] pip configurado con piwheels.
  • [ ] Flask==2.3.3, Pillow==10.3.0, Waitress==2.1.2 instalados.
  • [ ] Código:
  • [ ] app.py creado y ejecutable.
  • [ ] Variables (MJPEG_WIDTH/HEIGHT/FPS/QUALITY) ajustadas a tu entorno.
  • [ ] Ejecución:
  • [ ] python app.py entrega /health con status ok.
  • [ ] /stream.mjpg visible en navegador o VLC.
  • [ ] /snapshot.jpg devuelve un JPEG válido.
  • [ ] Servicio:
  • [ ] systemd mjpeg-csi.service en estado “active (running)”.
  • [ ] Arranca al boot y responde tras reinicio.
  • [ ] Rendimiento:
  • [ ] CPU en rango aceptable; si no, reduce resolución/FPS/calidad.
  • [ ] Sin cortes frecuentes; Wi‑Fi estable.

Con este caso práctico, dispones de un servidor web MJPEG eficiente y reproducible con el conjunto “Raspberry Pi Zero W + Camera Module v2” usando la pila libcamera y Python 3.11 en Raspberry Pi OS Bookworm (32-bit). Si en el futuro migras a placas más potentes (por ejemplo, Pi 3/4/5), puedes incrementar resolución, FPS y calidad, o sustituir la compresión por encoders más exigentes sin alterar la arquitectura básica del servidor.

Encuentra este producto y/o libros sobre este tema en Amazon

Ir a Amazon

Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.

Quiz rápido

Pregunta 1: ¿Cuál es el sistema operativo recomendado para el Raspberry Pi Zero W?




Pregunta 2: ¿Qué versión de Python se recomienda utilizar?




Pregunta 3: ¿Cuál es la versión mínima de GCC recomendada?




Pregunta 4: ¿Qué comando se utiliza para verificar la versión de libcamera?




Pregunta 5: ¿Qué tipo de red se debe configurar para el Raspberry Pi Zero W?




Pregunta 6: ¿Qué herramienta se recomienda para el servidor WSGI puro Python?




Pregunta 7: ¿Cuál es la versión de Flask que se debe utilizar?




Pregunta 8: ¿Qué módulo de Python se recomienda para la cámara?




Pregunta 9: ¿Qué tipo de streaming se menciona en el artículo?




Pregunta 10: ¿Cuál es la imagen recomendada para el Raspberry Pi Zero W?




Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio