2
$\begingroup$

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?

$\endgroup$
3
  • 1
    $\begingroup$ Interesting, but what about a video filter that only plays every nth frame? Blender Video Sequence Editor has Video>"Strobe", and you could output that to render your frames. Also, Effect Strip>"Speed Control" can help. You can even adjust "Strobe" on the Effect Strip itself. $\endgroup$ Jan 12, 2021 at 19:17
  • 1
    $\begingroup$ @CobyRandal I wasn't aware that existed when I wrote this question, but it's a good point. For some context, I was rendering in Cycles on a laptop and had a hard deadline to meet, so rendering every n frames was a practical necessity in addition to being an artistic choice. Also, each frame was getting rendered with as much motion blur as I could add, and (I think) the amount of blur would have been lower had I rendered it with a normal framerate. I really liked the look of it once I started, though, so the limitation wound up working in my favor. $\endgroup$
    – Tinstar
    Jan 13, 2021 at 16:44
  • $\begingroup$ I see, way to turn that limitation around! Yes, I would NOT recommend using strobe in VSE if your strip is a scene strip that requires rendering because strobe creates duplicate frames and Blender will re-render any duplicate frames, thus it multiplies render times needlessly. You could instead use Effect Strip>Speed Control. There's also a nice Add-on called Loom that lets you render every nth frame, and even more advanced options like rendering every keyframe etc! $\endgroup$ Jan 13, 2021 at 23:35

1 Answer 1

1
$\begingroup$

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.")

$\endgroup$

You must log in to answer this question.

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