32blogby StudioMitsu

Cómo recibir, convertir y transmitir cámaras RTSP con FFmpeg

Aprende a recibir, grabar y convertir streams RTSP a HLS con FFmpeg 8.0. Cubre fundamentos del protocolo, solución de problemas y aceleración GPU.

11 min read
Contenido

Quieres ver la imagen de tu cámara IP en un navegador. Grabarla. Quizás combinar varias cámaras en un solo panel. El soporte RTSP de FFmpeg hace todo esto posible.

RTSP (Real-Time Streaming Protocol) es el estándar de facto para cámaras IP, pero los navegadores no pueden reproducir streams RTSP directamente. Usando FFmpeg como intermediario para convertir RTSP a HLS (HTTP Live Streaming), puedes mostrar las imágenes de la cámara en cualquier dispositivo con navegador.

Este artículo te guía desde los fundamentos del protocolo RTSP hasta la recepción, grabación y conversión de streams con FFmpeg, incluyendo solución de problemas y optimización del rendimiento.

Qué es RTSP — Fundamentos del protocolo explicados

RTSP (Real-Time Streaming Protocol) es un protocolo para controlar streams de medios a través de una red. Fue estandarizado en RFC 2326 (1998) y posteriormente revisado en RFC 7826 (RTSP 2.0, 2016).

El punto clave es que RTSP no transporta los datos multimedia en sí. Piensa en RTSP como un control remoto: envía comandos como PLAY, PAUSE y TEARDOWN. Los datos reales de vídeo y audio fluyen por separado a través de RTP (Real-time Transport Protocol).

RTSP (TCP:554)
Client(FFmpeg)
DESCRIBE
SDP Response
SETUP
PLAY
RTP (video)
RTCP (ctrl)
Camera(Server)

El flujo de intercambio funciona así:

  1. DESCRIBE: El cliente pregunta al servidor qué streams están disponibles. El servidor responde con SDP (Session Description Protocol) que contiene el códec, resolución, números de puerto, etc.
  2. SETUP: Se negocia el método de transporte (UDP o TCP)
  3. PLAY: Comienza la transmisión. Los datos RTP empiezan a fluir
  4. TEARDOWN: Finaliza la sesión

Formatos de URL RTSP

Cada fabricante de cámaras usa un formato de URL diferente. Estos son los patrones de las principales marcas:

bash
# Hikvision — Canal 101 es el stream principal, 102 es el secundario
rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101

# Dahua — channel=1&subtype=0 es el stream principal
rtsp://admin:password@192.168.1.108:554/cam/realmonitor?channel=1&subtype=0

# ONVIF genérico — la mayoría de cámaras lo soportan
rtsp://admin:password@192.168.1.100:554/onvif1

# Tapo (TP-Link) — stream1 es principal, stream2 es secundario
rtsp://admin:password@192.168.1.200:554/stream1

# Cámara USB (v4l2 en Linux) — no es RTSP pero FFmpeg puede capturar directamente
# /dev/video0

Preparación del entorno — Verificar soporte RTSP en FFmpeg 8.0.1

El soporte RTSP viene incluido en las compilaciones estándar de FFmpeg. No se necesitan flags de compilación especiales, pero verifiquemos.

bash
# Verificar versión de FFmpeg
ffmpeg -version
# ffmpeg version 8.0.1 Copyright (c) 2000-2025 the FFmpeg developers

# Verificar que el protocolo RTSP está disponible
ffmpeg -protocols 2>/dev/null | grep rtsp
# Input:  rtsp
# Output: rtsp

# Verificar que el decodificador H.264 está disponible
ffmpeg -decoders 2>/dev/null | grep h264
# V..... h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10

Si los tres comandos producen salida, estás listo.

Prueba de conexión

Antes de intentar cualquier conversión, verifica que el stream es accesible usando ffprobe.

bash
ffprobe -rtsp_transport tcp \
  "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101"

Una respuesta exitosa se ve así:

Input #0, rtsp, from 'rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101':
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: h264 (Main), yuv420p, 1920x1080, 25 fps
  Stream #0:1: Audio: aac (LC), 16000 Hz, mono, fltp

El flag -rtsp_transport tcp se explica más adelante. Si no puedes obtener información del stream aquí, salta a la sección "Errores comunes y cómo solucionarlos".

Recibir y grabar un stream RTSP

Empecemos con el caso más simple: guardar un stream RTSP directamente en un archivo.

Guardar sin recodificar (-c copy)

bash
ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c copy \
  -t 60 \
  output.mp4
OpciónPropósito
-rtsp_transport tcpUsar TCP para la transferencia de datos RTSP (explicado después)
-i "rtsp://..."URL RTSP de la fuente de entrada
-c copyCopiar vídeo y audio sin recodificar (uso de CPU casi nulo)
-t 60Grabar durante 60 segundos y parar

