So close yet so far (I think)

A function within an addon am creating is suppose to rename the file ouput using tokens. This is based on the Oscurart tools.

The projects consists of markers on every frame with different binded cameras. The rendered image name needs to consist of a Marker and Camera.

def replaceMarker (dummy):
    global renderpath
#Set Tokens variables
    cameraCURRENT = bpy.context.scene.camera.name
    markerTIMELINE = []
    for marker in bpy.context.scene.timeline_markers:
        name = marker.name
    markerCURRENT = markerTIMELINE[bpy.context.scene.frame_current-1]

    tokens = {
#Replace filename output
    renderpath = bpy.context.scene.render.filepath

    bpy.context.scene.render.filepath = renderpath.replace("$Marker",tokens["$Marker"]).replace("$Camera",tokens["$Camera"])
#Clear list to repeat sequence

The function does not replace the marker and only uses one camera name.

Am I suppose to more this to the init.py? How can I call the function between every frame?


EDIT Question to circumvent the issue, it is possible to access the Metadata in fileoutput and use it to rename the file?

  • $\begingroup$ Have you checked that the file path actually contains the markers? If it doesn't, then it can't replace them. $\endgroup$
    – Robert Gützkow
    Dec 3, 2019 at 11:59
  • $\begingroup$ Yes, I can using a dummy file to test the addon. The output is set to /tmp\AAA - $Marker - $Camera $\endgroup$
    – Sharl
    Dec 3, 2019 at 12:11
  • $\begingroup$ I think we are missing some context information in how this function is used that would explain the problem. $\endgroup$
    – Robert Gützkow
    Dec 3, 2019 at 12:43
  • $\begingroup$ Basically, I am creating a proof of concept to develop an addon which will integrate Blender in the Company's future 3D pipeline. All functions are outside the init.py file, called upon with the import function. As I progress, I can keep adding functions and tools to assist none 3D personal. The file output rename function is in its own file. $\endgroup$
    – Sharl
    Dec 3, 2019 at 13:18
  • $\begingroup$ I would very much like to see a solution for this. My current project has several cameras bound to the timeline, and I want my output frames named according to the cameras they were rendered from. $\endgroup$ Apr 29, 2020 at 3:53

1 Answer 1


So sorry for the very late reply. I found the answer in another thread and with some help.

But below is the Render Function I am currently using.

    bl_idname = "render.colorways"
    bl_label = "Render list"
    bl_description = "Render colorways with marker in filename"

    # Define some variables to register
    _timer = None
    shots = None
    stop = None
    rendering = None
    path = "/tmp/"

    # Set up the handler methods
    def pre(self, scene, depsgraph):
        self.rendering = True

    def post(self, scene, depsgraph):
        self.rendering = False

    def cancelled(self, scene, depsgraph):
        self.stop = True

    def execute(self, context):
        # Define the variables during execution. This allows
        # to define when called from a button
        self.stop = False
        self.rendering = False

        # Get all markers in a list and assign them to shots variable
        itemmarkers = bpy.context.scene.timeline_markers.items()
        self.shots = []
        for m in itemmarkers:
        #don't know why but I need to begin 1 frame before the start
        bpy.context.scene.frame_set(bpy.context.scene.frame_start - 1)
        self.path = context.scene.render.filepath


        # The timer gets created and the modal handler
        # is added to the window manager
        self._timer = context.window_manager.event_timer_add(0.5, window=context.window)

        return {"RUNNING_MODAL"}

    def modal(self, context, event):
        if event.type == 'TIMER':
            scn = context.scene
            # filename prefix ans suffix
            firstpart = bpy.context.scene.TextInputProps.nameprefix
            lastpart = bpy.context.scene.TextInputProps.namesuffix
            # No frames in the list or user hits ESC
            if True in (scn.frame_current >= scn.frame_end, self.stop is True):

                # We remove the handlers and the modal timer to clean everything

                # Reset the output path
                scn.render.filepath = self.path
                return {"FINISHED"}

            elif self.rendering is False: # Nothing is currently rendering.
                                          # Proceed to render.
                # Get the marker from the list
                marker_name  = self.shots[scn.frame_current]

                #Create filename variable
                if firstpart == "" and lastpart == "":
                    finalfilename = marker_name
                elif firstpart == "" and lastpart != "":
                    finalfilename = marker_name +"_"+ lastpart
                elif firstpart != "" and lastpart == "":
                    finalfilename = firstpart +"_"+ marker_name
                    finalfilename = firstpart +"_"+ marker_name +"_"+ lastpart
                # Assemble the file path and filename
                scn.render.filepath = os.path.join(self.path, finalfilename + "." + scn.render.image_settings.file_format)

                # Call the render operator
                bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)
                # Set the next frame
                scn.frame_set(scn.frame_current + 1)

        return {"PASS_THROUGH"}

There is one issue, in the render process certain frames don't save. Perhaps optimizing the loop the statement in the def modal would help.

I hope this helps.


You must log in to answer this question.

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