# How to add an animated time controlled text effect to the VSE

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

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.

Progress

I've discovered that I can do

import bpy

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

bpy.app.handlers.frame_change_pre.append(my_handler)


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']
ob['Text']=scene.frame_current

bpy.app.handlers.frame_change_pre.append(my_handler)


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

but I get console errors as

• You could try out the TextFX addon. Oct 29, 2017 at 21:46

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.
bpy.app.handlers.frame_change_pre.clear()
bpy.app.handlers.frame_change_pre.append(recalculate_text)

# This is used during animation rendering.
bpy.app.handlers.render_pre.clear()
bpy.app.handlers.render_pre.append(recalculate_text)


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:

You can do all sort of editing like:

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

• 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? Oct 29, 2017 at 21:40
• Have you installed the animation nodes addon? Oct 29, 2017 at 21:45
• No. I guess that will be the problem Oct 29, 2017 at 21:51
• Got it. Solution rocks :) Oct 29, 2017 at 22:08

The following script displays the frame count as an overlay

import bpy

def my_handler(scene):
print("Frame Change", scene.frame_current)
bpy.data.scenes['Scene'].sequence_editor.sequences_all["TimeCode"].text=str(scene.frame_current)

bpy.app.handlers.frame_change_pre.append(my_handler)


• 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. Oct 29, 2017 at 16:11
• 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. Oct 29, 2017 at 16:53
• 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. Oct 29, 2017 at 17:22
• 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. 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

• 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?