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:
raspividraspberry pi video capture command-ndisable the preview window on the raspberry-t 0disable the timeout, keep raspivid running--flicker offthis will disable the de-flicker mode, slight latency improvement-w 640input width 640 pixels wide-h 480input height 480 pixels-fps 50capture at 50 frames per second--codec H264use the h264 codec-pf baselineslightly faster preset for h264 encoder-ihinline h264 header, this will help detect the format on the receiving side--intra 120the 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 0don’t limit the bitrate, see –qp--qp 30this 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--flushflush the output buffer to minimize latency-o udp://224.0.0.1:3333output 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 fatalminimize logging-fflags nobuffer+fastseek+flush_packetsdo not buffer and flush packets when possible-andont use audio-f gdigrabwindows framebuffer filter-framerate 60set framerate to 60-video_size 640x480capture a size of height 640 and 480 width-i desktopuse the desktop as input-c:v h264set the video codec to h264-preset ultrafastset the h264 preset to ultrafast-tune zerolatencyset the h264 tune to the lowest possible latency-f rawvideoset 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 fatalset the logging to ‘fatal’ level, show only grave errors-fflags nobuffer+fastseek+flush_packetsdo not buffer input data-rtbufsize 0real time buffer, 0: do not buffer-anno sound-f gdigrabuse windows screen grab-framerate 60set the framerate, in this case 60 fps-video_size 640x480size of the screen grab 640 pixels heigh and 480 wide. You can vary this like you want-i desktopinput is the desktop-bufsize 0buffersize for the video codec is 0-c:v h264_nvencvideo code is hardware nvidia codec-qp 30set the quality of the video encoder-preset llhpset the video codec preset to low latency highquality preset-zerolatency 1set the video codec latency al low as possible-delay 0encoder delay as low as possible-rc:v cbrset the video encoder to constant bit rate mode-f rawvideooutput 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 fatalminimize logging-fflags nobuffer+fastseek+flush_packetsdo not buffer and flush packets when possible-andont use audio-framerate 60set framerate to 60-video_size 640x480capture a size of height 640 and 480 width-f x11grabwindows framebuffer filter-i :0.0use the desktop 0 as input (selects first desktop)-c:v h264set the video codec to h264-preset ultrafastset the h264 preset to ultrafast-tune zerolatencyset the h264 tune to the lowest possible latency-f rawvideoset 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 fatalminimize logging-fflags nobuffer+fastseek+flush_packetsdo not buffer and flush packets when possible-andont use audio-framerate 60set framerate to 60-video_size 640x480capture a size of height 640 and 480 width-f x11grabwindows framebuffer filter-i :0.0use the desktop 0 as input (selects first desktop)-c:v h264_vaapiset the video codec to h264_vaapi. vaapi is a hardware encode api-qp 25set the variable quality to 25 (worse) than the default 20-f rawvideoset 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:
ffplaythis is the executable itself-v fataltell’s ffplay to output only very severe errors-andisable sound-probesize 32limit 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_delayglobal options to lower latency-fflags nobuffer+fastseek+flush_packetssome more options to disable buffering and flushing to minimize latency-framedropallow frame dropping to keep the frame rate as fast as possible-sync extthis will ensure the input buffer is read as fast as possible-max_delay 0maximum demux delay-framerate 120set 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