Headless Renders with OpenUSD
OpenUSD offers a headless rendering script. Let's play around with it and see if we can remove a Qt dependency!

Getting headless renders is actually pretty easy once you have a working USD install.
If you've got all the dependencies and you can render with usdview
, you can run the usdrecord
script to get a rendered image. It's located in the bin
directory of your USD install if it was built with rendering support. I'll use the Kitchen_set example asset since it's easy to come by.
usdrecord Kitchen_set/Kitchen_set.usd kitchen.png
You should get an output image like this:

Nice and easy! usdrecord
has command line parameters to choose which frames to render, which camera to use, and lots of other things. Run usdrecord -h
to get a list.
That was too easy. Let's try something harder 😈
Removing the Qt Dependency
Recently I wanted to get headless renders in a docker container, and I wanted to keep the docker image size small. I found that the Qt libraries were contributing hundreds of megabytes to the image size. Since I wanted headless renders I thought I could get by without them.
When I removed Qt from the image I found that usdrecord
would fail with an error like
Traceback (most recent call last):
File "/opt/USD/bin/usdrecord", line 45, in _SetupOpenGLContext
from PySide6.QtOpenGLWidgets import QOpenGLWidget
ModuleNotFoundError: No module named 'PySide6'
It turns out usdrecord
uses Qt to create a window handle and manage the OpenGL context it needs for rendering. If you don't need to do an OpenGL render you don't need to do this, but I wanted the kind of OpenGL preview renders you get from usdview
, so I wanted to make OpenGL work.
The glfw library can set up window handles and give you an OpenGL context. It's much lighter weight than Qt and has python bindings. The error above references a function called _SetupOpenGLContext. I removed all the Qt related imports from usdrecord
and replaced that function with the version below. Then, after I ran pip install glfw
, I could run usdrecord
without Qt.
def _SetupOpenGLContext(width=100, height=100):
import glfw
glfw.init()
glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
window = glfw.create_window(width, height, "offscreen buffer", None, None)
if not window:
glfw.terminate()
return None
glfw.make_context_current(window)
return window
Once I knew that worked I wrote up a new render launching script that doesn't use Qt. You can see the script I wound up using on github here.
My Docker Build
If you'd like to use that docker image to get usdrecord
like renders, feel free. The image is called rstelzleni/usd-alpine
on dockerhub. The gl-24.05
version has OpenGL support and is about a 140MB download. If your Kitchen_set (or other USD content) is in the current directory you can run it like below and get the output png file back in the current directory.
docker run --rm -v.:/data rstelzleni/usd-alpine:gl-24.05 /data/Kitchen_set/Kitchen_set.usd /data/kitchen.png