I am building a tool to convert FBX files into sequence OBJ files in batches. But I need to be able to change the end of the timeline to the last frame of the selected meshes animation. It's the last part I need to finish this script up. Any help would be greatly appreciated.

  • $\begingroup$ Do you know about python API ? Look for that and you'll find the code related to bpy. I remember now that I couldn't find the docs, what you can do is play around with python console autocomplete to figure out where that is at, probably in bpy.ops., whire are operator, but also maybe in bpy.data.scene somewhere in the timeline's settings where a variable can be set. $\endgroup$
    – Yvain
    Commented Jul 11, 2022 at 17:24

1 Answer 1


This should be enough for simple use. If you use keyframes for example in materials, you will need to add more for loops. At bottom of this page is the list, where you can find animation_data property.

import bpy
import math

last = 1

def find_last_keyframe(what):
    last = 0
    if what.animation_data is not None and what.animation_data.action is not None:
    for fcurve in what.animation_data.action.fcurves:
        for keyframe in fcurve.keyframe_points:
            last = max(last, keyframe.co[0])
    return last

last = max(last, find_last_keyframe(bpy.context.scene))
# if you want to get all objects in scene, use
# for obj in bpy.context.scene.objects:
for obj in bpy.context.selected_objects:
    last = max(last, find_last_keyframe(obj))

# use math.ceil instead of math.floor if you want to round the number up
bpy.context.scene.frame_end = math.floor(last)

update: ok, here is much simpler and cleaner solution:

import bpy
scene = bpy.context.scene
old_current_frame = scene.frame_current

while bpy.ops.screen.keyframe_jump(next=True) != {'CANCELLED'}:

scene.frame_end = scene.frame_current
scene.frame_current = old_current_frame
  • $\begingroup$ Thanks for the help, I must be messing something up cus it just keeps moving the end of the timeline to whatever I have last = to. IE frame 1 in the example above or whatever I change the number too. $\endgroup$
    – PSDWizzard
    Commented Jul 11, 2022 at 19:46
  • $\begingroup$ edit that code works if the funky animation coming in from the fbx files $\endgroup$
    – PSDWizzard
    Commented Jul 11, 2022 at 19:53
  • $\begingroup$ You don't need the innermost loop. Keyframe_points is sorted on x, so last = max(last, keyframe_points[-1].co[0]) is sufficient. Also, last should start at -1 in case the animation starts at 0. (Well, a very large negative number.) $\endgroup$ Commented Jul 11, 2022 at 20:01
  • $\begingroup$ Also note that if FBX supports multiple actions on a mesh, then you're going to need to walk what.animation_data.nla_tracks to find the longest NLA strip. $\endgroup$ Commented Jul 11, 2022 at 20:04
  • $\begingroup$ Actually, keyframes are not always in order, that's why I used for cycle instead of [-1]. For example bpy.context.scene.animation_data.action.fcurves[0].keyframe_points.add(1). You can call fcurve.update() to make sure its keyframe_points are in correct order. $\endgroup$
    – rooobertek
    Commented Jul 12, 2022 at 19:52

You must log in to answer this question.

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