El flag -c copy preserva el stream H.264/H.265 original de la cámara sin pérdida de calidad y con uso de CPU casi nulo. Para una explicación detallada de cada opción, consulta el Tutorial de uso de FFmpeg.

Grabar indefinidamente (detener con Ctrl+C)

bash
ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c copy \
  -movflags +faststart \
  recording_$(date +%Y%m%d_%H%M%S).mp4

El flag -movflags +faststart mueve el moov atom (metadatos) al principio del archivo, permitiendo su reproducción en navegadores incluso durante la grabación. Sin embargo, si FFmpeg no se termina correctamente (con Ctrl+C), el archivo puede corromperse.

Grabación continua segmentada

Para grabación 24/7, un solo archivo grande no es práctico. Usa -f segment para dividir por tiempo.

bash
ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c copy \
  -f segment \
  -segment_time 3600 \
  -segment_format mp4 \
  -reset_timestamps 1 \
  -strftime 1 \
  "recordings/cam01_%Y%m%d_%H%M%S.mp4"

Esto crea un nuevo archivo cada hora (3600 segundos) con nombres como cam01_20260312_140000.mp4. El flag -strftime 1 habilita nombres de archivo basados en marcas de tiempo.

Convertir RTSP a HLS en tiempo real

Cuando quieres ver las cámaras en vivo en un navegador, necesitas conversión HLS. HLS (HTTP Live Streaming) divide el vídeo en segmentos cortos servidos por HTTP, y es compatible con prácticamente todos los navegadores. Para un análisis profundo de HLS, consulta Cómo transmitir vídeo HLS con FFmpeg y un CDN.

El flujo de datos completo se ve así:

IP CameraRTSP ServerRTSPFFmpegTranscodeWriteHLS Files.m3u8 + .tsHTTPBrowserhls.js

Comando básico de conversión HLS

bash
mkdir -p /var/www/hls/cam01

ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c:v copy \
  -c:a aac -b:a 128k \
  -f hls \
  -hls_time 2 \
  -hls_list_size 10 \
  -hls_flags delete_segments+append_list \
  -hls_segment_filename "/var/www/hls/cam01/seg_%03d.ts" \
  "/var/www/hls/cam01/index.m3u8"
OpciónPropósito
-c:v copyPasar el vídeo H.264 de la cámara sin recodificar
-c:a aacConvertir audio a AAC para compatibilidad con navegadores
-f hlsEstablecer formato de salida como HLS
-hls_time 2Establecer duración de cada segmento en 2 segundos
-hls_list_size 10Mantener 10 segmentos en la playlist (20 segundos recientes)
-hls_flags delete_segmentsEliminar automáticamente segmentos antiguos para ahorrar disco
-hls_flags append_listAñadir a la playlist en vez de sobrescribir

Sirve el index.m3u8 generado a través de un servidor web (como Nginx) y podrás ver la cámara en el navegador.

Configuración de Nginx

nginx
server {
    listen 8080;
    server_name localhost;

    location /hls/ {
        alias /var/www/hls/;
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        add_header Cache-Control "no-cache";
        add_header Access-Control-Allow-Origin "*";
    }
}

Navega a http://ip-servidor:8080/hls/cam01/index.m3u8 en tu navegador. Safari soporta HLS nativamente; Chrome y Firefox necesitan una librería como hls.js.

Cuándo es necesario recodificar

Si tu cámara transmite en H.265 (HEVC), el soporte en navegadores es limitado. Transcodificar a H.264 es la opción segura.

bash
ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c:v libx264 -preset ultrafast -tune zerolatency -crf 23 \
  -c:a aac -b:a 128k \
  -f hls \
  -hls_time 2 \
  -hls_list_size 10 \
  -hls_flags delete_segments+append_list \
  "/var/www/hls/cam01/index.m3u8"

La combinación -preset ultrafast -tune zerolatency minimiza la latencia, priorizando la entrega en tiempo real sobre la eficiencia de compresión, ideal para vigilancia. Si la carga de CPU es una preocupación, consulta la Guía de aceleración GPU para alternativas con aceleración por hardware.

Errores comunes y cómo solucionarlos

Estos son los problemas más frecuentes con streaming RTSP y cómo resolverlos.

Connection refused / Connection timed out

rtsp://192.168.1.64:554/...: Connection refused

Causa: El servicio RTSP de la cámara está deshabilitado, el número de puerto es incorrecto, o un firewall bloquea la conexión.

Solución:

bash
# Verificar si el puerto está abierto
nc -zv 192.168.1.64 554

# Verificar reglas del firewall (Linux)
sudo iptables -L -n | grep 554

# Verificar que RTSP está habilitado en el panel de administración de la cámara
# Hikvision: Configuración → Red → Configuración avanzada → Puerto → Puerto RTSP

