I'm trying to edit videos for my dance group. What I'd like to be able to do is have an overlay that I can set the B.P.M (beats per minute) and I can display a simple metronome + counter over the video.

I notice that there is a text effect in the VSE

enter image description here

Is there any way to hook a callback based on the frame count that can change the text as the video progresses? This might be able to get me what I need.


I've discovered that I can do

import bpy

def my_handler(scene):
    print("Frame Change", scene.frame_current)


and the current frame count is output to the console. Now I would need to calculate and inject some text into the VSE

First real attempt

import bpy

def my_handler(scene):
    print("Frame Change", scene.frame_current)
    ob = bpy.data.objects['TimeCode']


where I have a text effect added to the VSE and defined as

enter image description here

but I get console errors as

File "C:\Users\bradp\OneDrive\Video\NewStyle C\choreo1.blend\Counter", line 7, in my_handler KeyError: 'bpy_prop_collection[key]: key "TimeCode" not found'

  • $\begingroup$ You could try out the TextFX addon. $\endgroup$
    – Samoth
    Oct 29, 2017 at 21:46

4 Answers 4


Expanding and slightly correcting the answer by bradgonesurfing, you can do this without any addons. First, create the text strip in the Video Sequence Editor and give it a name like "Timer". Now, create a Python script similar to this:

# TimerScript.py
# Arrange to update a VSE text strip to show elapsed time.

# Put this file next to your .blend file, open it in the Blender
# Text Editor view, and use "Text -> Run Script" to run it.  It
# will be active for the duration of the Blender editing session.

import bpy

scene = bpy.context.scene
obj = scene.sequence_editor.sequences_all['Timer']
fps = scene.render.fps

def recalculate_text(scene):
    # Number of frames since the start of the text strip.
    frames = scene.frame_current - obj.frame_start

    # Divide to get hours, minutes, seconds, and hundredths of a second.
    seconds_float = frames / fps
    seconds = int(seconds_float)
    hundredths = int((seconds_float - seconds) * 100)
    minutes = int(seconds / 60)
    seconds -= minutes * 60
    hours = int(minutes / 60)
    minutes -= hours * 60

    # Combine as a string.
    time_string = "{:d}:{:02d}:{:02d}.{:02d}".format(
        hours, minutes, seconds, hundredths)

    # Update the text object.    
    #print('Recalc: ' + time_string)
    obj.text = time_string

# This is used when moving between frames during editing.

# This is used during animation rendering.

Open the script in the Blender Text Editor (you can create it there in the first place) and run it via "Text → Run Script".

The slightly tricky bit, and the correction to Brad's answer, is you need to install this both as a pre-frame handler and a pre-render handler. If you only set it as pre-frame, then the update will not happen when rendering animations!


You can use Animation Nodes to do this very easily:

Node Tree

You can do all sort of editing like:

Node Tree 2

The Frame Rate input is hidden by default, show it like this:

Node Tree 3

  • $\begingroup$ This looks great. However I have blender 2.79 and my node editor window is a little different. Next to the node menu I only have 3 icons not 4 and the far left one you have selected I don't have. What am I missing? $\endgroup$ Oct 29, 2017 at 21:40
  • $\begingroup$ Have you installed the animation nodes addon? $\endgroup$
    – Samoth
    Oct 29, 2017 at 21:45
  • $\begingroup$ No. I guess that will be the problem $\endgroup$ Oct 29, 2017 at 21:51
  • $\begingroup$ Got it. Solution rocks :) $\endgroup$ Oct 29, 2017 at 22:08
  • 1
    $\begingroup$ @bradgonesurfing Updated the answer. $\endgroup$
    – Omar Emara
    Oct 30, 2017 at 13:13

The following script displays the frame count as an overlay

import bpy

def my_handler(scene):
    print("Frame Change", scene.frame_current)


The path to the data object was retrieved from the tooltip

enter image description here

  • $\begingroup$ Nice. Could expand this for a generic case for any strip in scene named "TimeCode". .Would need to check seq = scene.sequence_editor is not None, and seq.sequences_all.get("TimeCode") is not None. $\endgroup$
    – batFINGER
    Oct 29, 2017 at 16:11
  • $\begingroup$ Actually this does't work as it only works in manual mode. When I create a rendering the script is not called. No idea why. $\endgroup$ Oct 29, 2017 at 16:53
  • $\begingroup$ lol, see what you mean. Does appear to work in render (still) image. Suggest adding a text object to scene and using frame change handler to animate its body. $\endgroup$
    – batFINGER
    Oct 29, 2017 at 17:22
  • 1
    $\begingroup$ The reason this script does not work during rendering is you also need to add it as a render_pre handler. See my answer for a little elaboration. $\endgroup$ Feb 5, 2020 at 7:26

I know nothing about scripting. Try to answer it with the manual way. From my understaning, it is about rendering a sequence of numbers and clamp it into one minute.

If anything fancy is not needed. Frame counter can be generated from Metadata.

Properties > Render > Metadata > Stamp Output

Render Frame count in frame

  • Setup a empty Scene and set End Frame = BPM
  • Render the empty scene with Metadata ON and Transparent.
  • Overlay the clip to the dancing video, Transform the clip to one minute long with Speed Control. and Loop it over.

For video looping, please refer to:

How do you make a movie loop in the sequencer?


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .