1
$\begingroup$

I'm attempting to navigate to a specific frame in the Movie Clip Editor in order to subsequently detect features on the new frame. However, I'm encountering issues with the execution order of my Python code. Initially, I set the desired frame using bpy.context.scene.frame_current = frame to move to the specified frame. Following that, I utilize bpy.context.area.tag_redraw() to refresh the Movie Clip Editor timeline because, for unknown reasons, the frame does not update properly in that editor. Finally, I employ bpy.ops.clip.detect_features() to identify features on the new frame.

The problem arises when executing this code: the updated frame and the newly added tracking points appear simultaneously. Consequently, the tracking points generated by the bpy.ops.clip.detect_features() function are based on the original frame, which is not the desired outcome.

I even attempted using time.sleep() functions to introduce delays before executing the bpy.ops.clip.detect_features() function. However, this approach yielded the same result as before, where the frame updates at the same time as the detection function is called. It appears that the script is not executing in the correct order.

Here is the simple script:

import math
import time

MiddleFrame = int(NumberOfFrames / 2)
bpy.context.scene.frame_current = MiddleFrame

print("Checkpoint1")
time.sleep(2)

bpy.context.area.tag_redraw()

print("Checkpoint2")
time.sleep(1)


bpy.ops.clip.detect_features()
print("Checkpoint3")
time.sleep(1)

print("Checkpoint4")

Results:

Checkpoint1

Checkpoint2

Checkpoint3

Checkpoint4

Frame updates and trackers appear detected from the original frame.

Here is what I want to happen:

Frame changes to the new frame in the timeline.

Checkpoint1

Frame updates in the Novie Clip Editor.

Checkpoint2

Detects feature on the updated frame.

Checkpoint3

Checkpoint4

What am I doing wrong?

$\endgroup$

1 Answer 1

1
$\begingroup$

The issue you encountered with bpy.ops.clip.detect_features() processing the previous frame instead of the frame you set in bpy.context.scene.frame_current is due to the order in which operations are executed in Blender's event loop.

When you set bpy.context.scene.frame_current with a frame value, it updates the current frame value in the scene, but it doesn't immediately update the interface. The interface update occurs during the event loop, and bpy.ops.clip.detect_features() may execute before the interface update happens.

To work around this issue, you can use a timer event to delay the execution of detect_features() and make sure it happens after the frame update using the bpy.app.handlers.frame_change_post application handler. Also a side note, you always need to make sure you execute ops functions in the correct context. The bpy.ops.clip.detect_features() function needs to be executed in the CLIP_EDITOR context. Read more about context overrides here

import bpy

frame_to_detect_features = 130 # change to MiddleFrame in your case

def detect_features_callback(scene):
    area_type = 'CLIP_EDITOR'
    areas = [area for area in bpy.context.window.screen.areas if area.type == area_type]

    if len(areas) <= 0:
        raise Exception(f"Make sure an Area of type {area_type} is open or visible on your screen!")

    with bpy.context.temp_override(
        area=areas[0],
    ):
        bpy.ops.clip.detect_features()

    bpy.app.handlers.frame_change_post.clear()

bpy.app.handlers.frame_change_post.clear()
bpy.app.handlers.frame_change_post.append(detect_features_callback)

bpy.context.scene.frame_set(frame_to_detect_features)

Make sure both the Movie Clip Editor area and Script Editor area are open in the same window for this script to work. In this script, the callback function detect_features_callback gets invoked automatically after bpy.context.scene.frame_set() has finished processing. Take note we need to use bpy.context.scene.frame_set() instead of bpy.context.scene.frame_current for the callback to get invoked.

$\endgroup$

You must log in to answer this question.

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