Python API/highrescreenshot

Can’t see any mention of the High Res Screenshot tool in the Python documentation.
Is this planned for the future?

1 Like

Found it.
https://docs.unrealengine.com/en-US/PythonAPI/class/AutomationLibrary.html?highlight=screenshot#unreal.AutomationLibrary.take_high_res_screenshot

you might need to consider the scoped slow tasks.

Think a limitation of screenshot is that you can only do one per tick (frame), so you will have to make a way to somehow wait for tick to happen.

We solved this by having the python bridge run a method in tick that we implement in the python class to return next for generator functions. Not fully clear on the implementation but allows us to run


for _ in TakeMultipleScreenshots():
  yield MyEnum.WaitForNextFrame

Think I’ve seen that you can attach functions as callbacks to slate which to me seems like a much better solution but our method worked so haven’t touched it since.


import unreal
import time

class OnTick(object):
  """ Register a function and run it on tick, """
  def __init__(self):
    # make a generator function so we can call next on it,
    self.actors = (actor for actor in unreal.EditorLevelLibrary.get_selected_level_actors())

    # register a callback on tick
    self.on_tick = unreal.register_slate_post_tick_callback(self.__tick__)

  def __tick__(self, deltatime):
    """ Function we will call every tick, """
    try:
      print(deltatime) # Print the deltatime just for sanity check so we
      # know a tick was made,

      # Get the next actor from our generator function,
      actor = next(self.actors)
      actor_location = actor.get_actor_location()

      # Solve the camera position, and rotation
      position = actor_location + unreal.Vector(200.0, 200.0, 200.0)

      # roll, pitch, yaw
      rotation = unreal.Rotator(0.0, -45.0, -130.0)

      unreal.EditorLevelLibrary.set_level_viewport_camera_info(
        position,
        rotation
      )

      # Take the screenshot,
      unreal.AutomationLibrary.take_high_res_screenshot(
        1920,
        1080,
        actor.get_name() + ".png"
      )

    except Exception as error:
      print(error)
      unreal.unregister_slate_post_tick_callback(self.on_tick)

if __name__ == '__main__':
  instance = OnTick()

Seeing people using it to hook up Qt event to it https://github.com/techartorg/TAO-Wi…ndow-BaseClass I based this example from that.

I noticed that on_tick waits for texture streaming causing hiccups and skips a few screenshots, but pre_tick does the work here is updated version





import unreal


class capture(object):
  def __init__(self):
    unreal.EditorLevelLibrary.editor_set_game_view(True)
    self.actors = (actor for actor in unreal.EditorLevelLibrary.get_selected_level_actors())
    self.on_pre_tick = unreal.register_slate_pre_tick_callback(self.__pretick__)

  def __pretick__(self, deltatime):
    try:
      actor = next(self.preactors)
      shot_name = actor.get_name()
      unreal.EditorLevelLibrary.pilot_level_actor(actor)
      unreal.AutomationLibrary.take_high_res_screenshot(1920,1080, shot_name + ".png")
      unreal.EditorLevelLibrary.eject_pilot_level_actor()
    except Exception as error:
      print(error)
      unreal.unregister_slate_pre_tick_callback(self.on_pre_tick)




2 Likes

this still skips a few screenshots for me. anyone has a better fix for this?

Is it also possible to automate screenshots of buffer visualisation targets such as world depth mask, opacity mask, etc? Above code produces only .png for me and I am unable to find any reference for additional buffers.

Thank you very much in advance :slight_smile:

This IS Good Fix Code

import unreal
import time

class OnTick(object):
  """ Register a function and run it on tick, """
  def __init__(self):
    # make a generator function so we can call next on it,
    
    EditorLevelLibrary = unreal.EditorLevelLibrary()
    all_level_actors=EditorLevelLibrary.get_all_level_actors()
    CameraActors=[]
    for actor in all_level_actors:
        #CameraBool=actor.find_camera_component_when_view_target
        CameraComponent=actor.get_component_by_class(unreal.CameraComponent)
        #print("CameraComponent="+str(CameraComponent))
        #className=CameraComponent.get_class() 
        #print("CameraComponent.get_class() ="+str(className))
        if(str(CameraComponent)=="None"):
            pass
        else:
            #if(str(CameraComponent) in "CineCameraComponent"):
            #    pass
            #else: 
            CameraActors.append(actor)
    
    self.CameraActors=CameraActors
    #self.actors = (actor for actor in unreal.EditorLevelLibrary.get_selected_level_actors())
    self.actors = iter(CameraActors)
    
    self.tickcount=0
    
    # register a callback on tick
    self.on_tick = unreal.register_slate_post_tick_callback(self.__tick__)
    
    
    
  def __tick__(self, deltatime):
    """ Function we will call every tick, """
    try:
      print(deltatime) # Print the deltatime just for sanity check so we
      # know a tick was made,
        
      # Get the next actor from our generator function,
      actor = next(self.actors)
      """
      actor_location = actor.get_actor_location()
      actor_rotation = actor.get_actor_rotation() 
      # Solve the camera position, and rotation
      position = actor_location + unreal.Vector(0.0, 0.0, 0.0)

      # roll(z), pitch(tate), yaw(yoko)
      rotation = unreal.Rotator(actor_rotation.roll+0.0, actor_rotation.pitch+5.0,actor_rotation.yaw+0.0)
      
      unreal.EditorLevelLibrary.set_level_viewport_camera_info(
        position,
        rotation
      )
      """
      try:
          CameraComponent=actor.get_component_by_class(unreal.CameraComponent)
          print("actor= "+str(actor))
          print("CameraComponent= "+str(CameraComponent))
          unreal.AutomationLibrary.take_high_res_screenshot(
            1920,
            1080,
            actor.get_name() + ".hdr",
            camera=actor,
            capture_hdr=True,
            comparison_tolerance=unreal.ComparisonTolerance.HIGH,
            delay=0.25
          )
      except Exception as error:
          pass
      """
      unreal.EditorLevelLibrary.pilot_level_actor(actor)
      unreal.EditorLevelLibrary.editor_set_game_view(True)
      # Take the screenshot,
      unreal.AutomationLibrary.take_high_res_screenshot(
        1920,
        1080,
        actor.get_name() + ".hdr",
        camera=actor,
        capture_hdr=True,
        comparison_tolerance=unreal.ComparisonTolerance.HIGH,
        delay=0.25
      )
      
      unreal.EditorLevelLibrary.eject_pilot_level_actor()
      """
      # Count
      self.tickcount=self.tickcount+1
      
      CameraActors=self.CameraActors
      CameraActorsLen=len(CameraActors)
      endActor=CameraActors[CameraActorsLen-1]
      print("self.tickcount="+str(self.tickcount)+"  :CameraActorsLen="+str(CameraActorsLen))
      if(str(self.tickcount)==str(CameraActorsLen)):
          print("finish")
          unreal.unregister_slate_post_tick_callback(self.on_tick)
      
    except Exception as error:
      #pass
      print(error)
      try:
          unreal.unregister_slate_post_tick_callback(self.on_tick)
      except Exception as error:
          pass
#if __name__ == '__main__':
instance = OnTick()

I had the same problem, and had to check whether the capture was done or not. See here: