Skip to content

Headless Rendering

Panopti offers headless rendering, which works even in remote work setups. Panopti uses Playwright's headless Chromium shell to achieve headless rendering -- in general, all of Panopti's functionality is compatible with this rendering mode.

Installation

To use Panopti's headless renderer, you first need to install Playwright along with its headless Chromium shell:

pip install playwright
# Now install headless chromium shell:
python -m playwright install chromium

Enabling headless rendering

Simply specify the optional argument headless=True in panopti.connect(...). That's it! Note that you still need to run a Panopti server for headless rendering.

Example:

import panopti
import trimesh
import numpy as np

# Use `headless=True` here!
viewer = panopti.connect(server_url="http://localhost:8080", 
                         viewer_id="client", 
                         headless=True)

# Add a sphere to the scene:
sphere = trimesh.creation.icosphere(subdivisions=4)
verts, faces = sphere.vertices, sphere.faces

mesh = viewer.add_mesh(
    name="Sphere",
    vertices=verts,
    faces=faces,
)

# Animate the mesh in a circular path and capture frames
frames = []
for i in range(360):
    angle = np.radians(i)
    position = np.array([np.cos(angle), np.sin(angle), 0])

    # Update mesh position
    mesh.update(position=position)

    # Capture frame at custom resolution
    frame = viewer.screenshot(
        filename=f"./frames/frame_{i:03d}.png",
        bg_color=(0.05, 0.05, 0.05),
        resolution=(1080, 512)
    )
    frames.append(frame)

# Do something with frames here: ...

Tips

Headless screenshot resolution

Headless screenshot resolution

By default, the Chromium headless window runs at 1280x720 resolution, and hence screenshots will be taken with respect to this resolution. It's suggested to manually specify screenshot resolution as needed, like in the example above.

Running on clusters

Running on clusters

To do headless rendering on a cluster (e.g. SLURM), where you submit jobs as batch scripts, you can use this quick recipe:

# job.sh    
# ... Load virtual environment, etc...

# Launch server with trailing `&` to fork process:
python -m panopti.run_server --host localhost --port 8080 &

# Run your experiment:
python your_script.py

Now the Panopti server will run asychronously in a separate process, and in your_script.py you can enable headless mode, just as we did above:

import panopti
viewer = panopti.connect(server_url="http://localhost:8080", 
                         viewer_id="client", 
                         headless=True)
...

See also: Screenshots, Camera, Remote SSH