feat: blur適用

This commit is contained in:
Keisuke Hirata 2026-02-06 21:22:21 +09:00
parent c0ad2a551d
commit 0c9b646690
2 changed files with 116 additions and 26 deletions

View File

@ -133,8 +133,15 @@ def setup_strip_compositor_modifier(
type='COMPOSITOR', type='COMPOSITOR',
) )
# Set the node tree # Set the node tree/group (Blender 5.0 uses node_group instead of node_tree)
if hasattr(modifier, 'node_group'):
# Blender 5.0+
modifier.node_group = node_tree
elif hasattr(modifier, 'node_tree'):
# Blender 4.x
modifier.node_tree = node_tree modifier.node_tree = node_tree
else:
raise AttributeError("Compositor modifier has neither 'node_group' nor 'node_tree' attribute")
# Configure input mapping # Configure input mapping
# The modifier automatically maps strip image to first input # The modifier automatically maps strip image to first input

View File

@ -9,8 +9,6 @@ import bpy
from bpy.props import FloatProperty, IntProperty, StringProperty from bpy.props import FloatProperty, IntProperty, StringProperty
from bpy.types import Operator from bpy.types import Operator
from ..core.compositor_setup import get_or_create_blur_node_tree, setup_strip_compositor_modifier
class SEQUENCER_OT_apply_mask_blur(Operator): class SEQUENCER_OT_apply_mask_blur(Operator):
"""Apply blur effect using mask strip.""" """Apply blur effect using mask strip."""
@ -80,27 +78,112 @@ class SEQUENCER_OT_apply_mask_blur(Operator):
return {'CANCELLED'} return {'CANCELLED'}
try: try:
# Try using Compositor Modifier (preferred method) # Use Mask Modifier approach (Blender 5.0 compatible)
self._apply_with_modifier(context, video_strip, mask_strip) self._apply_with_mask_modifier(context, video_strip, mask_strip)
except Exception as e: except Exception as e:
self.report({'ERROR'}, f"Failed to apply blur: {e}") self.report({'ERROR'}, f"Failed to apply blur: {e}")
return {'CANCELLED'} return {'CANCELLED'}
return {'FINISHED'} return {'FINISHED'}
def _apply_with_modifier(self, context, video_strip: "bpy.types.Strip", mask_strip: "bpy.types.Strip"): def _apply_with_mask_modifier(self, context, video_strip: "bpy.types.Strip", mask_strip: "bpy.types.Strip"):
"""Apply blur using Compositor Modifier.""" """
# Get or create the blur node tree Apply blur using Mask Modifier.
node_tree = get_or_create_blur_node_tree(blur_size=self.blur_size)
# Add compositor modifier to the video strip Workflow:
modifier = setup_strip_compositor_modifier( 1. Duplicate the video strip
strip=video_strip, 2. Create Gaussian Blur effect on the duplicate
mask_strip=mask_strip, 3. Add Mask modifier to the blur effect (references mask strip)
node_tree=node_tree, 4. Composite with Alpha Over effect
"""
seq_editor = context.scene.sequence_editor
# Find available channels
used_channels = {s.channel for s in seq_editor.strips}
duplicate_channel = video_strip.channel + 1
while duplicate_channel in used_channels:
duplicate_channel += 1
blur_channel = duplicate_channel + 1
while blur_channel in used_channels:
blur_channel += 1
composite_channel = blur_channel + 1
while composite_channel in used_channels:
composite_channel += 1
# Step 1: Duplicate the video strip
if video_strip.type == 'MOVIE':
video_copy = seq_editor.strips.new_movie(
name=f"{video_strip.name}_copy",
filepath=bpy.path.abspath(video_strip.filepath),
channel=duplicate_channel,
frame_start=video_strip.frame_final_start,
)
elif video_strip.type == 'IMAGE':
# For image sequences, duplicate differently
video_copy = seq_editor.strips.new_image(
name=f"{video_strip.name}_copy",
filepath=bpy.path.abspath(video_strip.elements[0].filename) if video_strip.elements else "",
channel=duplicate_channel,
frame_start=video_strip.frame_final_start,
)
# Copy all elements
for elem in video_strip.elements[1:]:
video_copy.elements.append(elem.filename)
else:
raise ValueError(f"Unsupported strip type: {video_strip.type}")
# Match strip length
strip_length = video_strip.frame_final_end - video_strip.frame_final_start
video_copy.frame_final_end = video_copy.frame_final_start + strip_length
# Step 2: Create Gaussian Blur effect on the duplicate
blur_effect = seq_editor.strips.new_effect(
name=f"{video_strip.name}_blur",
type='GAUSSIAN_BLUR',
channel=blur_channel,
frame_start=video_strip.frame_final_start,
length=strip_length,
input1=video_copy,
) )
self.report({'INFO'}, f"Applied blur with Compositor Modifier") # Set blur size (Blender 5.0 API)
if hasattr(blur_effect, 'size_x'):
blur_effect.size_x = self.blur_size
blur_effect.size_y = self.blur_size
elif hasattr(blur_effect, 'size'):
blur_effect.size = self.blur_size
# Step 3: Add Mask modifier to the blur effect
mask_mod = blur_effect.modifiers.new(
name="FaceMask",
type='MASK'
)
# Set mask input (Blender 5.0 API)
if hasattr(mask_mod, 'input_mask_strip'):
mask_mod.input_mask_strip = mask_strip
elif hasattr(mask_mod, 'input_mask_id'):
mask_mod.input_mask_type = 'STRIP'
mask_mod.input_mask_id = mask_strip
# Step 4: Composite with Alpha Over effect
alpha_over = seq_editor.strips.new_effect(
name=f"{video_strip.name}_composite",
type='ALPHA_OVER',
channel=composite_channel,
frame_start=video_strip.frame_final_start,
length=strip_length,
input1=video_strip, # Base (original)
input2=blur_effect, # Blurred with mask
)
# Hide intermediate strips (but keep them active)
video_copy.mute = True
mask_strip.mute = True
self.report({'INFO'}, f"Applied blur with Mask Modifier (composite on channel {composite_channel})")
def _apply_with_meta_strip(self, context, video_strip: "bpy.types.Strip", mask_strip: "bpy.types.Strip"): def _apply_with_meta_strip(self, context, video_strip: "bpy.types.Strip", mask_strip: "bpy.types.Strip"):
""" """