Search code examples
videoffmpeg

FFMPEG: embed current time in milliseconds into video


I would like to embed the computer's local time in milliseconds into a stream using FFMPEG.

I can embed the local time in seconds using drawtext like so:

ffmpeg -i <input> -vf "drawtext=text='%{localtime\:%T}'" -f flv <output>

Looking through the documentation for drawtext, doing some tests, and Googling around, it seems like localtime and gmtime don't provide milliseconds -- just seconds. However the pts options does have milliseconds:

ffmpeg -i <input> -vf "drawtext=text='%{pts\:hms}'" -f flv <output>

I also found out that pts supports an offset, so I was able to use something like this to display local time (kind of):

ffmpeg -i <input> -vf "drawtext=text='%{pts\:hms\:$(date +%s.%N)}'" -f flv <output>

This had two problems:

  1. It displayed something like 17499:17:29 for the time... I found a (rather complex) way to work around this
  2. It uses the server's current time when you first run the ffmpeg command as the offset -- not the server's current time when ffmpeg actually starts decoding video. I noticed ffmpeg had about a 2-second startup time, causing the clock to be off by roughly 2 seconds

Is there a way to modify my solution, or an entirely separate solution, that can embed server local time in milliseconds into the stream?


Solution

  • Use

    ffmpeg -i input
           -vf "settb=AVTB,
                setpts='trunc(PTS/1K)*1K+st(1,trunc(RTCTIME/1K))-1K*trunc(ld(1)/1K)',
                drawtext=text='%{localtime}.%{eif\:1M*t-1K*trunc(t*1K)\:d}'"
           -f flv out
    

    First, the incoming timestamps are represented as microsecond precision by forcing the timebase to the default AVTB which is 10e-6.

    Second, a new PTS is set, which comprises of the original PTS reduced to milliseconds and left-shifted (decimally) three digits. To this, is added the wallclock's milliseconds component. RTCTIME is available in setpts and returns an integer with microsecond precision.

    Third, the text string has three parts. The first is the localtime which is formatted as a Y-M-D-H-M-S string and returns second precision. Then a dot to demarcate the milliseconds. In the third, t returns fractional seconds. The millisecond component is extracted and printed as an integer.