burnt-in timecode with ffmpeg

Burning-in timecode is easy in Avid or Final Cut, but if for any reason you need to do it the hard way with command-line ffmpeg, here is how.

To not make it harder than necessary, there are links to pre-compiled versions of ffmpeg on their download page. For Mac OS X, as of August 2013, there were these 2 versions:

  •  http://ffmpegmac.net, which unfortunately didn't have the needed filter. It would give the error
    "AVFilterGraph ...] No such filter: 'drawtext'".
  • the version 2.0.1 built by Helmut Tessarek worked fine. Unfortunately, it is compressed with 7-zip, so you may need to get a decompressor first. I used Keka (not open source, but free).

Below is the command I used to quickly encode Sony mpeg2 MXF files into H264 Quicktimes, preserving the original timecode in the QT TC track (ffmpeg does this automatically), and also burning it into the picture.

Since the command itself is quite awful, it is best to predefine variables, so that the long command itself can be copy/pasted directly, without further editing, or at least not too much...

# set variables for the input and output files:


# the timecode rate must be set. Should be identical to the FPS.


# select a monospaced font file on your machine. On Linux, try:


# or on Mac:

font="/Library/Fonts/Andale Mono.ttf"

# size and position:

position="x=w-text_w-(text_w/6):y=text_h" # top right

# For bottom right, try this instead: position="x=(w-tw)/2: y=h-(2*lh)"

# get the timecode, and escape the ":" to be able to use it in the burn-in filter

timecode=$( ffmpeg -i "$in" 2>&1 | awk '$1 ~ /^timecode/ {print $NF}' )

# To test encoding only the first x seconds, use:

test_secs="-t 20"

# or for the whole video, leave this empty:


# quality/size/speed : (try crf between 18 and 25? lower is better quality and bigger file.)

preset=ultrafast # (superfast, fast, slow, ...)

# And finally (with de-interlacing and without scaling):

ffmpeg -threads 0 -i "$in" $test_secs -acodec copy -vcodec libx264 -preset $preset -crf $crf -deinterlace -vf "drawtext=fontfile=$font: timecode='$tc_escaped': r=$tc_rate: $position: fontcolor=white: fontsize=$fontsize: box=1: boxcolor=black@0.2" "$out"

or to keep only video with audio channel 1 (throwing away audio channels 2, etc. ):

ffmpeg -threads 0 -i "$in" $test_secs -map 0:0 -map 0:1 -acodec copy -vcodec libx264 -preset $preset -crf $crf -deinterlace -vf "drawtext=fontfile=$font: timecode='$tc_escaped': r=$tc_rate: $position: fontcolor=white: fontsize=$fontsize: box=1: boxcolor=black@0.2" "$out"


Labels: , , ,


Blogger Evan Evans said...

Is there any way to make it an AppleScript or something, so one can just drop a file onto it (or one of a few different applescripts in a folder that are different frame rates for example) and that's it?

13 January, 2018 10:00  
Blogger Milivoj. said...

@Evan: Sure. The easiest would probably be to first put things together into a full Bash script. Then you can test it by dragging files from the Finder into the Terminal window to give the arguments to the script.
Once it works as you want, it should be easy to wrap your shell script with Automator / Apple script / Platypus or whatever so that dropped files are given as arguments to the script.

13 January, 2018 11:30  

Post a Comment

Links to this post:

Create a Link

<< Home