Suppose we have an image strip in VSE and it has 2 keyframes for its opacity. How can I edit the values of each one of them via python?
Import the bpy module to access Blender's data.
If you just created the keyframes and are simply scripting in the text editor, you can look up the objects by context. You need to be certain that the strip has two keyframes and is selected (active) in the sequencer.
Get the active scene by context.
scene = bpy.context.scene
Get the active sequencer strip by context.
strip = scene.sequence_editor.active_strip
Lookup the fcurve connected to the
data_path of the active strip with it's name and property. (Look at batFINGER's answer on how to construct the data_path more elegantly with
data_path = 'sequence_editor.sequences_all["' + strip.name + '"].blend_alpha' fcrv = scene.animation_data.action.fcurves.find(data_path)
Assign some values to the
keyframe_points stored in the fcurve.
for i, y in [[0, 0.0], [1, 1.0]]: fcrv.keyframe_points[i].co.y = y fcrv.keyframe_points[i].handle_left.y = y fcrv.keyframe_points[i].handle_right.y = y
Force the sequencer to refresh.
If are trying to use this functionality from an addon or are unsure wether an active strip is selected or even if keyframes are present at all, you have to validate the data.
Encapsulate the functionality in a method, which can be aborted, if a precondition is missing. The required parameters are:
the scene's name
the sequencer strip's name
the values which are used to overwrite the existing keyframes values
def modify_strip_keyframes(scene_name, strip_name, keyframe_values = [1.0, 0.0]):
Get the scene by name, but return if it doesn't exist.
scene = bpy.data.scenes.get(scene_name) if scene == None: print("Scene not found.") return
Verify that there is
animation_data and a
sequence_editor. If there are no keyframes or no strips, these items will be
None. (Calling properties of
None will crash the script.)
if (scene.animation_data == None or scene.sequence_editor == None): print("No strips with keyframes.") return
Get the strip by name and get the fcurve associated with it's
blend_alpha (the opacity) property.
strip = scene.sequence_editor.sequences.get(strip_name) if strip == None: print("Strip not found.") return data_path = 'sequence_editor.sequences_all["' + strip_name + '"].blend_alpha' fcrv = scene.animation_data.action.fcurves.find(data_path) if fcrv == None: print("No opacity keyframes found.") return
Verify that there are as many
keyframe_points on the fcurve, as values have been supplied. Then loop over the points and assign the new values to the
if len(fcrv.keyframe_points) != len(keyframe_values): print("The strip has " + str(len(fcrv.keyframe_points)) + " keys, but " + str(len(keyframe_values)) + " values were supplied.") return for i in range(len(fcrv.keyframe_points)): key = fcrv.keyframe_points[i] key.co.y = keyframe_values[i] key.handle_left.y = keyframe_values[i] key.handle_right.y = keyframe_values[i] key.handle_left.x = key.co.x key.handle_right.x = key.co.x
To execute the function, call it and refresh the sequencer to visualize the change.
modify_strip_keyframes("Scene", "cat", keyframe_values = [1, 0.5]) bpy.ops.sequencer.refresh_all()
Find the fcurve based on its datapath
The suggestion of toggling into graph editor and looking at the visible fcurves, will be dependent on graph editor settings.
Instead create the datapath that is keyframed and search for it in the action fcurves.
VSE strip animations belong to the scene object.
gets the active strip
finds the path of the active strip from its ID object, the scene, an example for active movie strip named "Foo"
Searches for it within the scene actions fcurve collection
Note: Many or all of the properties above could have value
None including the sequence editor the active strip, the animation data and the action. Would need to test for each.
import bpy from bpy import context scene = context.scene seq = scene.sequence_editor active_strip = seq.active_strip datapath = active_strip.path_from_id("blend_alpha") action = scene.animation_data.action fc = action.fcurves.find(datapath)
#Assuming you are at VSE with your strip selected context.area.type = 'GRAPH_EDITOR' for fcurve in context.visible_fcurves: for keyframe in fcurve.keyframe_points: #Do w/e you want with the keyframe pass #We switch back to VSE context.area.type = 'SEQUENCE_EDITOR'
My misconception was that Graph > Keyframes. While the reality is Graph > FCurves > Keyframes.