401 Unauthorized

Server returned 401 Unauthorized (all attempts)

Causa: Usuario o contraseña incorrectos.

Solución: Verifica las credenciales RTSP en el panel de administración de tu cámara. La mayoría de cámaras usan las mismas credenciales que la interfaz web, pero algunas requieren cuentas RTSP separadas. También verifica que los caracteres especiales (@, :, /) en la contraseña estén correctamente codificados en URL.

Pérdida de paquetes UDP / Vídeo entrecortado

[rtsp @ 0x...] RTP: dropping old packet received too late

Causa: Se están perdiendo paquetes UDP durante la transferencia. Esto es común en WiFi o al enrutar a través de múltiples saltos de red.

Solución: Cambiar a modo TCP.

bash
# UDP es el predeterminado — cambiar a TCP
ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c copy output.mp4

El flag -rtsp_transport tcp cambia al modo intercalado TCP (RTP sobre TCP). Esto elimina la pérdida de paquetes a costa de una latencia ligeramente mayor. Se recomienda TCP para casos de vigilancia.

Broken pipe / El stream se desconecta repentinamente

Causa: La cámara cerró la conexión por timeout, o la red es inestable.

Solución: Escribir un script de reconexión automática.

bash
#!/bin/bash
RTSP_URL="rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101"
OUTPUT_DIR="/var/www/hls/cam01"

while true; do
  echo "[$(date)] Iniciando FFmpeg..."
  ffmpeg -rtsp_transport tcp \
    -timeout 5000000 \
    -i "$RTSP_URL" \
    -c:v copy -c:a aac \
    -f hls \
    -hls_time 2 \
    -hls_list_size 10 \
    -hls_flags delete_segments+append_list \
    -hls_segment_filename "$OUTPUT_DIR/seg_%03d.ts" \
    "$OUTPUT_DIR/index.m3u8"

  echo "[$(date)] FFmpeg terminó con código $?. Reiniciando en 5 segundos..."
  sleep 5
done

El -timeout 5000000 (5 segundos, en microsegundos) establece el timeout del socket RTSP. Cuando la cámara deja de responder, FFmpeg termina y el bucle while true lo reinicia. Para producción, considera ejecutarlo como un servicio systemd.

Optimización del rendimiento y aceleración GPU

Reducir la carga de CPU

Con -c copy, no hay recodificación y el uso de CPU es casi nulo. Pero si necesitas conversión H.265→H.264 o cambios de resolución, el consumo de CPU aumenta significativamente.

bash
# Monitorear uso de CPU mientras FFmpeg se ejecuta (en otra terminal)
top -p $(pgrep -f ffmpeg)

Consejos para reducir la carga:

  • Usa -preset ultrafast (ligera pérdida de calidad pero velocidad máxima)
  • Reduce la resolución desde la cámara (usa el stream secundario: /Channels/102)
  • Reduce la tasa de fotogramas con -r 15 (15 fps es suficiente para vigilancia)

Aceleración GPU

Si tienes una GPU NVIDIA, NVENC puede descargar casi toda la codificación de la CPU.

bash
ffmpeg -rtsp_transport tcp \
  -i "rtsp://admin:password@192.168.1.64:554/Streaming/Channels/101" \
  -c:v h264_nvenc -preset p4 -tune ll \
  -c:a aac -b:a 128k \
  -f hls \
  -hls_time 2 \
  -hls_list_size 10 \
  -hls_flags delete_segments+append_list \
  "/var/www/hls/cam01/index.m3u8"

El -preset p4 es el preset balanceado de NVENC, y -tune ll habilita el ajuste de baja latencia. Para configuración detallada de codificación GPU y comparaciones entre fabricantes, consulta la Guía de aceleración GPU de FFmpeg.

Optimizar la compresión de vídeo

Cuando el ancho de banda o el almacenamiento es limitado, ajustar los valores CRF y la configuración de bitrate puede ayudar a controlar la compresión. Consulta la Guía de compresión de vídeo con FFmpeg para configuración detallada.

Conclusión

RTSP es el protocolo estándar para cámaras IP, pero los navegadores no pueden reproducirlo directamente. Con FFmpeg puedes:

  • Grabar: Guardar streams con -c copy con uso de CPU casi nulo
  • Convertir a HLS: Conversión en tiempo real con -f hls para reproducción en navegador
  • Operar de forma estable: Modo TCP + scripts de reconexión automática

Cubrimos los patrones de URL RTSP de los principales fabricantes de cámaras (Hikvision, Dahua, dispositivos compatibles con ONVIF). Cuando algo falle, empieza con ffprobe para verificar la conectividad, luego prueba cambiar a modo TCP.

Para los siguientes pasos — integración de múltiples cámaras y acceso remoto seguro mediante VPN — consulta estos artículos relacionados: