Hi, I’m trying to add keyframes to the active sound strip in the Video Sequence Editor for the purpose of marking the beats of the audio. The code below successfully adds a few keyframes in the ‘volume’ property of the sound strip.
And now, I’d like to change the type of these keyframes. By default, they are of the type ‘KEYFRAME’, and I’d like to change it to ‘EXTREME’, ‘BREAKDOWN’, ‘MOVING_HOLD’ or ‘JITTER’, whatever.
This is the operator bpy.ops.action.keyframe_type(type='EXTREME') that gets called when I do it manually, but how can I achieve that in code for the strip?
def execute(self, context):
strip = bpy.context.scene.sequence_editor.active_strip
if strip.type == 'SOUND':
for frame in range(0, 200, 20):
strip['volume'] = 0.0
strip.keyframe_insert(data_path='volume', frame=frame)
return {'FINISHED'}
To modify the keyframe type (such as setting it to ‘Extreme’, ‘Jitter’, etc.) in the Dope Sheet, you’ll need to work with the keyframe’s type property after inserting it. Blender’s API allows you to set the keyframe type to various predefined types, including ‘KEYFRAME’, ‘BREAKDOWN’, ‘EXTREME’, ‘JITTER’, etc.
Here’s how you can adjust your script to set the keyframe type after inserting it:
Insert the Keyframe: As before, insert the keyframe without specifying the type argument.
Access the F-Curve and Keyframe Points: After inserting the keyframe, find the F-Curve for the property you’ve keyed and then iterate over its keyframe points to find the one you’ve just inserted.
Set the Keyframe Type: Once you’ve found the correct keyframe point, you can set its type property to your desired keyframe type (e.g., ‘EXTREME’, ‘JITTER’).
Here’s an updated version of your execute method incorporating these steps:
def execute(self, context):
sequence_editor = context.scene.sequence_editor
active_strip = sequence_editor.active_strip
if hasattr(active_strip, "osc_intensity"):
# Insert the keyframe
active_strip.keyframe_insert(data_path="osc_intensity", frame=bpy.context.scene.frame_current)
# Ensure the strip has animation data
if not active_strip.animation_data:
active_strip.animation_data_create()
# Find the F-Curve for 'osc_intensity'
fcurves = active_strip.animation_data.action.fcurves if active_strip.animation_data.action else []
fcurve = next((fc for fc in fcurves if fc.data_path == "osc_intensity"), None)
if fcurve:
# Find the keyframe you've just inserted and set its type
for keyframe in fcurve.keyframe_points:
if keyframe.co[0] == bpy.context.scene.frame_current:
keyframe.type = 'EXTREME' # Set the keyframe type here
else:
self.report({'ERROR'}, "F-Curve for 'osc_intensity' not found.")
else:
self.report({'ERROR'}, "Active strip does not have 'osc_intensity' property.")
return {'FINISHED'}
In this script, after inserting the keyframe for the osc_intensity property, it searches for the corresponding F-Curve. If the F-Curve is found, it iterates over the keyframe points to find the one that matches the current frame and then sets its type to ‘EXTREME’. You can replace ‘EXTREME’ with any valid keyframe type as per your requirement (e.g., ‘JITTER’, ‘KEYFRAME’, ‘BREAKDOWN’).