def create_level(self): self.ass_lev = unreal.AssetToolsHelpers.get_asset_tools().create_asset( asset_name=self.ass_lev_name, package_path=self.ass_lev_path, asset_class=unreal.World, factory=unreal.WorldFactory()) self.ass = unreal.AssetToolsHelpers.get_asset_tools().create_asset( asset_name=self.ass_name, package_path=self.ass_path, asset_class=unreal.LevelSequence, factory=unreal.LevelSequenceFactoryNew()) self.ass.set_display_rate(unreal.FrameRate(self.fps, 1)) # 设置关卡序列的开始帧 self.ass.make_range(self.start, self.end) self.ass.set_playback_start(self.start) self.ass.set_playback_end(self.end) self.ass.set_work_range_start(self.start / self.fps) self.ass.set_work_range_end(self.end / self.fps) self.ass.set_view_range_start(self.start / self.fps) self.ass.set_view_range_end(self.end / self.fps) # 添加摄像机关卡 unreal.EditorLevelLibrary().load_level("{path}{name}.{name}".format( path=self.ass_lev_path, name=self.ass_lev_name)) # 打开创建的关卡
def read_config(self, text=True): self.ini_file = self.Config_LE.text() if not os.path.exists(self.ini_file): toast(u"配置路径不存在") self.Config_LE.setText("") return # print(self.ini_file) self.config = ConfigParser() if six.PY2 else ConfigParser(strict=False) self.config.read(self.ini_file) section = "MovieSceneCaptureUIInstance AutomatedLevelSequenceCapture" option = "Settings" try: capture_settings = self.config.get(section, option) except: return capture_settings_dict = self.json_config[section][option] capture_settings = capture_settings[1:-1] pattern = re.compile("\((.+?)\)") value_list = [] for i, match in enumerate(pattern.findall(capture_settings)): capture_settings = capture_settings.replace(match, "$$%s$$" % i) value_list.append(match) # NOTE 设置 for pair in capture_settings.split(","): k, v = pair.split("=") v = value_list[int(v[3])] if v.startswith("($$") else v k = capture_settings_dict.get(k) if not k: continue elif k == "output_directory": self.Output_LE.setText(v[6:-1].replace("\\\\", "\\")) if text else None elif text and k == "output_format": self.FileName_LE.setText(v[1:-1]) if text else None elif k == "game_mode_override": if v == "None": continue v = v.split('"')[1] v = unreal.load_class(None, v) self.capture_settings.set_editor_property(k, v) elif k == "custom_frame_rate": numerator, denominator = v.split(",") numerator = numerator.split("=")[1] denominator = denominator.split("=")[1] v = unreal.FrameRate(int(numerator), int(denominator)) self.capture_settings.set_editor_property(k, v) elif k == "resolution": x, y = v.split(",") x = x.split("=")[1] y = y.split("=")[1] v = unreal.CaptureResolution(int(x), int(y)) self.capture_settings.set_editor_property(k, v) else: v = ast.literal_eval(v) self.capture_settings.set_editor_property(k, v)
def CreateSequencer(): import unreal import os.path import sys import time import json ''' if int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 26: import configparser as ConfigParser else: import ConfigParser ''' # Prepare process import json_data_file = 'ImportSequencerData.json' dir_path = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(dir_path, json_data_file), "r") as json_file: sequence_data = json.load(json_file) spawnable_camera = sequence_data['spawnable_camera'] startFrame = sequence_data['startFrame'] endFrame = sequence_data['endFrame'] + 1 render_resolution_x = sequence_data['render_resolution_x'] render_resolution_y = sequence_data['render_resolution_y'] frameRateDenominator = sequence_data['frameRateDenominator'] frameRateNumerator = sequence_data['frameRateNumerator'] secureCrop = sequence_data[ 'secureCrop'] # add end crop for avoid section overlay unreal_import_location = sequence_data['unreal_import_location'] ImportedCamera = [] # (CameraName, CameraGuid) def AddSequencerSectionTransformKeysByIniFile(sequencer_section, track_dict): for key in track_dict.keys(): value = track_dict[key] # (x,y,z x,y,z x,y,z) frame = unreal.FrameNumber(int(key)) 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 AddSequencerSectionFloatKeysByIniFile(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 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) print("Warning this file already exists") # ??? factory = unreal.LevelSequenceFactoryNew() asset_tools = unreal.AssetToolsHelpers.get_asset_tools() seq = asset_tools.create_asset_with_dialog('MySequence', '/Game', None, factory) if seq is None: return 'ERROR: level sequencer factory_create fail' print("Sequencer reference created") print(seq) # Process import print( "========================= Import started ! =========================") # Set frame rate myFFrameRate = unreal.FrameRate() myFFrameRate.denominator = frameRateDenominator myFFrameRate.numerator = frameRateNumerator seq.set_display_rate(myFFrameRate) # Set playback range seq.set_playback_end_seconds( (endFrame - secureCrop) / float(frameRateNumerator)) seq.set_playback_start_seconds( startFrame / float(frameRateNumerator)) # set_playback_end_seconds camera_cut_track = seq.add_master_track(unreal.MovieSceneCameraCutTrack) camera_cut_track.set_editor_property('display_name', 'Imported Camera Cuts') if int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 26: camera_cut_track.set_color_tint(unreal.Color(b=200, g=0, r=0, a=0)) else: pass for x, camera_data in enumerate(sequence_data["cameras"]): # import camera print("Start camera import " + str(x + 1) + "/" + str(len(sequence_data["cameras"])) + " :" + camera_data["name"]) # Import camera tracks transform with open(camera_data["additional_tracks_path"], "r") as json_file: camera_tracks = json.load(json_file) # Create spawnable camera and add camera in sequencer cine_camera_actor = unreal.EditorLevelLibrary().spawn_actor_from_class( unreal.CineCameraActor, unreal.Vector(0, 0, 0), unreal.Rotator(0, 0, 0)) # Import additional tracks (camera_component) camera_component_binding = seq.add_possessable( cine_camera_actor.get_cine_camera_component()) # Get the last TrackFocalLength = camera_component_binding.add_track( unreal.MovieSceneFloatTrack) TrackFocalLength.set_property_name_and_path('CurrentFocalLength', 'CurrentFocalLength') TrackFocalLength.set_editor_property('display_name', 'Current Focal Length') sectionFocalLength = TrackFocalLength.add_section() sectionFocalLength.set_end_frame_bounded(False) sectionFocalLength.set_start_frame_bounded(False) AddSequencerSectionFloatKeysByIniFile( sectionFocalLength, camera_tracks['Camera FocalLength']) TrackSensorWidth = camera_component_binding.add_track( unreal.MovieSceneFloatTrack) TrackSensorWidth.set_property_name_and_path('Filmback.SensorWidth', 'Filmback.SensorWidth') TrackSensorWidth.set_editor_property('display_name', 'Sensor Width (Filmback)') sectionSensorWidth = TrackSensorWidth.add_section() sectionSensorWidth.set_end_frame_bounded(False) sectionSensorWidth.set_start_frame_bounded(False) AddSequencerSectionFloatKeysByIniFile( sectionSensorWidth, camera_tracks['Camera SensorWidth']) TrackSensorHeight = camera_component_binding.add_track( unreal.MovieSceneFloatTrack) TrackSensorHeight.set_property_name_and_path('Filmback.SensorHeight', 'Filmback.SensorHeight') TrackSensorHeight.set_editor_property('display_name', 'Sensor Height (Filmback)') sectionSensorHeight = TrackSensorHeight.add_section() sectionSensorHeight.set_end_frame_bounded(False) sectionSensorHeight.set_start_frame_bounded(False) crop_camera_sensor_height = {} for key in camera_tracks['Camera SensorHeight'].keys(): original_width = float(camera_tracks['Camera SensorWidth'][key]) original_height = float(camera_tracks['Camera SensorHeight'][key]) res_x = float(sequence_data['render_resolution_x']) res_y = float(sequence_data['render_resolution_y']) pixel_x = float(sequence_data['pixel_aspect_x']) pixel_y = float(sequence_data['pixel_aspect_y']) res_ratio = res_x / res_y pixel_ratio = pixel_x / pixel_y crop_camera_sensor_height[key] = (original_width / (res_ratio * pixel_ratio)) AddSequencerSectionFloatKeysByIniFile(sectionSensorHeight, crop_camera_sensor_height) TrackFocusDistance = camera_component_binding.add_track( unreal.MovieSceneFloatTrack) # Wtf this var name change every version or I do someting wrong??? :v if int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 26: TrackFocusDistance.set_property_name_and_path( 'FocusSettings.ManualFocusDistance', 'FocusSettings.ManualFocusDistance') TrackFocusDistance.set_editor_property( 'display_name', 'Manual Focus Distance (Focus Settings)') elif int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 25: TrackFocusDistance.set_property_name_and_path( 'FocusSettings.ManualFocusDistance', 'FocusSettings.ManualFocusDistance') TrackFocusDistance.set_editor_property( 'display_name', 'Manual Focus Distance (Focus Settings)') elif int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 24: TrackFocusDistance.set_property_name_and_path( 'CurrentFocusDistance', 'CurrentFocusDistance') TrackFocusDistance.set_editor_property('display_name', 'Current Focus Distance') else: TrackFocusDistance.set_property_name_and_path( 'ManualFocusDistance', 'ManualFocusDistance') TrackFocusDistance.set_editor_property('display_name', 'Current Focus Distance') sectionFocusDistance = TrackFocusDistance.add_section() sectionFocusDistance.set_end_frame_bounded(False) sectionFocusDistance.set_start_frame_bounded(False) AddSequencerSectionFloatKeysByIniFile( sectionFocusDistance, camera_tracks['Camera FocusDistance']) TracknAperture = camera_component_binding.add_track( unreal.MovieSceneFloatTrack) TracknAperture.set_property_name_and_path('CurrentAperture', 'CurrentAperture') TracknAperture.set_editor_property('display_name', 'Current Aperture') sectionAperture = TracknAperture.add_section() sectionAperture.set_end_frame_bounded(False) sectionAperture.set_start_frame_bounded(False) AddSequencerSectionFloatKeysByIniFile(sectionAperture, camera_tracks['Camera Aperture']) # add a binding for the camera camera_binding = seq.add_possessable(cine_camera_actor) if spawnable_camera: # Transfer to spawnable camera camera_spawnable = seq.add_spawnable_from_class( unreal.CineCameraActor) # Add camera in sequencer camera_component_binding.set_parent(camera_spawnable) # Import transform tracks if spawnable_camera: transform_track = camera_spawnable.add_track( unreal.MovieScene3DTransformTrack) else: transform_track = camera_binding.add_track( unreal.MovieScene3DTransformTrack) transform_section = transform_track.add_section() transform_section.set_end_frame_bounded(False) transform_section.set_start_frame_bounded(False) AddSequencerSectionTransformKeysByIniFile( transform_section, camera_tracks['Camera transform']) # Set property binding if spawnable_camera: current_camera_binding = camera_spawnable else: current_camera_binding = camera_binding if int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 26: current_camera_binding.set_display_name(camera_data["name"]) else: pass tracksSpawned = current_camera_binding.find_tracks_by_exact_type( unreal.MovieSceneSpawnTrack) if len(tracksSpawned) > 0: sectionSpawned = tracksSpawned[0].get_sections()[0] AddSequencerSectionBoolKeysByIniFile( sectionSpawned, camera_tracks['Camera Spawned']) # Set property actor if spawnable_camera: current_cine_camera_actor = camera_spawnable.get_object_template() else: current_cine_camera_actor = cine_camera_actor current_cine_camera_actor.set_actor_label(camera_data["name"]) camera_component = cine_camera_actor.camera_component camera_component.aspect_ratio = render_resolution_x / render_resolution_y camera_component.lens_settings.min_f_stop = 0 camera_component.lens_settings.max_f_stop = 1000 # Clean the created assets if spawnable_camera: cine_camera_actor.destroy_actor() camera_binding.remove() if spawnable_camera: ImportedCamera.append((camera_data["name"], camera_spawnable)) else: ImportedCamera.append((camera_data["name"], camera_binding)) # Import camera cut section for section in sequence_data['marker_sections']: camera_cut_section = camera_cut_track.add_section() if section["has_camera"] is not None: for camera in ImportedCamera: if camera[0] == section["camera_name"]: camera_binding_id = unreal.MovieSceneObjectBindingID() camera_binding_id = seq.make_binding_id( camera[1], unreal.MovieSceneObjectBindingSpace.LOCAL) camera_cut_section.set_camera_binding_id(camera_binding_id) camera_cut_section.set_end_frame_seconds( (section["end_time"] - secureCrop) / float(frameRateNumerator)) camera_cut_section.set_start_frame_seconds(section["start_time"] / float(frameRateNumerator)) # Import result print( '========================= Imports completed ! =========================' ) ImportedCameraStr = [] for cam in ImportedCamera: ImportedCameraStr.append(cam[0]) print(ImportedCameraStr) print('=========================') # Select and open seq in content browser if int(unreal.SystemLibrary.get_engine_version()[:4][2:]) >= 26: unreal.AssetEditorSubsystem.open_editor_for_assets( unreal.AssetEditorSubsystem(), [unreal.load_asset(seq.get_path_name())]) else: unreal.AssetToolsHelpers.get_asset_tools().open_editor_for_assets( [unreal.load_asset(seq.get_path_name())]) unreal.EditorAssetLibrary.sync_browser_to_objects([seq.get_path_name()]) return 'Sequencer created with success !'
def render(sequence_list, i, output_directory="C:/render", output_format="{sequence}"): # NOTE 如果超出数组则退出执行 if i >= len(sequence_list): # NOTE 输出完成 打开输出文件夹的路径 os.startfile(output_directory) return # NOTE 获取当前渲染序号下的 LevelSequence sequence = sequence_list[i] # NOTE 配置渲染参数 settings = unreal.MovieSceneCaptureSettings() path = unreal.DirectoryPath(output_directory) settings.set_editor_property("output_directory", path) settings.set_editor_property("output_format", output_format) settings.set_editor_property("overwrite_existing", True) settings.set_editor_property("game_mode_override", None) settings.set_editor_property("use_relative_frame_numbers", False) settings.set_editor_property("handle_frames", 0) settings.set_editor_property("zero_pad_frame_numbers", 4) settings.set_editor_property("use_custom_frame_rate", True) settings.set_editor_property("custom_frame_rate", unreal.FrameRate(24, 1)) # NOTE 渲染大小 w, h = 1280, 720 settings.set_editor_property("resolution", unreal.CaptureResolution(w, h)) settings.set_editor_property("enable_texture_streaming", False) settings.set_editor_property("cinematic_engine_scalability", True) settings.set_editor_property("cinematic_mode", True) settings.set_editor_property("allow_movement", False) settings.set_editor_property("allow_turning", False) settings.set_editor_property("show_player", False) settings.set_editor_property("show_hud", False) # NOTE 设置默认的自动渲染参数 option = unreal.AutomatedLevelSequenceCapture() option.set_editor_property("use_separate_process", False) option.set_editor_property("close_editor_when_capture_starts", False) option.set_editor_property("additional_command_line_arguments", "-NOSCREENMESSAGES") option.set_editor_property("inherited_command_line_arguments", "") option.set_editor_property("use_custom_start_frame", False) option.set_editor_property("use_custom_end_frame", False) option.set_editor_property("warm_up_frame_count", 0.0) option.set_editor_property("delay_before_warm_up", 0) option.set_editor_property("delay_before_shot_warm_up", 0.0) option.set_editor_property("write_edit_decision_list", True) # option.set_editor_property("custom_start_frame",unreal.FrameNumber(0)) # option.set_editor_property("custom_end_frame",unreal.FrameNumber(0)) option.set_editor_property("settings", settings) option.set_editor_property("level_sequence_asset", unreal.SoftObjectPath(sequence.get_path_name())) # NOTE 设置自定义渲染参数 option.set_image_capture_protocol_type( unreal.CompositionGraphCaptureProtocol) protocol = option.get_image_capture_protocol() # NOTE 这里设置 Base Color 渲染 Base Color 通道,可以根据输出的 UI 设置数组名称 passes = unreal.CompositionGraphCapturePasses(["Base Color"]) protocol.set_editor_property("include_render_passes", passes) # protocol.set_editor_property("compression_quality",100) # NOTE 设置全局变量才起作用! global on_finished_callback on_finished_callback = unreal.OnRenderMovieStopped(lambda s: render( sequence_list, i + 1, output_directory, output_format)) unreal.SequencerTools.render_movie(option, on_finished_callback)
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 CreateSequencer(): import os.path import time import ConfigParser import unreal seqPath = r"/Game/ImportedFbx/Sequencer" seqName = r'MySequence' seqTempName = r'MySequence'+str(time.time()) startFrame = 1 endFrame = 251 frameRateDenominator = 1.0 frameRateNumerator = 25 secureCrop = 0.0001 #add end crop for avoid section overlay 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 AddSequencerSectionFloatKeysByIniFile(SequencerSection, SectionFileName, FileLoc): Config = ConfigParser.ConfigParser() Config.read(FileLoc) for option in Config.options(SectionFileName): frame = float(option)/float(frameRateNumerator) #FrameRate value = float(Config.get(SectionFileName, option)) SequencerSection.get_channels()[0].add_key(unreal.FrameNumber(frame*float(frameRateNumerator)),value) 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) print("Warning this file already exists") factory = unreal.LevelSequenceFactoryNew() asset_tools = unreal.AssetToolsHelpers.get_asset_tools() seq = asset_tools.create_asset_with_dialog(seqName.replace('.',''), seqPath, None, factory) if seq is None: return 'Error /!\ level sequencer factory_create fail' print("Sequencer reference created") print(seq) ImportedCamera = [] #(CameraName, CameraGuid) print("========================= Import started ! =========================") #Set frame rate myFFrameRate = unreal.FrameRate() myFFrameRate.denominator = frameRateDenominator myFFrameRate.numerator = frameRateNumerator seq.set_display_rate(myFFrameRate) #Set playback range seq.set_playback_end_seconds((endFrame-secureCrop)/float(frameRateNumerator)) seq.set_playback_start_seconds(startFrame/float(frameRateNumerator)) camera_cut_track = seq.add_master_track(unreal.MovieSceneCameraCutTrack) #Import camera cut section camera_cut_section = camera_cut_track.add_section() #Not camera found for this section camera_cut_section.set_end_frame_seconds((251-secureCrop)/float(frameRateNumerator)) camera_cut_section.set_start_frame_seconds(1/float(frameRateNumerator)) print('========================= Imports completed ! =========================') for cam in ImportedCamera: print(cam[0]) print('=========================') #Select and open seq in content browser unreal.AssetToolsHelpers.get_asset_tools().open_editor_for_assets([unreal.load_asset(seqPath+'/'+seqName.replace('.',''))]) unreal.EditorAssetLibrary.sync_browser_to_objects([seqPath+'/'+seqName.replace('.','')]) return 'Sequencer created with success !'
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 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)