Generate MPEG-TS from file with ffmpeg

Eyevinn Technology
3 min readMar 19, 2019

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.

--

--

Eyevinn Technology

We are consultants sharing the passion for the technology for a media consumer of the future.