Hi, I’m running a script from powershell trying to render a usd file using a specific camera to file. How can I do it headlessly?
- I’m using CaptureExtension for that and I’ve encountered an issue when trying to start the render because there’s no viewport to speak of since the script doesn’t launch USD Composer with all the UI. It stops on self._capture_instance.start():
import carb
import asyncio
import carb.settings
from pathlib import Path
import omni.usd
from pxr import Usd, UsdGeom
from omni.kit.capture.viewport import CaptureExtension
from omni.kit.capture.viewport.capture_options import CaptureOptions
class HeadlessRenderer:
def __init__(self) -> None:
self.task = None
self._capture_instance = CaptureExtension.get_instance()
self._options = CaptureOptions()
self._settings = carb.settings.get_settings()
self.stage = Usd.Stage.Open(self._settings.get("/stageToOpen"))
self._CameraList = [x for x in self.stage.Traverse() if x.IsA(UsdGeom.Camera)]
self._is_frame_rendered = False
self._isRendering = False
def OnRenderFinished(self):
self._isRendering = False
async def _single_render(self):
SECONDS_TO_WAIT = 5
SECONDS_EACH_TIME = 1
self._options.camera = self._CameraList[0].GetPath()
self._options.file_type = ".png"
self._options.path_trace_spp = 16
self._options.ptmb_subframes_per_frame = 1
self._options.file_name = "TEST"
self._options.output_folder = "C:\\Projects\\Renders"
self._options.res_height = 1080
self._options.res_width = 1920
self._options.render_product = ''
path = self._options.output_folder + "/" + self._options.file_name
self._capture_instance.options = self._options
self._capture_instance.capture_finished_fn = self.OnRenderFinished
self._capture_instance._frame_path = str(Path(path))
'''I've tried creating an instance of a viewport but it doesn't work as such'''
# viewport_interface = omni.kit.viewport.get_viewport_interface()
# viewport_handle = viewport_interface.create_instance()
# viewport = viewport_interface.get_viewport_window(viewport_handle)
# viewport.set_active_camera(self._CameraList[0].GetPath())
await omni.kit.app.get_app().next_update_async()
carb.log_error("________________1")
'''the script stops at this: '''
self._capture_instance.start()
carb.log_error("________________2")
self._capture_instance._frame_pattern_prefix = str(Path(path))
while seconds_tried < SECONDS_TO_WAIT:
await asyncio.sleep(SECONDS_EACH_TIME)
seconds_tried += SECONDS_EACH_TIME
return True
def Render(self):
loop = asyncio.get_event_loop()
self.task = loop.create_task(
self._single_render())
renderer = HeadlessRenderer()
renderer.Render()
So this is all it prints:
- I’ve tried using omni.kit.renderer.capture to circumvent having to access viewport, but it seems it still needs it, and thus the script stops on viewport_ldr_rp as well in that case:
import omni.kit.renderer.capture
render_capture = omni.renderer_capture.acquire_renderer_capture_interface()
viewport_ldr_rp = omni.kit.viewport.get_viewport_interface().get_viewport_window(None).get_drawable_ldr_resource()