# Getting interstitial compositor frames when using frame step

I'm trying for a really jittery stop-motion like effect by using frame step to render on the twos (or threes, or fours). Rendering this normally and getting a video file out makes the frames happen at the expected speed.

However, I'd also like to get some render passes out of the compositor. I currently have a File Output node set to get the mist, emission, and cryptomatte mask/image passes and make them image sequences. These are named appropriate to the frame step (animating on the fours gets me Mist_0001, Mist_0005, Mist_0009, etc), but since they're single images, importing them as an image sequence into another video editor doesn't get me the intermediate frames. I essentially have one render that's at the correct, jerky speed, and four image sequences that are going twice as fast.

And since I'm using Resolve, they won't even import normally - Resolve likes image sequences to be labeled sequentially. An 0001, 0005, and 0009 would get imported as separate images, rather than a clip.

So: is there a good way, in or out of Blender, to (I'm assuming) copy the intermediate frames, with correct numbering?

This does it, though it uses a separate python script instead of something automated in Blender. Use it with python3 script.py [subfoldername] [framecount].

This is based on my setup, where each render pass has its own subfolder. This will search through all the files in a subfolder, determine their frame step, and generate duplicate frames based on the gaps. None of the pass files have special names, so everything's 001.png, etc.

import shutil
import sys
import os

# figure out the frame difference
def getFrameStep(list):
step = int(list[1][:-4]) - int(list[0][:-4])
return step

# how many 0's should precede the number
def getFrameFilename(index):
maximum = 4
l = len(str(index))
return '0' * (maximum - l) + str(index)

# generate frames based on missing steps
def framesFromParent(path, parent, step):
starter = int(parent[:-4]) + 1
for f in range(step-1):
if (starter + f > int(FRAMECOUNT) and (FRAMECOUNT) != -1):
return

name = path + "/" + getFrameFilename(starter + f) + ".png"
shutil.copy(path + "/" + parent, name)

# ignore OSX DS_Store files
def cleanDSStore(list):
s = ".DS_Store"
index = list.index(s) if s in list else None
if index == None:
return list

list.pop(index)

return list

# check if command line args exist
def checkArg(index, default):
if len(sys.argv) > index:
if isinstance(sys.argv[index], int):
return int(sys.argv[index])
return sys.argv[index]
else:
return default

########

# the subfolder containing the shot you want
SHOTFOLDER = checkArg(1, "1-entering")

"""
using frame step means sometimes your animation won't divide
evenly, and if you try to replace frames exclusively by the
frame step, you'll wind up with more frames than the original
animation. Set the frame count if you want to limit the total
number of files generated to 50 frames.
"""
FRAMECOUNT = checkArg(2, -1)

for root, dirs, files in os.walk(SHOTFOLDER, topdown=False):
for name in dirs:
for r, d, f in os.walk(os.path.join(root, name)):
folder = os.path.join(root, name)
files = os.listdir(r)
files = cleanDSStore(files)
step = getFrameStep(files)

for f in files:
framesFromParent(folder, f, step)


("Why don't you just use OpenEXR?" "It's a huge pain to work with in Resolve.")