2

I found a script (here: Can frames with no animation be automatically skipped?) that should do exactly what I need. But When I add it to the text editor and press run in Blender it does nothing. How do I get it running please? (I really have no clue how codes work, so explaining it to me like to an idiot would be very much appreciated.)

import bpy
import subprocess
import os
import shutil

def render_with_skips(start, stop): """ Take start and stop, and render animation only for animated frames. Still frames, are substituted into the output folder as copies of their equivalents. """

render_range = list(range(start, stop))

# create JSON like dictionary to store each
# animated object's fcurve data at each frame.
all_obj_fcurves = {}
for obj in bpy.data.objects:    
    obj_fcurves = {}

    try:
        obj.animation_data.action.fcurves
    except AttributeError:
        print("--|'%s' is not animated" % obj.name)
        continue

    print("\n--> '%s' is animated at frames:" % obj.name)

    for fr in list(range(start,stop+1)):
        fc_evals = [c.evaluate(fr) for c in obj.animation_data.action.fcurves]
        obj_fcurves.update({int(fr): fc_evals})
        print(fr, end=", ")
    print()

    all_obj_fcurves.update({obj.name: obj_fcurves})


# loop through each animated object and find its
# animated frames. then remove those frames from
# a set containing all frames, to get still frames.
still_frames = set(render_range)
for obj in all_obj_fcurves.keys():
    obj_animated_frames = []
    for i, fr in enumerate(sorted(all_obj_fcurves[obj].keys())):
        if i != 0:
            if all_obj_fcurves[obj][fr] != all_obj_fcurves[obj][fr_prev]:
                obj_animated_frames.append(fr)
        fr_prev = fr

    still_frames = still_frames - set(obj_animated_frames)

print("\nFound %d still frames" % len(still_frames))
print(sorted(still_frames), end="\n\n")


# render animation, skipping the still frames and
# filling them in as copies of their equivalents
filepath = bpy.context.scene.render.filepath

for fr in render_range:
    if fr not in still_frames or fr == render_range[0]:
        bpy.context.scene.frame_set(fr)
        bpy.context.scene.render.filepath = filepath + '%04d' % fr
        bpy.ops.render.render(write_still=True)
    else:
        scene = bpy.context.scene
        abs_filepath = scene.render.frame_path(scene.frame_current)
        #abs_path = '/'.join(abs_filepath.split('/')[:-1]) + '/'
        print("Frame %d is still, copying from equivalent" % fr)
        scn = bpy.context.scene
        shutil.copyfile(filepath + '%04d.png' % (fr-1), filepath + '%04d.png' % fr)

bpy.context.scene.render.filepath = filepath

start = bpy.data.scenes['Scene'].frame_start end = bpy.data.scenes['Scene'].frame_end render_with_skips(start,end) ```

Václav Musil
  • 350
  • 1
  • 13
  • What is your operating system? – Markus von Broady Jul 07 '21 at 14:36
  • I use Windows 10. – Václav Musil Jul 07 '21 at 14:53
  • Related https://blender.stackexchange.com/questions/108562/how-to-list-the-frame-numbers-which-contain-keyframes-in-python/108588#108588 Also https://blender.stackexchange.com/questions/1718/is-it-possible-to-render-only-keyframes-from-dope-sheet/23196#23196 to set up a more printer like range eg frames 1, 3, 4-40, 50 – batFINGER Jul 07 '21 at 14:57

0 Answers0