def AddSequencerSectionBoolKeysByIniFile(SequencerSection, SectionFileName, FileLoc): Config = ConfigParser.ConfigParser() Config.read(FileLoc) for option in Config.options(SectionFileName): frame = float(option)/float(frameRateNumerator) #FrameRate value = Config.getboolean(SectionFileName, option) SequencerSection.get_channels()[0].add_key(unreal.FrameNumber(frame*float(frameRateNumerator)),value)
def AddSequencerSectionTransformKeysByIniFile(sequencer_section, track_dict): for key in track_dict.keys(): frame = float(key) / float(frameRateNumerator) # FrameRate value = track_dict[key] # (x,y,z x,y,z x,y,z) frame = unreal.FrameNumber(frame * float(frameRateNumerator)) sequencer_section.get_channels()[0].add_key( frame, value["location_x"]) sequencer_section.get_channels()[1].add_key( frame, value["location_y"]) sequencer_section.get_channels()[2].add_key( frame, value["location_z"]) sequencer_section.get_channels()[3].add_key( frame, value["rotation_x"]) sequencer_section.get_channels()[4].add_key( frame, value["rotation_y"]) sequencer_section.get_channels()[5].add_key( frame, value["rotation_z"]) sequencer_section.get_channels()[6].add_key( frame, value["scale_x"]) sequencer_section.get_channels()[7].add_key( frame, value["scale_y"]) sequencer_section.get_channels()[8].add_key( frame, value["scale_z"])
def add_keys_to_transform_channel(transform_component, transforms, channel): frame_number = unreal.FrameNumber() idx = 0 for transform in transforms: val = transform[transform_component] channel.add_key(unreal.TimeManagementLibrary.add_frame_number_integer(frame_number, idx), val) idx += 1
def AddSequencerSectionTransformKeysByIniFile(SequencerSection, SectionFileName, FileLoc): Config = ConfigParser.ConfigParser() Config.read(FileLoc) for option in Config.options(SectionFileName): frame = float(option)/float(frameRateNumerator) #FrameRate list = Config.get(SectionFileName, option) for x in range(0, 9): #(x,y,z x,y,z x,y,z) value = float(list.split(',')[x]) SequencerSection.get_channels()[x].add_key(unreal.FrameNumber(frame*float(frameRateNumerator)),value)
def add_actor_to_sequence(target_sequence, actor): """ Add the specified cube into the target sequence with keys :param unreal.MovieSceneSequence target_sequence: The sequence to add to :param unreal.Actor actor: The cube to be added :return: """ frame_rate = target_sequence.get_display_rate() frame_rate = frame_rate.numerator / frame_rate.denominator actor_location = actor.get_actor_location() actor_location = [actor_location.x, actor_location.y, actor_location.z] sequence = target_sequence.add_possessable(actor) transform_track = sequence.add_track(unreal.MovieScene3DTransformTrack) new_section = transform_track.add_section() new_section.set_range_seconds(0, SEQUENCE_LENGTH) channels = new_section.get_channels() # Add some motion flare adjusted_location = [v + random.randint(-500, 500) for v in actor_location] for channel in channels: if channel.get_name() not in CHANNELS_TO_KEY: continue # Key the ranges as needed channel_index = CHANNELS_TO_KEY.index(channel.get_name()) channel.add_key(unreal.FrameNumber(0), actor_location[channel_index], interpolation=unreal.MovieSceneKeyInterpolation.LINEAR) channel.add_key(unreal.FrameNumber(SEQUENCE_LENGTH * frame_rate), adjusted_location[channel_index], interpolation=unreal.MovieSceneKeyInterpolation.LINEAR)
def add_key_example(sequencer_asset_path): print( "This example inserts a new key at half the current key's time with the opposite value as the current key. Assumes you have bool keys in an object binding!" ) # Create a test sequence for us to use. sequence = unreal.load_asset("/Game/TestKeySequence", unreal.LevelSequence) # Iterate over the Object Bindings in the sequence as they're more likely to have a track we can test with. for binding in sequence.get_bindings(): for track in binding.get_tracks(): print(track) for section in track.get_sections(): print("\tSection: " + section.get_name()) for channel in section.get_channels(): print("\tChannel: " + channel.get_name()) keys = channel.get_keys() for key in keys: # Calculate a new Frame Number for the new key by halving the current time new_time = unreal.FrameNumber( key.get_time(unreal.SequenceTimeUnit. TICK_RESOLUTION).frame_number.value * 0.5) # Add a new key to this channel with the opposite value of the current key new_key = channel.add_key( new_time, not key.get_value(), 0.0, unreal.SequenceTimeUnit.TICK_RESOLUTION) # Print out our information. This shows how to convert between the Sequence Tick Resolution (which is the number a key is stored on) # and the Display Rate (which is what is shown in the UI) as well. new_time_in_display_rate = unreal.TimeManagementLibrary.transform_time( unreal.FrameTime(new_time), sequence.get_tick_resolution(), sequence.get_display_rate()) print( 'Inserting a new key at Frame {0}:{1} (Tick {2}) with Value: {3}' .format( new_time_in_display_rate.frame_number.value, new_time_in_display_rate.sub_frame, new_time.value, new_key.get_value())) print("Finished!") return
def add_time_to_keys(sequence, key_array, time): print('Adding {0} frames (time) to {1} keys in array...'.format( time, len(key_array))) # Initialize a FrameNumber from the given time and then convert it to a FrameTime with no sub-frame. Keys can only exist on whole FrameNumbers. time_as_frame_time = unreal.FrameTime(unreal.FrameNumber(time)) # Now transform from our Display Rate to the internal tick resolution. time_as_tick = unreal.TimeManagementLibrary.transform_time( time_as_frame_time, sequence.get_display_rate(), sequence.get_tick_resolution()) # Now we apply the new offset to each key in the array. key.get_time() and key.set_time() can take a frame number in either # Display Rate space or Tick Resolution. If you only want keys on whole frames as shown by the UI then you can use Display Rate # (which is the default for these functions). However, if you want to put keys on frames between keys you can put one on # every tick of the Tick Resolution (sequence.get_tick_resolution()). # key.set_key(...) optionally supports using a sub-frame (clamped 0-1) when used in combination with a DISPLAY_RATE time unit. # Example: # - set_key(5) - Sets the key to frame number 5 at your current display rate. If your sequence is at 30fps this will set you to 5/30, or 1/6th of a second. # - set_key(5, 0.5) - Sets the key to frame number 5.5. This will not be aligned in the UI and the precision is limited to your sequence's internal tick resolution. # - set_key(5, 0.0, unreal.SequenceTimeUnit.TICK_RESOLUTION) - Sets the key to internal tick number 5. If you have a 24,000 tick resolution and a display rate of 30fps this sets it to 5/(24000/30) of a frame, aka 5/800th of a frame at 30fps = 0.00625s in! # - set_key(5, 0.75, unreal.SequenceTimeUnit.TICK_RESOLUTION) - Invalid. Sub-Frames are not supported when using TICK_RESOLUTION. Will print a warning and set the sub-frame to 0. # # Conversely, key.get_time() can optionally take a uneal.SequenceTimeUnit enum value to determine what resolution to return the time in. # get_time() returns a unreal.FrameTime, because a FrameTime contains information about sub-frame values which is important if you've placed # a key between frames and want to get that again later. # # Example: # - get_key() - Returns the display rate frame of the key (which will match the UI). # This means "key.set_key(key.get_key().frame_number, key.get_key().sub_frame)" will not have any affect on position as the defaults for both are in the same resolution. # - get_key(unreal.SequenceTimeUnit.DISPLAY_RATE) - Returns the internal tick that this key is on with a 0.0 subframe value. # This means "key.set_key(key.get_key(unreal.SequenceTimeUnit.TICK_RESOLUTION), 0.0, unreal.SequenceTimeUnit.TICK_RESOLUTION)" will not have any affect on position. for key in key_array: print('CurrentTime: {0} NewTime: {1}'.format( key.get_time().frame_number, key.get_time().frame_number + time)) key.set_time(key.get_time().frame_number + time, 0.0, unreal.SequenceTimeUnit.DISPLAY_RATE) print('Finished!') return
def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): for key in track_dict.keys(): frame = unreal.FrameNumber(int(key)) value = track_dict[key] sequencer_section.get_channels()[0].add_key(frame, value)
def setup_capture(self): self.read_config(False) path = unreal.DirectoryPath(self.output_directory) self.capture_settings.set_editor_property("output_directory", path) self.capture_settings.set_editor_property("output_format", self.FileName_LE.text()) index = self.Proctocol_Combo.currentIndex() protocol = proctocol_dict.get(index) capture = unreal.AutomatedLevelSequenceCapture() section = "MovieSceneCaptureUIInstance AutomatedLevelSequenceCapture" for option, attr in self.json_config.get(section).items(): if not self.config.has_option(section, option): continue v = self.config.get(section, option) if option == "Settings": capture.set_editor_property("settings", self.capture_settings) continue elif attr == "custom_end_frame": pattern = re.compile("(\d+)") num = pattern.search(v).group(0) v = unreal.FrameNumber(int(num)) elif attr == "custom_start_frame": pattern = re.compile("(\d+)") num = pattern.search(v).group(0) v = unreal.FrameNumber(int(num)) elif attr == "audio_capture_protocol_type": v = unreal.SoftClassPath(v) elif attr == "additional_command_line_arguments": pass elif attr == "image_capture_protocol_type": capture.set_image_capture_protocol_type(protocol) protocol_name = ( "MovieSceneCaptureUIInstance_ImageProtocol %s" % protocol.__name__) print(protocol_name) protocol = capture.get_image_capture_protocol() for pro_name, pro_attr in self.json_config.get( protocol_name, {}).items(): if not self.config.has_option(protocol_name, pro_name): continue pro_v = self.config.get(protocol_name, pro_name) if pro_attr == "capture_gamut": pro_v = HDRCaptureGamut[pro_v.upper()] elif pro_attr == "post_processing_material": if pro_v == "None": continue pro_v = unreal.SoftObjectPath(pro_v) elif pro_attr == "include_render_passes": # NOTE 获取勾选的 passes name_list = [ cb.text() for cb in self.Pass_Container.findChildren( QtWidgets.QCheckBox) if cb.isChecked() ] print(name_list) pro_v = unreal.CompositionGraphCapturePasses(name_list) else: pro_v = ast.literal_eval(pro_v) protocol.set_editor_property(pro_attr, pro_v) continue else: v = ast.literal_eval(v) capture.set_editor_property(attr, v) return capture
def render_sequence_to_movie(sequencer_asset_path, level_name, level_path, output_file_name, resolution=(1280, 720), game_mode_override='None', warm_up_frame_count=0, delay_before_warm_up=0.0, delay_before_shot_warm_up=0.0, delay_every_frame=0.0, use_burn_in=False, encorder_format='422'): # 1) Create an instance of our UAutomatedLevelSequenceCapture and override all of the settings on it. This class is currently # set as a config class so settings will leak between the Unreal Sequencer Render-to-Movie UI and this object. To work around # this, we set every setting via the script so that no changes the user has made via the UI will affect the script version. # The users UI settings will be reset as an unfortunate side effect of this. capture_settings = unreal.AutomatedLevelSequenceCapture() # Set all POD settings on the UMovieSceneCapture output_dir = unreal.SystemLibrary.get_project_directory( ) + "Saved/VideoCaptures/" capture_settings.settings.output_directory = unreal.DirectoryPath( output_dir) if not os.path.exists(output_dir): os.mkdir(output_dir) #capture_settings.settings.movie_extension = '.avi' # If you game mode is implemented in Blueprint, load_asset(...) is going to return you the C++ type ('Blueprint') and not what the BP says it inherits from. # Instead, because game_mode_override is a TSubclassOf<AGameModeBase> we can use unreal.load_class to get the UClass which is implicitly convertable. # ie: capture_settings.settings.game_mode_override = unreal.load_class(None, "/Game/AI/TestingSupport/AITestingGameMode.AITestingGameMode_C") editor_world_settings = unreal.EditorLevelLibrary.get_editor_world( ).get_world_settings() ''' game_mode_override is not working so change game_mode in world setting temporatily ''' print "# World Setting - Game Mode Input = " + game_mode_override print "# World Setting - Game Mode = " + str( editor_world_settings.default_game_mode) + " - type = " + str( type(editor_world_settings.default_game_mode)) if game_mode_override == 'None': unreal.EditorLevelLibrary.get_editor_world().get_world_settings( ).set_editor_property('default_game_mode', None) elif game_mode_override == 'BP_CameraGameMode': unreal.EditorLevelLibrary.get_editor_world().get_world_settings( ).set_editor_property( 'default_game_mode', unreal.load_class( None, '/VirtualCamera/Custom/BP_CameraGameMode.BP_CameraGameMode_C')) else: pass print "# World Setting - Game Mode Override = " + str( editor_world_settings.default_game_mode) + " - type = " + str( type(editor_world_settings.default_game_mode)) capture_settings.settings.game_mode_override = None #if game_mode_override=='BP_CameraGameMode': # capture_settings.settings.game_mode_override = None capture_settings.settings.output_format = output_file_name capture_settings.settings.overwrite_existing = False capture_settings.settings.use_relative_frame_numbers = False capture_settings.settings.handle_frames = 0 capture_settings.settings.zero_pad_frame_numbers = 4 # If you wish to override the output framerate you can use these two lines, otherwise the framerate will be derived from the sequence being rendered capture_settings.settings.use_custom_frame_rate = True capture_settings.settings.custom_frame_rate = unreal.FrameRate(24, 1) capture_settings.settings.resolution.res_x = resolution[0] capture_settings.settings.resolution.res_y = resolution[1] capture_settings.settings.enable_texture_streaming = False capture_settings.settings.cinematic_engine_scalability = True capture_settings.settings.cinematic_mode = True capture_settings.settings.allow_movement = False # Requires cinematic_mode = True capture_settings.settings.allow_turning = False # Requires cinematic_mode = True capture_settings.settings.show_player = False # Requires cinematic_mode = True capture_settings.settings.show_hud = False # Requires cinematic_mode = True capture_settings.use_separate_process = False capture_settings.close_editor_when_capture_starts = False # Requires use_separate_process = True capture_settings.additional_command_line_arguments = "-NOSCREENMESSAGES" # Requires use_separate_process = True capture_settings.inherited_command_line_arguments = "" # Requires use_separate_process = True # Set all the POD settings on UAutomatedLevelSequenceCapture capture_settings.use_custom_start_frame = False # If False, the system will automatically calculate the start based on sequence content capture_settings.use_custom_end_frame = False # If False, the system will automatically calculate the end based on sequence content capture_settings.custom_start_frame = unreal.FrameNumber( 0) # Requires use_custom_start_frame = True capture_settings.custom_end_frame = unreal.FrameNumber( 0) # Requires use_custom_end_frame = True capture_settings.warm_up_frame_count = warm_up_frame_count capture_settings.delay_before_warm_up = delay_before_warm_up capture_settings.delay_before_shot_warm_up = delay_before_shot_warm_up capture_settings.delay_every_frame = delay_every_frame capture_settings.write_edit_decision_list = True # Tell the capture settings which level sequence to render with these settings. The asset does not need to be loaded, # as we're only capturing the path to it and when the PIE instance is created it will load the specified asset. # If you only had a reference to the level sequence, you could use "unreal.SoftObjectPath(mysequence.get_path_name())" capture_settings.level_sequence_asset = unreal.SoftObjectPath( sequencer_asset_path) # To configure the video output we need to tell the capture settings which capture protocol to use. The various supported # capture protocols can be found by setting the Unreal Content Browser to "Engine C++ Classes" and filtering for "Protocol" # ie: CompositionGraphCaptureProtocol, ImageSequenceProtocol_PNG, etc. Do note that some of the listed protocols are not intended # to be used directly. # Right click on a Protocol and use "Copy Reference" and then remove the extra formatting around it. ie: # Class'/Script/MovieSceneCapture.ImageSequenceProtocol_PNG' gets transformed into "/Script/MovieSceneCapture.ImageSequenceProtocol_PNG" #capture_settings.set_image_capture_protocol_type(unreal.load_class(None, "/Script/MovieSceneCapture.VideoCaptureProtocol")) capture_settings.set_image_capture_protocol_type( unreal.load_class( None, "/Script/AppleProResMedia.AppleProResEncoderProtocol")) # After we have set the capture protocol to a soft class path we can start editing the settings for the instance of the protocol that is internallyc reated. #capture_settings.get_image_capture_protocol().compression_quality = 100 # The other complex settings is the burn-in. Create an instance of the LevelSequenceBurnInOptions which is used to # specify if we should use a burn in, and then which settings. burn_in_options = unreal.LevelSequenceBurnInOptions() #unreal.log('use_burn_in =' + str(use_burn_in)) burn_in_options.use_burn_in = use_burn_in #unreal.log('burn_in_options.use_burn_in =' + str(burn_in_options.use_burn_in)) # You have to specify a path to a class to use for the burn in (if use_burn_in = True), and this class specifies a UClass to define the # settings object type. We've created a convinence function which takes the class path, loads the class at that path and assigns it to # the Settings object. #burn_in_options.set_burn_in(unreal.SoftClassPath("/Engine/Sequencer/DefaultBurnIn.DefaultBurnIn_C")) burn_in_options.set_burn_in( unreal.SoftClassPath("/MofacRenderMovie/CustomBurnIn.CustomBurnIn_C")) # The default burn in is implemented entirely in Blueprint which means that the method we've been using to set properties will not # work for it. The python bindings that turn bSomeVariableName into "some_variable_name" only work for C++ classes with # UPROPERTY(BlueprintReadWrite) marked fields. Python doesn't know about the existence of Blueprint classes and their fields, so we # have to use an alternative method. burn_in_options.settings.set_editor_property( 'TopLeftText', "{FocalLength}mm,{Aperture},{FocusDistance}") burn_in_options.settings.set_editor_property( 'TopCenterText', "{MasterName} - {Date} - {EngineVersion} - " + proj_names) burn_in_options.settings.set_editor_property('TopRightText', artist_names) burn_in_options.settings.set_editor_property( 'BottomLeftText', "Level: " + level_name + "\nPath: " + level_path + "\n{ShotName}") burn_in_options.settings.set_editor_property( 'BottomCenterText', "{hh}:{mm}:{ss}:{ff} ({MasterFrame})") burn_in_options.settings.set_editor_property( 'BottomRightText', "{shh}:{smm}:{sss}:{sff} {SourceTimecode} {ShotFrame}") # Load a Texture2D asset and assign it to the UTexture2D reference that Watermark is. # burn_in_settings.set_editor_property('Watermark', None) # Note that this example creates a really obvious watermark (a big blurry green smiley face) just so that you know it's working! #burn_in_options.settings.set_editor_property('Watermark', unreal.load_asset("/Engine/EngineResources/AICON-Green")) #burn_in_options.settings.set_editor_property('WatermarkTint', unreal.LinearColor(1.0, 0.5, 0.5, 0.5)) # Create a FLinearColor to tint our Watermark # Assign our created instances to our original capture_settings object. capture_settings.burn_in_options = burn_in_options # Finally invoke Sequencer's Render to Movie functionality. This will examine the specified settings object and either construct a new PIE instance to render in, # or create and launch a new process (optionally shutting down your editor). #unreal.log(capture_settings.get_image_capture_protocol().get_editor_property('EncodingFormat')) ''' enum class EAppleProResEncoderFormats : uint8 { F_422HQ UMETA(DisplayName = "422 HQ"), F_422 UMETA(DisplayName = "422"), F_422LT UMETA(DisplayName = "422 LT"), F_422Proxy UMETA(DisplayName = "422 Proxy"), F_4444 UMETA(DisplayName = "4444"), F_4444XQ UMETA(DisplayName = "4444 XQ"), }; ''' TargetEncoderFormat = unreal.AppleProResEncoderFormats.F_422 #print type(TargetEncoderFormat) #print TargetEncoderFormat #print dir(type(TargetEncoderFormat)) if encorder_format == '422 HQ': TargetEncoderFormat = unreal.AppleProResEncoderFormats.F_422HQ elif encorder_format == '422': pass elif encorder_format == '422 LT': TargetEncoderFormat = unreal.AppleProResEncoderFormats.F_422LT elif encorder_format == '422 Proxy': TargetEncoderFormat = unreal.AppleProResEncoderFormats.F_422_PROXY elif encorder_format == '4444': TargetEncoderFormat = unreal.AppleProResEncoderFormats.F_4444 elif encorder_format == '4444 XQ': TargetEncoderFormat = unreal.AppleProResEncoderFormats.F_4444XQ capture_settings.get_image_capture_protocol().set_editor_property( 'EncodingFormat', TargetEncoderFormat) if args.use_audio_capture: capture_settings.set_audio_capture_protocol_type( unreal.load_class( None, "/Script/MovieSceneCapture.MasterAudioSubmixCaptureProtocol")) capture_settings.get_audio_capture_protocol().set_editor_property( 'FileName', output_file_name) #unreal.log(capture_settings.get_image_capture_protocol().get_editor_property('EncodingFormat')) #unreal.log(type(capture_settings.get_image_capture_protocol().get_editor_property('EncodingFormat'))) unreal.SequencerTools.render_movie(capture_settings, on_finished_callback)
def render_sequence_to_movie(sequencer_asset_path): # 1) Create an instance of our UAutomatedLevelSequenceCapture and override all of the settings on it. This class is currently # set as a config class so settings will leak between the Unreal Sequencer Render-to-Movie UI and this object. To work around # this, we set every setting via the script so that no changes the user has made via the UI will affect the script version. # The users UI settings will be reset as an unfortunate side effect of this. capture_settings = unreal.AutomatedLevelSequenceCapture() # Set all POD settings on the UMovieSceneCapture capture_settings.settings.output_directory = unreal.DirectoryPath( "../../../QAGame/Saved/VideoCaptures/") # If you game mode is implemented in Blueprint, load_asset(...) is going to return you the C++ type ('Blueprint') and not what the BP says it inherits from. # Instead, because game_mode_override is a TSubclassOf<AGameModeBase> we can use unreal.load_class to get the UClass which is implicitly convertable. # ie: capture_settings.settings.game_mode_override = unreal.load_class(None, "/Game/AI/TestingSupport/AITestingGameMode.AITestingGameMode_C") capture_settings.settings.game_mode_override = None capture_settings.settings.output_format = "{world}" capture_settings.settings.overwrite_existing = True capture_settings.settings.use_relative_frame_numbers = False capture_settings.settings.handle_frames = 0 capture_settings.settings.zero_pad_frame_numbers = 4 capture_settings.settings.frame_rate = unreal.FrameRate(24, 1) capture_settings.settings.resolution.res_x = 1280 capture_settings.settings.resolution.res_y = 720 capture_settings.settings.enable_texture_streaming = False capture_settings.settings.cinematic_engine_scalability = True capture_settings.settings.cinematic_mode = True capture_settings.settings.allow_movement = False # Requires cinematic_mode = True capture_settings.settings.allow_turning = False # Requires cinematic_mode = True capture_settings.settings.show_player = False # Requires cinematic_mode = True capture_settings.settings.show_hud = False # Requires cinematic_mode = True capture_settings.use_separate_process = False capture_settings.close_editor_when_capture_starts = False # Requires use_separate_process = True capture_settings.additional_command_line_arguments = "-NOSCREENMESSAGES" # Requires use_separate_process = True capture_settings.inherited_command_line_arguments = "" # Requires use_separate_process = True # Set all the POD settings on UAutomatedLevelSequenceCapture capture_settings.use_custom_start_frame = False # If False, the system will automatically calculate the start based on sequence content capture_settings.use_custom_end_frame = False # If False, the system will automatically calculate the end based on sequence content capture_settings.custom_start_frame = unreal.FrameNumber( 0) # Requires use_custom_start_frame = True capture_settings.custom_end_frame = unreal.FrameNumber( 0) # Requires use_custom_end_frame = True capture_settings.warm_up_frame_count = 0.0 capture_settings.delay_before_warm_up = 0 # ToDo: Test int -> float capture_settings.delay_before_shot_warm_up = 0.0 capture_settings.write_edit_decision_list = True # Tell the capture settings which level sequence to render with these settings. The asset does not need to be loaded, # as we're only capturing the path to it and when the PIE instance is created it will load the specified asset. # If you only had a reference to the level sequence, you could use "unreal.SoftObjectPath(mysequence.get_path_name())" capture_settings.level_sequence_asset = unreal.SoftObjectPath( sequencer_asset_path) # Now let's work on setting some more complex settings. The image capture is composed of two fields that need to correspond to each other. # The first field is the CaptureType ("Output Format" on the UI). This is how you specify if you want to output custom render passes, a video sequence, etc. # Then, once you decide on a capture type you also need to create an instance of the settings object specific to that capture type and assign it. # In this example, we will be using a Custom Render Passes output as it is the most complicated one to set up. # # The settings classes for each capture protocol can be found in the /Engine/Source/Runtime/MovieSceneCapture/Public/Protocols folder. # The identifier comes from MovieSceneCaptureModule.cpp ("CustomRenderPasses", "Video", "PNG", "JPG", "BMP") capture_settings.capture_type.identifier = "CustomRenderPasses" protocol_settings = unreal.CompositionGraphCaptureSettings() # The passes comes from BufferVisualizationData.cpp protocol_settings.include_render_passes.value.append("BaseColor") protocol_settings.include_render_passes.value.append("SceneDepth") protocol_settings.include_render_passes.value.append("Roughness") protocol_settings.capture_frames_in_hdr = False protocol_settings.hdr_compression_quality = 1 # Requires capture_frames_in_hdr = True, 0 means no compression, 1 means standard. protocol_settings.capture_gamut = unreal.HDRCaptureGamut.HCGM_REC709 # Requires capture_frames_in_hdr = True # protocol_settings.post_processing_material = unreal.SoftObjectPath("/Game/Path/To/Material") protocol_settings.post_processing_material = unreal.SoftObjectPath( "") # Soft Object Paths use an empty string for None. protocol_settings.disable_screen_percentage = True # The other complex settings is the burn-in. Create an instance of the LevelSequenceBurnInOptions which is used to # specify if we should use a burn in, and then which settings. burn_in_options = unreal.LevelSequenceBurnInOptions() burn_in_options.use_burn_in = True # You have to specify a path to a class to use for the burn in (if use_burn_in = True), and this class specifies a UClass to define the # settings object type. We've created a convinence function which takes the class path, loads the class at that path and assigns it to # the Settings object. burn_in_options.set_burn_in( unreal.SoftClassPath( "/Engine/Sequencer/DefaultBurnIn.DefaultBurnIn_C")) # The default burn in is implemented entirely in Blueprint which means that the method we've been using to set properties will not # work for it. The python bindings that turn bSomeVariableName into "some_variable_name" only work for C++ classes with # UPROPERTY(BlueprintReadWrite) marked fields. Python doesn't know about the existence of Blueprint classes and their fields, so we # have to use an alternative method. burn_in_options.settings.set_editor_property( 'TopLeftText', "{FocalLength}mm,{Aperture},{FocusDistance}") burn_in_options.settings.set_editor_property( 'TopCenterText', "{MasterName} - {Date} - {EngineVersion}") burn_in_options.settings.set_editor_property( 'TopRightText', "{TranslationX} {TranslationY} {TranslationZ}, {RotationX} {RotationY} {RotationZ}" ) burn_in_options.settings.set_editor_property('BottomLeftText', "{ShotName}") burn_in_options.settings.set_editor_property( 'BottomCenterText', "{hh}:{mm}:{ss}:{ff} ({MasterFrame})") burn_in_options.settings.set_editor_property('BottomRightText', "{ShotFrame}") # Load a Texture2D asset and assign it to the UTexture2D reference that Watermark is. # burn_in_settings.set_editor_property('Watermark', None) burn_in_options.settings.set_editor_property( 'Watermark', unreal.load_asset("/Engine/EngineResources/AICON-Green")) burn_in_options.settings.set_editor_property( 'WatermarkTint', unreal.LinearColor(1.0, 0.5, 0.5, 0.5)) # Create a FLinearColor to tint our Watermark # Assign our created instances to our original capture_settings object. capture_settings.burn_in_options = burn_in_options capture_settings.protocol_settings = protocol_settings # Finally invoke Sequencer's Render to Movie functionality. This will examine the specified settings object and either construct a new PIE instance to render in, # or create and launch a new process (optionally shutting down your editor). unreal.SequencerTools.render_movie(capture_settings)
def render_sequence_to_movie(sequence_path, sequence_name): def on_render_movie_finished(success): print( "Movie has finished rendering. Python can now invoke another movie render if needed. Sucess: " + str(success)) on_finished_callback = unreal.OnRenderMovieStopped() on_finished_callback.bind_callable(on_render_movie_finished) file_path = sequence_path + "/" + sequence_name capture_settings = unreal.AutomatedLevelSequenceCapture() # out put path capture_settings.settings.output_directory = unreal.DirectoryPath( "../../../Game/Saved/VideoCaptures/") capture_settings.settings.game_mode_override = None # out put name capture_settings.settings.output_format = sequence_name capture_settings.settings.overwrite_existing = False capture_settings.settings.use_relative_frame_numbers = False capture_settings.settings.handle_frames = 0 capture_settings.settings.zero_pad_frame_numbers = 4 capture_settings.settings.use_custom_frame_rate = True capture_settings.settings.custom_frame_rate = unreal.FrameRate(24, 1) capture_settings.settings.resolution.res_x = 1280 capture_settings.settings.resolution.res_y = 720 capture_settings.settings.enable_texture_streaming = False capture_settings.settings.cinematic_engine_scalability = True capture_settings.settings.cinematic_mode = True capture_settings.settings.allow_movement = False capture_settings.settings.allow_turning = False capture_settings.settings.show_player = False capture_settings.settings.show_hud = False capture_settings.use_separate_process = False capture_settings.close_editor_when_capture_starts = False capture_settings.additional_command_line_arguments = "-NOSCREENMESSAGES" capture_settings.inherited_command_line_arguments = "" capture_settings.use_custom_start_frame = False capture_settings.use_custom_end_frame = False capture_settings.custom_start_frame = unreal.FrameNumber(0) capture_settings.custom_end_frame = unreal.FrameNumber(0) capture_settings.warm_up_frame_count = 0.0 capture_settings.delay_before_warm_up = 0 capture_settings.delay_before_shot_warm_up = 0.0 capture_settings.write_edit_decision_list = True # Change format capture_settings.set_image_capture_protocol_type( unreal.load_class( None, "/Script/MovieSceneCapture.ImageSequenceProtocol_JPG")) capture_settings.get_image_capture_protocol().compression_quality = 100 capture_settings.level_sequence_asset = unreal.SoftObjectPath( file_path) unreal.SequencerTools.render_movie(capture_settings, on_finished_callback)
def AddSequencerSectionBoolKeysByIniFile(sequencer_section, track_dict): for key in track_dict.keys(): frame = float(key) / float(frameRateNumerator) # FrameRate value = track_dict[key] sequencer_section.get_channels()[0].add_key( unreal.FrameNumber(frame * float(frameRateNumerator)), value)
def render_sequence_to_movie(sequencer_asset_path): # 1) Create an instance of our UAutomatedLevelSequenceCapture and override all of the settings on it. This class is currently # set as a config class so settings will leak between the Unreal Sequencer Render-to-Movie UI and this object. To work around # this, we set every setting via the script so that no changes the user has made via the UI will affect the script version. # The users UI settings will be reset as an unfortunate side effect of this. capture_settings = unreal.AutomatedLevelSequenceCapture() # Set all POD settings on the UMovieSceneCapture capture_settings.settings.output_directory = unreal.DirectoryPath( "../../../QAGame/Saved/VideoCaptures/") # If you game mode is implemented in Blueprint, load_asset(...) is going to return you the C++ type ('Blueprint') and not what the BP says it inherits from. # Instead, because game_mode_override is a TSubclassOf<AGameModeBase> we can use unreal.load_class to get the UClass which is implicitly convertable. # ie: capture_settings.settings.game_mode_override = unreal.load_class(None, "/Game/AI/TestingSupport/AITestingGameMode.AITestingGameMode_C") capture_settings.settings.game_mode_override = None capture_settings.settings.output_format = "{world}" capture_settings.settings.overwrite_existing = True capture_settings.settings.use_relative_frame_numbers = False capture_settings.settings.handle_frames = 0 capture_settings.settings.zero_pad_frame_numbers = 4 # If you wish to override the output framerate you can use these two lines, otherwise the framerate will be derived from the sequence being rendered capture_settings.settings.use_custom_frame_rate = True capture_settings.settings.custom_frame_rate = unreal.FrameRate(24, 1) capture_settings.settings.resolution.res_x = 1280 capture_settings.settings.resolution.res_y = 720 capture_settings.settings.enable_texture_streaming = False capture_settings.settings.cinematic_engine_scalability = True capture_settings.settings.cinematic_mode = True capture_settings.settings.allow_movement = False # Requires cinematic_mode = True capture_settings.settings.allow_turning = False # Requires cinematic_mode = True capture_settings.settings.show_player = False # Requires cinematic_mode = True capture_settings.settings.show_hud = False # Requires cinematic_mode = True capture_settings.use_separate_process = False capture_settings.close_editor_when_capture_starts = False # Requires use_separate_process = True capture_settings.additional_command_line_arguments = "-NOSCREENMESSAGES" # Requires use_separate_process = True capture_settings.inherited_command_line_arguments = "" # Requires use_separate_process = True # Set all the POD settings on UAutomatedLevelSequenceCapture capture_settings.use_custom_start_frame = False # If False, the system will automatically calculate the start based on sequence content capture_settings.use_custom_end_frame = False # If False, the system will automatically calculate the end based on sequence content capture_settings.custom_start_frame = unreal.FrameNumber( 0) # Requires use_custom_start_frame = True capture_settings.custom_end_frame = unreal.FrameNumber( 0) # Requires use_custom_end_frame = True capture_settings.warm_up_frame_count = 0.0 capture_settings.delay_before_warm_up = 0 capture_settings.delay_before_shot_warm_up = 0.0 capture_settings.write_edit_decision_list = True # Tell the capture settings which level sequence to render with these settings. The asset does not need to be loaded, # as we're only capturing the path to it and when the PIE instance is created it will load the specified asset. # If you only had a reference to the level sequence, you could use "unreal.SoftObjectPath(mysequence.get_path_name())" capture_settings.level_sequence_asset = unreal.SoftObjectPath( sequencer_asset_path) # To configure the video output we need to tell the capture settings which capture protocol to use. The various supported # capture protocols can be found by setting the Unreal Content Browser to "Engine C++ Classes" and filtering for "Protocol" # ie: CompositionGraphCaptureProtocol, ImageSequenceProtocol_PNG, etc. Do note that some of the listed protocols are not intended # to be used directly. # Right click on a Protocol and use "Copy Reference" and then remove the extra formatting around it. ie: # Class'/Script/MovieSceneCapture.ImageSequenceProtocol_PNG' gets transformed into "/Script/MovieSceneCapture.ImageSequenceProtocol_PNG" capture_settings.set_image_capture_protocol_type( unreal.load_class( None, "/Script/MovieSceneCapture.ImageSequenceProtocol_PNG")) # After we have set the capture protocol to a soft class path we can start editing the settings for the instance of the protocol that is internallyc reated. capture_settings.get_image_capture_protocol().compression_quality = 100 # The other complex settings is the burn-in. Create an instance of the LevelSequenceBurnInOptions which is used to # specify if we should use a burn in, and then which settings. burn_in_options = unreal.LevelSequenceBurnInOptions() burn_in_options.use_burn_in = True # You have to specify a path to a class to use for the burn in (if use_burn_in = True), and this class specifies a UClass to define the # settings object type. We've created a convinence function which takes the class path, loads the class at that path and assigns it to # the Settings object. burn_in_options.set_burn_in( unreal.SoftClassPath( "/Engine/Sequencer/DefaultBurnIn.DefaultBurnIn_C")) # The default burn in is implemented entirely in Blueprint which means that the method we've been using to set properties will not # work for it. The python bindings that turn bSomeVariableName into "some_variable_name" only work for C++ classes with # UPROPERTY(BlueprintReadWrite) marked fields. Python doesn't know about the existence of Blueprint classes and their fields, so we # have to use an alternative method. burn_in_options.settings.set_editor_property( 'TopLeftText', "{FocalLength}mm,{Aperture},{FocusDistance}") burn_in_options.settings.set_editor_property( 'TopCenterText', "{MasterName} - {Date} - {EngineVersion}") burn_in_options.settings.set_editor_property( 'TopRightText', "{TranslationX} {TranslationY} {TranslationZ}, {RotationX} {RotationY} {RotationZ}" ) burn_in_options.settings.set_editor_property('BottomLeftText', "{ShotName}") burn_in_options.settings.set_editor_property( 'BottomCenterText', "{hh}:{mm}:{ss}:{ff} ({MasterFrame})") burn_in_options.settings.set_editor_property('BottomRightText', "{ShotFrame}") # Load a Texture2D asset and assign it to the UTexture2D reference that Watermark is. # burn_in_settings.set_editor_property('Watermark', None) # Note that this example creates a really obvious watermark (a big blurry green smiley face) just so that you know it's working! burn_in_options.settings.set_editor_property( 'Watermark', unreal.load_asset("/Engine/EngineResources/AICON-Green")) burn_in_options.settings.set_editor_property( 'WatermarkTint', unreal.LinearColor(1.0, 0.5, 0.5, 0.5)) # Create a FLinearColor to tint our Watermark # Assign our created instances to our original capture_settings object. capture_settings.burn_in_options = burn_in_options # Finally invoke Sequencer's Render to Movie functionality. This will examine the specified settings object and either construct a new PIE instance to render in, # or create and launch a new process (optionally shutting down your editor). unreal.SequencerTools.render_movie(capture_settings, on_finished_callback)