4
$\begingroup$

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.

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

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'

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

4 Answers 4

2
$\begingroup$

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!

$\endgroup$
5
$\begingroup$

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

$\endgroup$
10
  • $\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
3
$\begingroup$

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)

The path to the data object was retrieved from the tooltip

enter image description here

$\endgroup$
4
  • $\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
0
$\begingroup$

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?

$\endgroup$

You must log in to answer this question.

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