Skip to content

Instantly share code, notes, and snippets.

@loupzeur
Last active June 27, 2023 11:41
Show Gist options
  • Save loupzeur/ecb2294a40b0a5ea9bc68904b2bf7ffc to your computer and use it in GitHub Desktop.
Save loupzeur/ecb2294a40b0a5ea9bc68904b2bf7ffc to your computer and use it in GitHub Desktop.
blender sound silence cutter, will cut out sound of silence
bl_info = {
# required
'name': 'Silence Cutter Addon',
'blender': (3, 5, 1),
'category': 'Object',
# optional
'version': (0, 0, 1),
'author': 'LoupZeur',
'description': 'An addon that cut silence in video found in sequence editor, require pydub (pip install pydub)',
}
import bpy
from pydub import AudioSegment
silence_frame=[]
def detect_silence(sequence, frame_start=1, frame_end=250, frame_duration=100, threshold=1000):
if not hasattr(sequence, 'filepath'):
return
audio = AudioSegment.from_file(bpy.path.abspath(sequence.filepath), format="mp4")
global silence_frame
silence_frame=[]
# Set the initial state
is_silence = True
start_frame = frame_start
# Iterate through the frames
for frame in range(frame_start, frame_end + 1):
bpy.context.scene.frame_set(frame)
start_time = (frame-1) * 1000 / 30
end_time = start_time + frame_duration #frame_duration
average_volume = audio[start_time:end_time].rms
# Determine if the frame is silent
if average_volume > threshold:
if is_silence:
if frame-1<=start_frame:
start_frame=frame
is_silence = False
continue
bpy.ops.sequencer.select_all()
# Silence has ended
end_frame = frame - 1
bpy.ops.sequencer.split(frame=start_frame)
bpy.ops.sequencer.split(frame=end_frame)
silence_frame.append((start_frame,end_frame))
start_frame = frame
is_silence = False
else:
if not is_silence:
# Silence has started
start_frame = frame
is_silence = True
bpy.ops.sequencer.select_all(action='DESELECT')
for x in silence_frame:
for i in bpy.context.scene.sequence_editor.sequences:
if i.frame_final_start>=x[0] and i.frame_final_end<=x[1]:
i.select=True
# Call the detect_silence function
#detect_silence(bpy.context.scene)
#Action operator
class SilenceCutterOperator(bpy.types.Operator):
bl_idname = 'scr.video_cutter'
bl_label = 'Silence Cutter'
def execute(self, context):
for obj in bpy.context.selected_sequences:
detect_silence(
obj,
context.scene.sc_start,
context.scene.sc_end,
context.scene.sc_sound_length,
context.scene.sc_sound_threshold)
return {'FINISHED'}
# To Display Options
class SilenceCutterPanel(bpy.types.Panel):
bl_idname = 'SEQUENCE_EDITOR_SILENCE_CUTTER'
bl_label = 'Silence Cutter'
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
def draw(self, context):
col = self.layout.column()
for (prop_name, _) in PROPS:
row = col.row()
row.prop(context.scene, prop_name)
col.operator('scr.video_cutter', text='Cut')
CLASSES = [
SilenceCutterPanel,
SilenceCutterOperator,
]
PROPS = [
('sc_start', bpy.props.IntProperty(name='Start Frame', default=1)),
('sc_end', bpy.props.IntProperty(name='End Frame', default=250)),
('sc_sound_length', bpy.props.IntProperty(name='Audio Length to check (ms)', default=100)),
('sc_sound_threshold', bpy.props.IntProperty(name='Audio Threshold (rms)', default=1000)),
]
# Registering and Unregistering
def register():
for (prop_name, prop_value) in PROPS:
setattr(bpy.types.Scene, prop_name, prop_value)
for klass in CLASSES:
bpy.utils.register_class(klass)
def unregister():
for (prop_name, _) in PROPS:
delattr(bpy.types.Scene, prop_name)
for klass in CLASSES:
bpy.utils.unregister_class(klass)
if __name__ == '__main__':
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment