*Functional intermission with light background jazz*
Table Of Contents
show
Context
I use Blender’s VSE to edit videos, and I am trying to speed up working with text sequences, which I use a lot for captions. We got to the point where we want to make it generically usable for everyone by providing a user interface in addon preferences for managing presets and their associated key bindings. However, there were some odd issues with with that, so in the meantime I wanted to publish something functional that leverages Blender’s own keymap editor.
Quicker Text Editing v0.5a
This alpha release makes four operators available for binding in Blender’s keymap editor:
sequencer.set_text_colour
sequencer.set_text_location
sequencer.set_text_size
sequencer.set_text_duration
Installation and Usage
- Save or download the python code below to a file named (eg)
quicker-text-editing.py
. Install this viaBlender > Preferences > Add-ons > Install...
- Navigate to
Preferences > Keymap
and expand the part of the keymap you would like to bind the keys, I usedSequencerCommon > Sequencer > Sequencer (Global)
. - Add bindings as you see fit
In the example below I bound F5 through F8 to one operator each:
Demo
Code
"""quicker-text-editing.py -- text addon for Blender VSE""" import bpy bl_info = { "name": "Quicker Text Editing for VSE", "author": "bertieb", "version": (0, 5), "blender": (3, 3, 0), "location": "Video Sequence Editor > Text Strip", "description": "Quicker editing of text: position, colour, size, duration", "warning": "", "doc_url": "", "category": "Sequencer", } class TextSequenceAction(bpy.types.Operator): """Implements operations for quickly manipulating text sequences in VSE""" bl_idname = "sequencer.textsequenceaction" bl_label = "Text Sequence Action" def execute(self, context): """One works on a text sequence... but does nothing!""" return {"FINISHED"} @classmethod def poll(cls, context): """Ensure we're in the VSE with at least one sequence selected""" return (context.scene and context.scene.sequence_editor and context.selected_editable_sequences is not None) class SetTextColour(TextSequenceAction): """Set colour of text sequence[s]""" bl_idname = "sequencer.set_text_colour" bl_label = "Set Text Colour" colour: bpy.props.FloatVectorProperty( name="Text colour", subtype='COLOR', description="Colour for text", size=4, min=0.0, max=1.0, default=(0.0, 0.0, 0.0, 1), # black in RGBA ) _colour = None _keymaps = [] def __init__(self): super().__init__() if self._colour: self.colour = self._colour def execute(self, context): for strip in bpy.context.selected_editable_sequences: if strip.type == "TEXT": strip.color = self.colour return {'FINISHED'} class SetTextLocation(TextSequenceAction): """Set location of text sequence[s]""" bl_idname = "sequencer.set_text_location" bl_label = "Set Text Location" _location = None location: bpy.props.FloatVectorProperty( name="Text location", subtype='COORDINATES', description="Location for text", size=2, min=-2000, max=2000, default=(0.5, 0.5) # (x,y) ) _location = None def __init__(self): super().__init__() if self._location: self.location = self._location def execute(self, context): for strip in bpy.context.selected_editable_sequences: if strip.type == "TEXT": strip.location = self.location return {'FINISHED'} class SetTextDuration(TextSequenceAction): """Set location of text sequence[s]""" bl_idname = "sequencer.set_text_duration" bl_label = "Set Text Duration" duration: bpy.props.IntProperty( name="Duration (frames)", subtype='TIME_ABSOLUTE', description="Duration for text", min=1, max=1048574, default=60 # frames ) _duration = None def __init__(self): super().__init__() if self._duration: self.duration = self._duration def execute(self, context): for strip in bpy.context.selected_editable_sequences: if strip.type == "TEXT": strip.frame_final_duration = self.duration return {'FINISHED'} class SetTextSize(TextSequenceAction): """Set size of text sequence[s]""" bl_idname = "sequencer.set_text_size" bl_label = "Set Text Size" size: bpy.props.FloatProperty( name="Text font size", subtype='UNSIGNED', description="Size for text", min=0.0, max=2000.0, default=100.0 # font size ) _size = None def __init__(self): super().__init__() if self._size: self.size = self._size def execute(self, context): for strip in bpy.context.selected_editable_sequences: if strip.type == "TEXT": strip.font_size = self.size return {'FINISHED'} REGISTER_CLASSES = [SetTextLocation, SetTextDuration, SetTextSize, SetTextColour] def register(): for classname in REGISTER_CLASSES: bpy.utils.register_class(classname) def unregister(): for classname in REGISTER_CLASSES: bpy.utils.unregister_class(classname) if __name__ == "__main__": register()