How to turn off visual display in Gym environments while keeping video recording functionality?

I’m working with different Gym environments and noticed some inconsistent behavior with video handling. In Atari games, when I wrap them with the Monitor class, the visual display stays hidden by default but the video still gets saved to my hard drive, which is exactly what I want.

But when I switch to other environments like CartPole-v0, Pendulum-v0, or MountainCarContinuous-v0, they automatically show the rendering window on screen. I need to find a way to hide this visual output while keeping the video recording feature working.

I’m working on a remote server setup and the usual xvfb solution doesn’t work for me. Many people seem to have issues with xvfb conflicting with nvidia graphics drivers. The typical fix involves reinstalling nvidia drivers, but I don’t have admin privileges on this server so that’s not an option for me.

Is there another approach to disable the visual rendering while maintaining the video capture functionality?

I fixed this with a virtual framebuffer that skips xvfb entirely. Build a custom rendering wrapper that catches the environment’s rendering calls and sends them to an in-memory buffer instead. Use pyvirtualdisplay with Display class and set visible=False - this spins up a virtual X server that grabs rendering output without popping up windows. Just make sure you initialize the virtual display before importing your gym environments. This works great with mixed environment types since it handles rendering at the display level instead of tweaking each environment separately. I’ve run this on servers where I couldn’t touch system graphics settings and it worked perfectly.

Another trick that worked for me - create the env with gym.make(env_name, render_mode=None) first, then wrap it with Monitor. Some environments respect the None parameter and skip window creation entirely. If that doesn’t work, you can patch pygame’s display.set_mode function to do nothing before loading the environment. It’s hacky but works for pygame-based envs when you don’t have admin access.

I ran into the same issue with headless setups. Each Gym environment handles rendering differently - Atari vs classic control environments work completely differently. Here’s what worked for me: Set render_mode to ‘rgb_array’ when you create the environment. This captures frames without showing them on screen. If some environments still give you trouble, set the DISPLAY variable to something fake like os.environ[‘DISPLAY’] = ‘:99’ before importing gym. I also had good luck using gym.make() with custom render settings. Some environments accept a --disable-rendering flag too, which makes everything run much smoother.

The problem is how Monitor wraps the environment’s step function vs render calls. Don’t try suppressing rendering after - intercept it at the wrapper level instead. Make a custom wrapper that inherits from gym.Wrapper and override both render() and step() to control frame capture. In step(), manually call env.render(mode=‘rgb_array’) to grab frame data for Monitor without showing the visual display. This gives you complete control over frame capture while totally bypassing the automatic rendering in classic control environments. Works reliably across different environment types without needing system hacks.

Had the same exact headache! The difference is Atari environments don’t auto-call render() internally, but classic control ones like CartPole do. I fixed it by overriding the render method after wrapping with Monitor. Just monkey-patch the environment’s render method to return None or pass - stops the window from popping up but doesn’t mess with Monitor’s frame capturing. You can also set the environment’s metadata render_modes to exclude ‘human’ mode entirely. Forces it to fall back to rgb_array mode even when it tries to render visually. Way cleaner than messing with display variables and no system-level changes needed.