1
$\begingroup$

My goal is to call blender form the command line with a set of arguments to use the built in 2D video stabilization tools.

I have been able to (via the bpy API):

  • Get parameters from command line call
  • load a new clip
  • add a marker (to track)
  • position the marker
  • 'select' the marker/track (not sure if needed)

This is all possible without relying on bpy.ops

Unfortunately now I need to access the following functionality programmatically:

clip.stabilize_2d_add()

My main question: I can't find a way to get to that (bpy.ops.clip.stabilize_2d_add()). I have no idea what context I would need to switch to to make this a valid python call.


At this point I also notice the transition from doing everything in code to having to hunt through the UI workflow for ways to replicate UI functionality. I am wondering if I shouldn't need to call bpy.ops.clip.stabilize_2d_add() at all and should instead find the underlying functionality?

The part that comes right after this, which is making the stabilized track is completely lost to me as well. Am I going in the wrong direction?

Any help would be greatly appreciated.

$\endgroup$
3
  • $\begingroup$ Related: blender.stackexchange.com/a/41747/2843 In this example script I use the context a lot to call bpy.ops.* functions, you need to use this override parameter. $\endgroup$
    – Samoth
    Mar 2, 2017 at 21:28
  • $\begingroup$ @Samoth do you have any tips on a clean way to figure out what screen+region+area this ops control is in? I notice that in one part of your code the override is hardcoded. How did you get the values you hardcode it to? $\endgroup$
    – BorisKourt
    Mar 2, 2017 at 22:45
  • $\begingroup$ As far as I can remember that was a mixture of copying it from somewhere and trial and error to adapt it to my needs. I actually use it in three different areas and in the end I included three more parameters: , 'active_object': bpy.context.object, 'edit_object': bpy.context.object, 'selected_objects': [helper] where I set the helper = bpy.data.objects['Empty'] and then adjusted override['selected_objects'] = [helper] and override['active_object'] = helper... This allowed me to call another bpy.ops.anim.keyframe_insert(override, type='Location') to create a new keyframe via python. $\endgroup$
    – Samoth
    Mar 2, 2017 at 23:04

2 Answers 2

1
$\begingroup$

You can add and adjust tracking markers without using operators.

Each movie clip has a tracking property which has a list of the tracks that have markers.

Every tracking.track is a point in that you are tracking. The markers for each track are keyframes of the tracks location.

import bpy

track_data = bpy.data.movieclips['movie_track'].tracking

for i in range(10):
    # this adds a new point to be tracked
    trck = track_data.tracks.new()
    for f in range(1,100,10):
        # this sets the location of the point at frame f
        x = (f+i) * 0.1
        y = (f+i) * 0.1
        trck.markers.insert_frame(f, co=(x,y))

# get track data
for t in track_data.tracks:
    for m in t.markers:
        print('marker on frame {} at {}'.format(m.frame, m.co))
$\endgroup$
2
  • $\begingroup$ Thanks but I have done this as the precursor to this question. What this doesn't answer is adding these tracks to the list of tracks that 2D stabilization uses so that I can then run the automatic stabilization tool. So far I only see operators as the way to do that. $\endgroup$
    – BorisKourt
    Mar 3, 2017 at 9:15
  • $\begingroup$ True - The stabilize_2d_add operator only changes the value of a flag, but as it isn't provided in the py-api we have to use the operator for that one step. So track_data.stabilization.tracks is presented as a list but it is really a dynamic subset of the tracks list based on the flag value, which would be why we can't alter it as a list. $\endgroup$
    – sambler
    Mar 3, 2017 at 16:19
0
$\begingroup$

Thanks to kostex on #blenderpython and @Samoth here.

The base answer is:

# Make a copy of the current context.
override = bpy.context.copy()

# Find the right area to override
for area in bpy.context.screen.areas:
     if area.type == 'CLIP_EDITOR':
         break

# Override the area
override['area'] = area

# Proceed with operator
bpy.ops.clip.stabilize_2d_add(override)

This is not the complete script for an application as that heavily depends on what else you need to do. A few things to keep in mind though:

  • You need to have a track selected to add it.
  • You need to access the Clip Editor (Movie Clip Editor) otherwise it may not exist at all.

Hope this helps others.

$\endgroup$
1
  • $\begingroup$ I wish I bothered to open the "Info" view before. If anyone is having similar questions, just open it. You will see context switches live as you edit manually, and can then translate them into your code. $\endgroup$
    – BorisKourt
    Mar 6, 2017 at 21:56

You must log in to answer this question.

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