Etiquetas: , ,

, ,

En este tutorial, veremos cómo enviar un flujo de vídeo de una máquina a otra utilizando FFMPEG. El envío de datos entre dos dispositivos, sea cual sea, es uno de los principales problemas de los objetos conectados (IoT). Si quieres crear una cámara conectada que envíe vídeo a una máquina remota, este artículo debería interesarte.

Instalación de ffmpeg

En una máquina Linux

sudo apt-get install ffmpeg

En un equipo Windows, siga este procedimiento.

N.B.: si es necesario en una máquina Linux sudo apt-get install v4l-utils

Obtenga la información que necesita para la transmisión de vídeo

Para crear un flujo de vídeo de una máquina a otra, las máquinas deben estar conectadas a la misma red (Wifi o Ethernet).

En primer lugar, es necesario obtener la dirección IP de la máquina cliente (que recibe el flujo)

Introduzca un terminal de comandos

ifconfig #por une machine linux
ip addr # si ifconfig n'est pas disponible 
raspi-ifconfig Transmisión de vídeo entre dos máquinas con FFMPEG

o

ipconfig #por une machine windows
window-ipconfig-ip-subnet-gateway Transmisión de vídeo entre dos máquinas con FFMPEG

Deberá obtener una dirección de la forma 192.168.X.X (en nuestro caso 192.168.1.67)

A continuación, recupere la salida de vídeo. Para listar todas las entradas de vídeo en una máquina Linux

ls -l /dev/video*
lsusb #list usb devices
v4l2-ctl --list-devices #list video devices

Estos comandos deberían ayudarte a identificar la fuente de vídeo. En nuestro caso, /dev/video5

debian-v4l2-list-devices Transmisión de vídeo entre dos máquinas con FFMPEG

Para listar las salidas de vídeo en una máquina Windows, puede utilizar ffmpeg

ffmpeg -list_devices true -f dshow -i dummy

En nuestro caso, video=»USB2.0 HD UVC WebCam «.

ffmpeg-list-devices-windows Transmisión de vídeo entre dos máquinas con FFMPEG

Recuperar las opciones y comprobar los formatos y resoluciones aceptados por la cámara

Linux

v4l2-ctl -d /dev/video0 --list-formats

Windows

ffmpeg -f dshow -list_options true -i video="USB2.0 HD UVC WebCam"

Una vez registrados estos datos, podemos configurar el streaming.

Crear un flujo de vídeo con ffmpeg

Para crear un flujo de vídeo, necesitas un emisor (servidor) y un receptor (cliente) que estarán conectados por dos terminales que se ejecutan en dos ordenadores diferentes.

  • servidor linux
ffmpeg -re -f v4l2 -i /dev/video5 -r 10 -f mpegts udp://192.168.1.67:8554?pkt_size=1316
  • Servidor Windows
ffmpeg -f dshow -i video="USB2.0 HD UVC WebCam" -r 10 -f mpegts udp://192.168.1.67:8554?pkt_size=1316
  • del lado del cliente
ffplay udp://127.0.0.1:8554

N.B.: Puedes probar el streaming en una sola máquina utilizando la dirección IP de la máquina en la que estás trabajando y utilizando dos terminales, uno para el servidor y otro para el cliente.

ffmpeg-streaming-between-machines-result Transmisión de vídeo entre dos máquinas con FFMPEG

Para recuperar las estadísticas de vídeo puede utilizar el comando ffprobe

ffprobe udp://127.0.0.1:8554

o, para más detalles,

ffprobe -show_format -show_streams udp://127.0.0.1:8554

Reducir el tiempo de recepción de secuencias de vídeo entre dos máquinas

Se observa un retardo de unos 15 segundos entre la transmisión y la recepción de vídeo. Puede ser útil reducir este retardo en función de la aplicación.

En el lado del servidor, los parámetros que afectan a la velocidad de transmisión son

  • el tamaño de la imagen (por ejemplo, -s 800×600)
  • conversión del formato del códec (por ejemplo, -c:v libx264)
  • número de fotogramas por segundo o framerate (por ejemplo, -r 10)

