Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_moderngl.Error: the program belongs to a different context #64

Open
yhiroya2000 opened this issue Sep 12, 2024 · 3 comments
Open

_moderngl.Error: the program belongs to a different context #64

yhiroya2000 opened this issue Sep 12, 2024 · 3 comments

Comments

@yhiroya2000
Copy link

yhiroya2000 commented Sep 12, 2024

Hi, I want to save all videos in the directory.

When I tried to save videos by using HeadlessRenderer(), " _moderngl.Error: the program belongs to a different context " happened.

The first video is saved perfectly, but this error happened on the second video.

What should I do?

Here is the detail of the error code.

name@Unknown:~/研究/code$ python3 amass_save_all.py
Processing: npz_path=../data/amass/ACCAD/Male1Walking_c3d/Walk B15 - Walk turn around_poses.npz, output_path=../export/headless/Walk B15 - Walk turn around_poses.mp4
Processing file: ../data/amass/ACCAD/Male1Walking_c3d/Walk B15 - Walk turn around_poses.npz
WARNING: You are using a SMPL+H model, with only 16 shape coefficients.
num_betas=10, shapedirs.shape=(6890, 3, 16), self.SHAPE_SPACE_DIM=300
Data keys available: ['trans', 'gender', 'mocap_framerate', 'betas', 'dmpls', 'poses']
  1367 poses of size  156.
  1367 trans of size    3.
     1 shape of size   16.
Gender male
FPS 120.0
Rendering frames: 100%|███████████████████████| 684/684 [00:44<00:00, 15.35it/s]
Frames saved to /home/name/研究/export/headless/Walk B15 - Walk turn around_poses.mp4/0006
Video saved to: ../export/headless/Walk B15 - Walk turn around_poses.mp4
Processing: npz_path=../data/amass/ACCAD/Male1Walking_c3d/Walk B22 - Side step left_poses.npz, output_path=../export/headless/Walk B22 - Side step left_poses.mp4
Processing file: ../data/amass/ACCAD/Male1Walking_c3d/Walk B22 - Side step left_poses.npz
WARNING: You are using a SMPL+H model, with only 16 shape coefficients.
num_betas=10, shapedirs.shape=(6890, 3, 16), self.SHAPE_SPACE_DIM=300
Data keys available: ['trans', 'gender', 'mocap_framerate', 'betas', 'dmpls', 'poses']
   555 poses of size  156.
   555 trans of size    3.
     1 shape of size   16.
Gender male
FPS 120.0

Traceback (most recent call last):
  File "/home/name/研究/code/amass_save_all.py", line 55, in <module>
    process_file(npz_path, output_path)
  File "/home/name/研究/code/amass_save_all.py", line 28, in process_file
    v.save_video(output_path)  # Use video_path instead of video_dir
  File "/home/name/.local/lib/python3.10/site-packages/aitviewer/headless.py", line 37, in save_video
    self._init_scene()
  File "/home/name/.local/lib/python3.10/site-packages/aitviewer/viewer.py", line 444, in _init_scene
    self.scene.make_renderable(self.ctx)
  File "/home/name/.local/lib/python3.10/site-packages/aitviewer/scene/scene.py", line 221, in make_renderable
    r.make_renderable(self.ctx)
  File "/home/name/.local/lib/python3.10/site-packages/aitviewer/scene/node.py", line 574, in _decorator
    func(self, *args, **kwargs)
  File "/home/name/.local/lib/python3.10/site-packages/aitviewer/renderables/plane.py", line 205, in make_renderable
    self.vao = ctx.vertex_array(
  File "/home/name/.local/lib/python3.10/site-packages/moderngl/__init__.py", line 1650, in vertex_array
    return self._vertex_array(*args, **kwargs)
  File "/home/name/.local/lib/python3.10/site-packages/moderngl/__init__.py", line 1671, in _vertex_array
    res.mglo, res._glo = self.mglo.vertex_array(
_moderngl.Error: the program belongs to a different context

@yhiroya2000
Copy link
Author

yhiroya2000 commented Sep 12, 2024

This is the code that I ran.
I tried to save videos of amass files.

import os
import numpy as np

from aitviewer.configuration import CONFIG as C
from aitviewer.headless import HeadlessRenderer
from aitviewer.renderables.smpl import SMPLSequence

def process_file(npz_path, output_path):
    """Process a single .npz file."""
    
    print(f"Processing file: {npz_path}")
    c = (149 / 255, 85 / 255, 149 / 255, 1)
    smpl_seq = SMPLSequence.from_amass(
        npz_data_path=npz_path,
        fps_out=60.0,
        color=c,
        name="AMASS Running",
        show_joint_angles=True,
    )

    # Create the headless renderer and add the sequence.
    # Ensure proper cleanup of resources by using a context manager if available.
    v = HeadlessRenderer()
    v.scene.add(smpl_seq)
    v.scene.camera.position = np.array([10.0, 2.5, 0.0])
    
    # Save video with correct path
    v.save_video(output_path)  # Use video_path instead of video_dir
    smpl_seq.release()
    print(f"Video saved to: {output_path}")
    del v
    """ except Exception as e:
        print(f"An error occurred while processing file {npz_path}: {e}")
        # Ensure that the renderer is cleaned up properly if an error occurs
        del v  # Explicitly delete the renderer to free resources
 """
if __name__ == "__main__":
    accad_dir = os.path.join(C.datasets.amass, "ACCAD")
    output_dir = os.path.join(C.export_dir, "headless")

    # Ensure output directory exists
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # Iterate over all .npz files in ACCAD directory and its subdirectories
    for root, _, files in os.walk(accad_dir):
        for file in files:
            if file.endswith(".npz"):
                npz_path = os.path.join(root, file)
                # Generate output path for the video
                video_name = os.path.splitext(file)[0] + ".mp4"
                output_path = os.path.join(output_dir, video_name)
                # Process each file
                print(f"Processing: npz_path={npz_path}, output_path={output_path}")
                process_file(npz_path, output_path)

@kaufManu
Copy link
Contributor

Yes, that is unfortunately a known problem, see #12 . The cause is that the viewer is not completely cleaned up after the first use, which appears to be related to the moderngl-window implementation of pyqt5. You could try to use pyglet as the backend instead, but this might be slower:

from aitviewer.configuration import CONFIG as C
C.update_conf({"window_type": "pyglet"})

Another possibility is to only instantiate the HeadlessRenderer once and re-use it. I.e. after your first rendering pass, you remove all the nodes you don't need anymore (v.scene.remove(*nodes)) and add the new ones, but you always keep a reference to the same headless renderer object.

Finally, you can also solve the problem by starting the script as a new process each time you want to render something. For example, you could re-write your script to take npz_path and output_path as inputs via command line arguments. And then you call that script from another script that iterates over all the rendering passes you want to do. Something like:

import subprocess
npz_files = ["some/path/test1.npz", "some/path/test2.npz"]
for npz_file in npz_files:
   command = "python render_something.py --npz_file npz_file --output_path npz_file.replace('.npz', '.mp4')"
   subprocess.run(command, shell=True, check=True)

@Diouo
Copy link

Diouo commented Nov 16, 2024

you should claim "v = HeadlessRenderer()" only once in if name == "main":, it works for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants