POSTS
🎥 ffmpeg multicast streaming (lan)
By Philip
intro
this part is a continuation of the previous post. In this post i will explain how to stream video with ffmpeg on a LAN, and keep the latency as low as possible.
note: this post is for lan only, client and server need to be on the same network or wifi.
(In detail: you need te be in the same layer 2 segement)
this is because we use multicast udp to transport the video.
(it is possbile to route multicast, but this is beyond the scope of this project)
The most important point to stream anything to multicast is the output. In all ffmpeg examples this will be the same:
-f rawvideo "udp://224.0.0.1:3333"
This sets the output format to rawvideo
, a raw video format, nothing more nothing less. The actual output is
udp
, wich is a network output. the network addres we will send it to is a multicast address (224.0.0.1
). You should
keep this address the same on all sender and receivers. Other multicast adresses are possible but ensure your device is listening on them (not covered here).
224.0.0.1
is a address that is usable on Windows, Linux and other OS’es.
3333
is the network port, you can choose one from 0
to 65535
, most practical is 1025
to 65535
. You can view
this a a video channel. Use only one sender per port, unlimited receivers are possible.
So you can stream alot of different video’s (or audio) on multicast.
server side (video sender)
first we will explain different option that could be used on the sending side, the video sender (server).
note: if you use wifi to stream video with low latency I suggest you disable power saving of the wifi. On the linux this is done with:
sudo iw dev wlan0 set power_save off
raspberry pi video
Streaming from a rasberry pi with around 124ms latency. This was the lowest i could get with the raspberry pi. The resolution and quality is rather low, but this for latency this was the best i could achieve.
raspivid -n -t 0 -w 640 -h 480 -fps 50 --codec H264 -ih -pf baseline --intra 100 --flicker off -v --qp 30 -b 0 --flush -o udp://224.0.0.1:3333
explanation:
raspivid
raspberry pi video capture command-n
disable the preview window on the raspberry-t 0
disable the timeout, keep raspivid running--flicker off
this will disable the de-flicker mode, slight latency improvement-w 640
input width 640 pixels wide-h 480
input height 480 pixels-fps 50
capture at 50 frames per second--codec H264
use the h264 codec-pf baseline
slightly faster preset for h264 encoder-ih
inline h264 header, this will help detect the format on the receiving side--intra 120
the h264 encoder will only send the “diff to the previous image”. if a frame is lost on the network the video stream could be damaged. This will enforce a full update every 120 frame’s-b 0
don’t limit the bitrate, see –qp--qp 30
this will set the video quality level instead of bitrate. This seems to have the largest impact on the latency, the lower the quality, the lower the latency--flush
flush the output buffer to minimize latency-o udp://224.0.0.1:3333
output the video over udp to multicast ip 224.0.0.1 at port 3333
desktop streaming
stream video from you desktop to multicast (your local network)
windows software encode
./ffmpeg -v fatal -fflags nobuffer+fastseek+flush_packets -an -f gdigrab -framerate 60 -video_size 640x480 -i desktop -c:v h264 -preset ultrafast -tune zerolatency -f rawvideo "udp://224.0.0.1:3333"
explantion:
-v fatal
minimize logging-fflags nobuffer+fastseek+flush_packets
do not buffer and flush packets when possible-an
dont use audio-f gdigrab
windows framebuffer filter-framerate 60
set framerate to 60-video_size 640x480
capture a size of height 640 and 480 width-i desktop
use the desktop as input-c:v h264
set the video codec to h264-preset ultrafast
set the h264 preset to ultrafast-tune zerolatency
set the h264 tune to the lowest possible latency-f rawvideo
set the output video format to rawvideo"udp://224.0.0.1:3333"
output the data with the udp network protocol and send it to multicast ip 224.0.0.1 on port 3333.
windows hardware encoded
ffmpeg -v fatal -fflags nobuffer+fastseek+flush_packets -rtbufsize 0 -an -f gdigrab -framerate 60 -video_size 640x480 -i desktop -c:v h264_nvenc -qp 30 -preset llhp -zerolatency 1 -delay 0 -rc:v cbr -f rawvideo "udp://224.0.0.1:3333?buffer_size=1480&pkt_size=1480"
explantion:
-v fatal
set the logging to ‘fatal’ level, show only grave errors-fflags nobuffer+fastseek+flush_packets
do not buffer input data-rtbufsize 0
real time buffer, 0: do not buffer-an
no sound-f gdigrab
use windows screen grab-framerate 60
set the framerate, in this case 60 fps-video_size 640x480
size of the screen grab 640 pixels heigh and 480 wide. You can vary this like you want-i desktop
input is the desktop-bufsize 0
buffersize for the video codec is 0-c:v h264_nvenc
video code is hardware nvidia codec-qp 30
set the quality of the video encoder-preset llhp
set the video codec preset to low latency highquality preset-zerolatency 1
set the video codec latency al low as possible-delay 0
encoder delay as low as possible-rc:v cbr
set the video encoder to constant bit rate mode-f rawvideo
output format is rawvideo"udp://224.0.0.1:3333?buffer_size=1480&pkt_size=1480"
output the video to udp on multicast address 224.0.0.1, on port 3333 with a buffer and packet size of 1480 bytes
linux software encode
ffmpeg -v fatal -fflags nobuffer+fastseek+flush_packets -an -framerate 60 -video_size 640x480 -f x11grab -i :0.0 -c:v h264 -qp 25 -f rawvideo "udp://224.0.0.1:3333"
explantion:
-v fatal
minimize logging-fflags nobuffer+fastseek+flush_packets
do not buffer and flush packets when possible-an
dont use audio-framerate 60
set framerate to 60-video_size 640x480
capture a size of height 640 and 480 width-f x11grab
windows framebuffer filter-i :0.0
use the desktop 0 as input (selects first desktop)-c:v h264
set the video codec to h264-preset ultrafast
set the h264 preset to ultrafast-tune zerolatency
set the h264 tune to the lowest possible latency-f rawvideo
set the output video format to rawvideo"udp://224.0.0.1:3333"
output the data with the udp network protocol and send it to multicast ip 224.0.0.1 on port 3333.
linux intel hardware encode
ffmpeg -v fatal -fflags nobuffer+fastseek+flush_packets -an -framerate 60 -video_size 640x480 -f x11grab -i :0.0 -c:v h264_vaapi -qp 25 -f rawvideo "udp://224.0.0.1:3333"
explantion:
-v fatal
minimize logging-fflags nobuffer+fastseek+flush_packets
do not buffer and flush packets when possible-an
dont use audio-framerate 60
set framerate to 60-video_size 640x480
capture a size of height 640 and 480 width-f x11grab
windows framebuffer filter-i :0.0
use the desktop 0 as input (selects first desktop)-c:v h264_vaapi
set the video codec to h264_vaapi. vaapi is a hardware encode api-qp 25
set the variable quality to 25 (worse) than the default 20-f rawvideo
set the output video format to rawvideo"udp://224.0.0.1:3333"
output the data with the udp network protocol and send it to multicast ip 224.0.0.1 on port 3333.
extra
# fixed bitrate, for predictable bandwith
raspivid -n -t 0 -w 640 -h 480 -fps 60 --flicker off --codec H264 -ih -pf baseline -b 2000000 --flush -o udp://224.0.0.1:3333
# another way to stream h264 video to multicast
raspivid -t 0 -w 320 -h 200 --flush -o - | ffmpeg -i pipe:0 -c copy -f mpegts "udp://224.0.0.1:3333"
client side (video player)
basic ffplay
we will use ffplay as the viewer for the multicast video. this command will almost open everything you throw in at the source, but has quite the latency (a few seconds)
ffplay -i udp://224.0.0.1:3333
ffplay low latency
this is a latency optimized command with options:
./ffplay -v fatal -an -probesize 32 -flags low_delay -fflags nobuffer+fastseek+flush_packets -framedrop -sync ext -max_delay 0 -framerate 120 -i "udp://224.0.0.1:3333"
explantion:
ffplay
this is the executable itself-v fatal
tell’s ffplay to output only very severe errors-an
disable sound-probesize 32
limit the startup probesize, this is the input stream size ffplay will use detect the input format. this will speed up the ffplay startup-flags low_delay
global options to lower latency-fflags nobuffer+fastseek+flush_packets
some more options to disable buffering and flushing to minimize latency-framedrop
allow frame dropping to keep the frame rate as fast as possible-sync ext
this will ensure the input buffer is read as fast as possible-max_delay 0
maximum demux delay-framerate 120
set the framerate higher then the sender framerate, this will ensure low latency-i "udp://224.0.0.1:3333"
set the input to udp, listen on multicast ip 224.0.0.1 on port 3333