, ,
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
o
ipconfig #por une machine windows
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
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 «.
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.
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))
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