Neste tutorial, veremos como enviar um fluxo de vídeo de uma máquina para outra usando FFMPEG. O envio de dados entre dois dispositivos, sejam eles quais forem, é um dos principais problemas dos objectos ligados (IoT). Se pretende criar uma câmara ligada que envia vídeo para uma máquina remota, este artigo deve interessar-lhe.
Instalando o ffmpeg
Numa máquina Linux
sudo apt-get install ffmpegNuma máquina Windows, siga este procedimento.
N.B.: se necessário numa máquina Linux sudo apt-get install v4l-utils
Obtenha as informações necessárias para a transmissão de vídeo
Para criar um fluxo de vídeo de uma máquina para outra, as máquinas devem estar ligadas à mesma rede (Wifi ou Ethernet).
Em primeiro lugar, é necessário obter o endereço IP da máquina cliente (que recebe o fluxo)
Introduzir um terminal de comando
ifconfig #pour une machine linux
ip addr # si ifconfig n'est pas disponible 
ou
ipconfig #pour une machine windows
Deve obter um endereço com o formato 192.168.X.X (no nosso caso 192.168.1.67)
Em seguida, recupere a fonte de vídeo. Para listar todas as entradas de vídeo numa máquina Linux
ls -l /dev/video*lsusb #list usb devicesv4l2-ctl --list-devices #list video devicesEstes comandos devem ajudá-lo a identificar a fonte de vídeo. No nosso caso,

Para listar fontes de vídeo numa máquina Windows, pode utilizar o ffmpeg
ffmpeg -list_devices true -f dshow -i dummyNo nosso caso, video=”USB2.0 HD UVC WebCam “

Recuperar as opções e verificar os formatos e resoluções aceites pela câmara
no Linux
v4l2-ctl -d /dev/video0 --list-formatsno Windows
ffmpeg -f dshow -list_options true -i video="USB2.0 HD UVC WebCam"Uma vez registados estes dados, podemos configurar o streaming.
Criar um fluxo de vídeo com o ffmpeg
Para criar um fluxo de vídeo, é necessário um emissor (servidor) e um recetor (cliente) que será reproduzido por dois terminais executados em dois computadores diferentes.
- lado do servidor linux
ffmpeg -re -f v4l2 -i /dev/video5 -r 10 -f mpegts udp://192.168.1.67:8554?pkt_size=1316- Lado do 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- lado do cliente
ffplay udp://127.0.0.1:8554Nota: Pode testar o streaming numa única máquina utilizando o endereço IP da máquina em que está a trabalhar e utilizando dois terminais, um para o servidor e outro para o cliente.

Para obter estatísticas de vídeo, pode utilizar o comando ffprobe
ffprobe udp://127.0.0.1:8554ou, para mais pormenores,
ffprobe -show_format -show_streams udp://127.0.0.1:8554Reduzir o tempo necessário para receber fluxos de vídeo entre duas máquinas
Existe um atraso de cerca de 15 segundos entre a transmissão e a receção do vídeo. Pode valer a pena reduzir este atraso, consoante a aplicação.
No lado do servidor, os parâmetros que afectam a velocidade de transmissão são:
- o tamanho da imagem (por exemplo, -s 800×600)
- conversão do formato do codec (por exemplo, -c:v libx264)
- o número de fotogramas por segundo ou framerate (por exemplo, -r 10)
Experimente jogar com estes parâmetros para reduzir o atraso, mantendo a qualidade suficiente.
ffmpeg -re -thread_queue_size 64 -s800x600 -iNo lado do cliente, existem várias opções que podem ser testadas a partir da documentação incluída nesta discussão.
ffplay -fflags nobuffer -probesize 32 -sync ext -vf setpts=0 udp:Estas alterações às opções dos comandos ffmpeg e ffplay reduzem o atraso do fluxo de vídeo de 15 para cerca de 2 segundos.
Criar um fluxo HTTP com o ffmpeg
É possível criar um servidor de vídeo HTTP utilizando o VLC. A vantagem deste método é que o fluxo de vídeo pode ser transmitido para qualquer dispositivo.
- lado do servidor linux
ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sout='#std{access=http,mux=ts,dst=:8554}'- lado do cliente, é necessário especificar o endereço IP do servidor
ffplay http://192.168.1.9:8554Criar um fluxo RTSP com o ffmpeg
É possível criar um servidor de vídeo HTTP utilizando o VLC. A vantagem deste método é que o fluxo de vídeo pode ser transmitido para qualquer dispositivo.
- lado do servidor linux
ffmpeg -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -f mpegts -|vlc -I dummy - --sout='#rtp{sdp=rtsp://:8554/} --sout-all --sout-keep'- lado do cliente, é necessário especificar o endereço IP do servidor
ffplay rtsp://192.168.1.9:8554/
Script Python para iniciar o streaming
Aqui está um script Python que lhe permitirá testar os diferentes métodos de streaming e os parâmetros do 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 - --sout='#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 - --sout='#rtp{sdp=rtsp://:8554/} --sout-all --sout-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")
Bónus: Apresentar o fluxo de vídeo FFMPEG com OpenCV
Uma vez que o fluxo de vídeo tenha sido estabelecido entre as duas máquinas, o OpenCV pode ser usado para ler e exibir as imagens do fluxo 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))

Bónus2 : Mostrar a hora no vídeo
Para mostrar a hora no vídeo, vamos utilizar o filtro drawtext do ffmpeg, que utiliza um determinado parâmetro de texto
- fontfile: tipo de letra utilizado
- fontsize: tamanho do texto
- fontcolor: cor do texto
"drawtext=fontfile=/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf: text='%{localtime\:%T}': fontsize=24: fontcolor=white@0.8: x=7: y=460"O filtro é aplicado com a etiqueta -vf. Aqui está o 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=1316Em 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"""
Útil para imitar uma câmara CCTV ou para comparar tempos de câmaras diferentes

 
					 
												