Generate MPEG-TS from file with ffmpeg
In this post I will describe how an MPEG-TS multicast stream can be generated with ffmpeg by looping an MP4 file and a Docker container you can use to instantly be up and running.
The following ffmpeg command line will produce an mpeg-ts multicast from a video file that is looping and with the local time burned into the video. One use-case for this could be if you want to measure the distribution and streaming live latency added in the live ABR transcoder and video player.
ffmpeg -stream_loop -1 -i /mnt/Sunrise.mp4 -map 0:v -vcodec copy -bsf:v h264_mp4toannexb -f h264 - | ffmpeg -framerate 25 -fflags +genpts -r 25 -re -i - -f lavfi -i anullsrc=r=48000:cl=stereo -c:a aac -shortest -vf drawtext=fontfile=/root/Vera.ttf:fontsize=12:text='eyevinntechnology/toolbox-loopts':fontcolor=white@0.9:x=20:y=20:shadowcolor=black:shadowx=2:shadowy=1,drawtext=fontfile=/root/Vera.ttf:fontsize=200:text='%{localtime\:%T}':fontcolor=white@0.9:x=(w-tw)/2:y=250:shadowcolor=black:shadowx=2:shadowy=1,drawtext=fontfile=/root/Vera.ttf:fontsize=40:text='[%{n}/%{pts}]':fontcolor=white@0.9:x=(w-tw)/2:y=h-th-10:shadowcolor=black:shadowx=2:shadowy=1 -vcodec libx264 -preset veryfast -pix_fmt yuv420p -strict -2 -y -f mpegts -r 25 udp://239.0.0.1:1234?pkt_size=1316
It can be in place to demystify a bit what this does.
Two ffmpeg processes is started. One process to read and decode the input file and another process to generate the mpeg-ts stream. The first process writes the output bitstream to stdout and the other process read the bitstream from stdin.
ffmpeg -stream_loop -1 -i /mnt/Sunrise.mp4 -map 0:v -vcodec copy -bsf:v h264_mp4toannexb -f h264 -
The line above “extracts” the h264/AVC bitstream from the input file and once end-of-file is reached it will seek to the start of the file and repeat this until the program is stopped. The output is then written to stdout.
ffmpeg -framerate 25 -fflags +genpts -r 25 -re -i -
This part of the second process reads the input from stdin and assumes that the framerate of the video is 25 frames per second and generates new PTS values. One thing to note is that the genpts flag only generate PTS when the value is missing and that is the reason to extract the h264/AVC bitstream first.
-f lavfi -i anullsrc=r=48000:cl=stereo -c:a aac -shortest
Above adds a silent audio track as some encoders requires an audio pid to be present in the mpeg-ts stream. Below filter adds the timecode and some other information to the video using the drawtext filter.
-vf "drawtext=fontfile=/root/Vera.ttf:fontsize=12:text='eyevinntechnology/toolbox-loopts':fontcolor=white@0.9:x=20:y=20:shadowcolor=black:shadowx=2:shadowy=1,drawtext=fontfile=/root/Vera.ttf:fontsize=200:text='%{localtime\:%T}':fontcolor=white@0.9:x=(w-tw)/2:y=250:shadowcolor=black:shadowx=2:shadowy=1,drawtext=fontfile=/root/Vera.ttf:fontsize=40:text='[%{n}/%{pts}]':fontcolor=white@0.9:x=(w-tw)/2:y=h-th-10:shadowcolor=black:shadowx=2:shadowy=1"
And finally the following specifies the output format:
-vcodec libx264 -preset veryfast -pix_fmt yuv420p -strict -2 -y -f mpegts -r 25 udp://239.0.0.1:1234?pkt_size=1316
To simplify all of this I have created a Docker container that you can use. It is part of a set of containers with some handy tools that video and streaming engineers may need. This is the first tool in the toolbox and more to come.
Assuming that you are running Docker engine on Mac and have VLC installed all you need to do is:
docker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 udp://host.docker.internal:9998?pkt_size=1316 --withtc
and then open VLC to stream from
udp://@127.0.0.1:9998
If you want to add a test tone you can add that as an option
docker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 udp://host.docker.internal:9998?pkt_size=1316 --withtc --withaudio
For a full list of options
docker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts -h
Secure Reliable Transport
If you want to use SRT (Secure Reliable Transport) instead of multicast you can run the loopts in SRT listener mode.
docker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 "srt://0.0.0.0:9998?pkt_size=1316&mode=listener" --withtc
and then use the following address in VLC
srt://@127.0.0.1:9998
Enjoy!
If you have any further questions and comments on this blog drop a comment below or tweet me on Twitter (@JonasBirme).
Eyevinn Technology is the leading independent consultant firm specializing in video technology and media distribution, and proud organizer of the yearly nordic conference Streaming Tech Sweden.
Update: updated with example using SRT (secure reliable transport) as transport protocol instead of multicast.