FFmpeg's drawtext
filter can burn timecodes into frames.
edit: I misread the docs before. I saw the timecode
option to the filter, and missed seeing that there was a pts
available for text expansion. See the edit history for the longer-and-less-useful answer.
I eventually got around to trying it, and here's the command line I cobbled together from pasting and tweaking some examples:
ffmpeg -i /f/p/moto-g\ camera/VID_20141225_140557099.mp4 -filter_complex "drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='frame %{n}\\: %{pict_type}\\: pts=%{pts \\: hms}': x=100: y=50: fontsize=24: fontcolor=yellow@0.8: box=1: boxcolor=blue@0.9" -c:a copy -c:v libx264 -preset veryfast -crf 16 -x264-params keyint=60 -map 0 foo.mkv
Note the actual text to be printed needs a lot of escaping, to protect it from the shell, then from ffmpeg's arg-to-drawtext
. To modify it, change the text='frame %{n}\\: %{pict_type}\\: pts=%{pts \\: hms}'
part of that ffmpeg command.
example output: "frame 0: I: pts=00:00:00.0000" (I/B/P are frame types, from %{pict_type}
.)
Modify x
and y
to put it somewhere else in the frame. (you can use x=iw/2
to put it horizontally in the middle. iw
= input width. (anchor = top left corner of the text, I think?)) Modify other params to change colors or whatnot.
This works even with VFR video. I checked with video from the camera in a Moto G phone, which makes variable frame-rate video. The first second has 30 frames. A later 1-sec interval in the video has 17 frames. (Indoors, not very well lit, so I think it's lower FPS to get more light, not because it can't write to flash storage fast enough.) The timestamps it puts in the MP4 container are correct, so it plays fine.
The encode parameters -c:a copy -c:v libx264 -preset faster -crf 16 -x264-params keyint=60
are my suggestion for what you might want for scratch files with timestamps burned in: you just want it to encode fast, and don't care much about filesize since you're just going to use it locally, since it has timestamps scribbled all over it. (There's even a superfast. Don't use ultrafast except for lossless mode, though.)
keyint=60
will make sure there's an I frame at least as often as every 60 frames, for efficient scrubbing. Leave it out if you don't need to be able to efficiently framestep backwards; lower it if you want high-rez seeking to be faster.
Use -map 0
if you want multiple audio and metadata streams copied into the output, instead of just the first audio and first video tracks (and no e.g. chapter metadata).