Intenta trabajar con estos parámetros para reducir el retardo manteniendo una calidad suficiente.

ffmpeg -re -thread_queue_size 64 -s800x600 -i

En el lado del cliente, hay varias opciones que puede probar a partir de la documentación incluida en esta discusión.

ffplay -fflags nobuffer -probesize 32 -sync ext -vf setpts=0 udp:

Estos cambios en las opciones de los comandos ffmpeg y ffplay reducen el retardo de 15 a unos 2 segundos para el flujo de vídeo.

Creación de un flujo HTTP con ffmpeg

Puede crear un servidor de vídeo HTTP utilizando VLC. La ventaja de este método es que el flujo de vídeo se puede transmitir a cualquier dispositivo.

  • servidor linux
ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sot='#std{access=http,mux=ts,dst=:8554}'
  • del lado del cliente, debe especificar la dirección IP del servidor
ffplay http://192.168.1.9:8554

Creación de un flujo RTSP con ffmpeg

Puede crear un servidor de vídeo HTTP utilizando VLC. La ventaja de este método es que el flujo de vídeo se puede transmitir a cualquier dispositivo.

  • servidor linux
ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sot='#rtp{sdp=rtsp://:8554/} --sot-all --sot-keep'
  • del lado del cliente, vos devez spécifier l’adresse IP du serveur
ffplay rtsp://192.168.1.9:8554/

Script Python para iniciar el streaming

Aquí tienes un script en Python que te permitirá probar los diferentes métodos de streaming y los parámetros de ffmpeg

import subprocess

#UDP
#input client ip address here 192.168.1.9
stream_video="ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts udp://192.168.1.9:8554?pkt_size=1316"
#on client side ffplay udp://127.0.0.1:8554

#HTTP
stream_video="ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sot='#std{access=http,mux=ts,dst=:8554}'"
#on client side ffplay http://192.168.1.73:8554

#RSTP
stream_video="ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sot='#rtp{sdp=rtsp://:8554/} --sot-all --sot-keep'"
#on client side ffplay rtsp://192.168.1.73:8554/ # don't forget / at the end

try:
	subprocess.call(stream_video,shell=True)
except:
	pass
print("Done")

Bonus: Visualizar el flujo de vídeo FFMPEG con OpenCV

Una vez establecido el flujo de vídeo entre las dos máquinas, se puede utilizar OpenCV para leer y mostrar las imágenes del flujo UDP.

import cv2

def main(args):

	#cap = cv2.VideoCapture(0) #default camera
	cap = cv2.VideoCapture('udp://127.0.0.1:8554')
	#cap = cv2.VideoCapture('http://192.168.1.9:8554')
	#cap = cv2.VideoCapture('rtsp://192.168.1.9:8554/')

	while(True):
		ret, frame = cap.read()
		if ret: #necessary if packet is lost
			frame=cv2.resize(frame, (800, 600)) 
			cv2.imshow('Capturing',frame)
			
		if cv2.waitKey(1) & 0xFF == ord('q'): #click q to stop capturing
			break

	cap.release()
	cv2.destroyAllWindows()
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
streaming-between-ffmpeg-opencv-result Transmisión de vídeo entre dos máquinas con FFMPEG

Bonus2 : Mostrar la hora en el vídeo

Para mostrar la hora en el vídeo, vamos a utilizar el filtro drawtext de ffmpeg, que utiliza un determinado parámetro de texto

  • fontfile: fuente utilizada
  • fontsize: tamaño del texto
  • fontcolor: coleur du texte
"drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460"

El filtro se aplica con la etiqueta -vf. Este es el comando completo

ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460" -vcodec copy -f mpegts udp://192.168.1.9:8554?pkt_size=1316

En python

stream_cmd="""ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vf "drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460" -vcodec copy -f mpegts udp://192.168.1.9:8554?pkt_size=1316"""

Práctico para imitar una cámara de CCTV o comparar tiempos de diferentes cámaras

ffmpeg-timestamp-videox2 Transmisión de vídeo entre dos máquinas con FFMPEG

Aplicaciones

Fuentes