In/Out Marks for render node in batch

Before I go and make an ass out of myself by making a feature request that is actually already there (had a bad one recently)…does anyone know if it’s possible to set the in/out marks of a render node. I don’t see it listed in any of the attributes of the node and trying render_node.in_mark = clip.in_mark yields an error.

Many thanks

It’s not the most elegant solution, but in cases where your source clip does not already have in and out points, you can just set them (without even leaving batch!) and then t-click the result to transfer them to your render node. I do this constantly.

I agree though, it would be nice if there were editable in/out fields in the render node parameters.

I do love the good 'ol t-click. This is more for the automatic creation of batchgroups based on a clip from a conform. I’ve managed to grab all the other metadata but the in/out points of the render node can’t be set via python, at least from what I can tell.

Ah. Sorry.

I will say that I think I’ve worked places where this happens automatically. @Stefan did you crack this?

What about range_start and range_end attributes? Haven’t tested it, but sound’s like it should do what you are looking for, right? :slight_smile:

Screen Shot 2022-01-14 at 16.44.18

Claus is right. These are the attributes you need to use to set the Render Range From and To fields.

That being said, I am curious to know where you looked at when you mention “I don’t see it listed in any of the attributes of the node” as this is in the documentation and listed in the Python Console.

I suppose I’m not explaining it clearly enough.

If you t-click a clip that you’ve matched out of an edit it’ll keep the in/out points whilst expanding the handles (at least based on my preferences). The resulting render also has those in/out markers while still rendering the duration of the whole shot…so including handles. You can then play that render back using the option “In to Out” and see it in context of the edit without having to actually put it into the edit.

Correct me if I’m wrong, but range in/out is the render range not the in/out markers of the resulting render.

@fredwarren

render_node = flame.batch.create_node("Render")
render_node.attributes
1 Like

Ok, I misunderstood you in the first place. Makes totally sense what you want to do, but I think I don’t know, how to do that. :smiley:

I tried T-click in batch and did a render and I don’t see this behavior (there’s no In and Out set on the render clip)

Is this maybe a BFX thing?

In anycase, theoretically, you can override “batch_render_begin” and “batch_render_end” hooks. They aren’t documented in the online help, but you can see them in this file:
/opt/Autodesk/flame_2021.1/python/batch_hook.py

So, what you can do is at “batch_render_begin”, grab the In and Out attributes from the source clip you’re rendering from. What I do for our batch templates is I have a special Compass which only has one clip like this:

Then I search for that compass and grab the one source clip:

    # Check for the MAIN CLIP in the _MAINCLIP_ Compass
    main_plate_compass = get_first_node_begin_with("_MAINCLIP_", 'Compass')
    clipnodes = []
    for clip in main_plate_compass.nodes:
        if clip.type == 'Clip':
            clipnodes.append(clip)
    if len(clipnodes) > 1:
        message_warn(MW_INIT_ERR_TOO_MANY_CLIPS)
        return
    if len(clipnodes) == 0:
        message_warn(MW_INIT_ERR_CLIP_MISSING)
        return

I also have a special “RENDER” compass where we keep the render and write nodes that need to be dynamically initialized via script:

We have the user run a batch initialization script and the render nodes are set to the full length of the clip. BUT, if the clip has a slip then it gets messy. Getting the length of the clip will not take into account the slip. You have to programmically, set the batch timeline to the first frame, grab the current TC of the clip and the end TC of the clip and figure out the range that way:

    # Go to the first frame of the batch comp
    batchstartfr = flame.batch.start_frame.get_value()
    flame.batch.current_frame = batchstartfr

    clip_start_tc = clip.start_time.get_value()
    flame.batch.current_node.set_value(clipnode)  # THIS fixes bug where clip.current_time doesn't update when you get current batch frame
    clip_current_tc = clip.current_time.get_value()  # if clip is slipped, then current tc != start tc
    # Calculate discarded heads by how much the clip is slipped.  User probably slipped the clip to give it the proper heads
    # For example, the source has 24fr heads and tails...but User slipped the clip 16fr to get 8 frames of heads.
    cliphead = clip_current_tc - clip_start_tc
    clipdur = clip.duration  # This is the total duration of the clip with NO slip
    clip_length = clipdur.frame - cliphead.frame * 2  # Clip length is source duration minus discarded heads and minus discarded tails (assume heads = tails)


render_compass = get_first_node_begin_with("_RENDER_", 'Compass')
    rnodes = []
    for n in render_compass.nodes:
        ntype = n.type
        if ntype == "Render" or ntype == "Write File":
            rnodes.append(n.name.get_value())
            n.frame_rate = comp_fps
            if ntype == "Render":
                n.source_timecode = clip_current_tc
                n.record_timecode = clip_current_tc
            else:
                # In Write File nodes, TC is not offset by render range, so subtract 1 on TC for the slate.
                n.source_timecode = clip_current_tc - 1
                n.record_timecode =  clip_current_tc - 1
            n.range_start = batchstartfr - 1  # Render from frame 0 (or 1000) where slate starts
            n.range_end = comp_length + batchstartfr - 1
            # n.shot_name = '<batch name>'  # I guess flame tokens don't work
            n.shot_name = clipname

Anyways…
The “batch_render_begin” hook is defined like this:
def batch_render_begin(info, userData, *args, **kwargs):
The “userData” is a dictionary that you can use to pass “black box data” to the batch_render_END" hook.

So when the render ends, the batch_render_end hook is called like this:
def batch_render_end(info, userData, *args, **kwargs):

You can retrieve from “userData”, the in and out info you stored in from here. Also, take a look at “Info”…it’s a dictionary that MAY have a reference to the rendered clip. I never used it…and it’s not documented for this hook. The “info” attributes for Write node hooks IS documented (see “batch_export_begin / batch_export_end”) and it’s probably has the same type of dict entries. So you may get lucky and get a reference to the rendered clip and then set the in and out points.

2 Likes

Wasn’t there a feature to auto sync renders in connected workflow some versions ago with the “Smart Replace” function in render node via the “Smart Shot Replace”? (sry I’ve actually never used it).
That will automatically replace your rendering with a clone from the original clip, which has the given in/out point. Maybe that could be some direction where you can spare Python, but maybe also need to extend some workflow in the batch creation, as the in/out need to be handles and only works, if you know your in/out before creating the batch.

I appreciate the input and thoughts but it seems like no, it is not possible to set those values via the existing Python API. Is that correct @fredwarren? I’m more than happy to make a feature request, I just wanted to double check before doing so.

@kyleobley No, the In/Out Marks are not available in the Python API.