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?


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.