1
$\begingroup$

I have some edited audio strips inside sequence editor and I want to batch render them because rendering them one by one will take an eternity. so I thought of writing a simple add-one to do so and I mean what can go wrong!

this is a how my audio strips are

enter image description here

they each have at least one empty frame between them and the cuts with no empty frame are going to be one file. I decided to make those a meta strip since I use the Strip_jump command for setting render frames.

also if not obvious, its my first time writing scripts inside blender so yea

here is what I got so far:

import bpy
from bpy.types import Panel, Operator

    #make a panel in the sequence editor
class AUDIOSTRIPEXPORTER_PT_main_panel(Panel):
    bl_label = "Batch Audio Strip Exporter"
    bl_idname = "BATCH_PT_export_audio_strip"
    bl_space_type = 'SEQUENCE_EDITOR'
    bl_region_type = 'UI'
    bl_category = "Export"
    
    def draw(self, context):
        layout = self.layout

        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False

        rd = context.scene.render
        ffmpeg = rd.ffmpeg

        layout.prop(rd, "filepath", text="")

        if ffmpeg.format != 'MP3':
            layout.prop(ffmpeg, "audio_codec", text="Audio Codec")

        if ffmpeg.audio_codec != 'NONE':
            layout.prop(ffmpeg, "audio_channels")
            layout.prop(ffmpeg, "audio_mixrate", text="Sample Rate")
            layout.prop(ffmpeg, "audio_bitrate")
            layout.prop(ffmpeg, "audio_volume", slider=True)
            
            layout.operator("audiostripexporter.strip_export")        

    
class AUDIOSTRIPEXPORTER_OT_strip_export(Operator):
    bl_label = "Export"
    bl_idname = "audiostripexporter.strip_export"

    
    def execute(self, context):
        
        strip = bpy.ops.sequencer
        strip.strip_jump(next=True, center=False)
        bpy.ops.anim.start_frame_set()
        strip.strip_jump(next=True, center=False)
        bpy.ops.anim.end_frame_set()
        bpy.ops.sound.mixdown(filepath='filepath', codec='MP3')
        
        return {'FINISHED'}


classes = [AUDIOSTRIPEXPORTER_PT_main_panel, AUDIOSTRIPEXPORTER_OT_strip_export]
 
 
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        
 
def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
 
 
if __name__ == "__main__":
    register()

but ofc it doesn't work and gives me this error:

Error: Python: Traceback (most recent call last):
  File "\squencer_batch_audio_export.py", line 49, in execute
  File "C:\Program Files\Blender Foundation\Blender 2.92\2.92\scripts\modules\bpy\ops.py", line 132, in __call__
    ret = _op_call(self.idname_py(), None, kw)
RuntimeError: Error: The file couldn't be written with any installed writer.

so how should I go about fixing this error and the add-one?

$\endgroup$

1 Answer 1

1
$\begingroup$

well after a lot of testing I was able to do it and wrote something that does the trick for me here is the code, it not perfect but it works :)

import bpy
import os

#set the directory to where the blend file is
basedir = os.path.dirname(bpy.data.filepath)
# if the blend file is not saved, operator wont be called
if not basedir:
    raise Exception("Blend file is not saved")

# the panel in the UI of sequence editor
class AUDIOSTRIPEXPORTER_PT_sequencer_panel(bpy.types.Panel):
    bl_label = "strip exporter"
    bl_idname = "EXPORT_PT_exporter_panel"
    bl_space_type = 'SEQUENCE_EDITOR'
    bl_region_type = 'UI'
    bl_category = "Export"

    def draw(self, context):
        layout = self.layout
        
        row = layout.row()
        rd = context.scene.render
        layout.label(text="Strip Exporter")
        row = layout.row()
        row.scale_y = 1.0
        row.operator("export.audio_strip_exporter_operator")

# the export operator
class AUDIOSTRIPEXPORTER_OT_sequencer_operator(bpy.types.Operator):
    """Exports all the strips separetly"""
    bl_idname = "export.audio_strip_exporter_operator"
    bl_label = "Simple Object Operator"
    
    def execute(self, context):
        layout = self.layout
        strip = bpy.ops.sequencer
        selection = bpy.context.selected_editable_sequences
        select_num = len(selection)
        bpy.ops.sequencer.select_all(action='DESELECT')     
        number = 1
        
        for each_strip in selection:
            # name the file here, the code will add a number to each file like: FileName_001, FileName_002 ...
            name = "FileName_" + str(number)
            # joining the file name with the directory name for saving
            fn = os.path.join(basedir, name)
            
            bpy.ops.anim.start_frame_set()
            strip.strip_jump(next=True, center=False)
            bpy.ops.anim.end_frame_set()
            bpy.ops.sound.mixdown('INVOKE_DEFAULT', filepath=fn + ".mp3", container='MP3', codec='MP3')

            number = number + 1
            strip.strip_jump(next=True, center=False)
        return {'FINISHED'}

classes = [AUDIOSTRIPEXPORTER_PT_sequencer_panel, AUDIOSTRIPEXPORTER_OT_sequencer_operator]
 
 
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        
 
def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
 
 
if __name__ == "__main__":
    register()

now as I said its not perfect so you have to change stuff to fit your needs

and remember:

  • it renders the files to the folder where the blend file is
  • you need to put cursor at the beginning of the first strip
  • add at least a few empty frames between each strip
  • you have to change the export name in the code

thats all I think

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .