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.