Search code examples
pythonmacosinstallationlibrariesmujoco

Understanding how to make a library recognise that I have the needed dependencies


I have started a project where I need to use an open source software called MuJoCo Mujoco Documentation. It is a physics simulation software that leans towards RL (reinforcement learning). Since the application I'm working on is to create an AI I also work in python for convinience.

The problem I have is that MuJoCo uses a library called 'mediapy' to visualize sequences of frames (video), and that library in turn uses a library called 'ffmpeg'. The issue is that mediapy dosen't recognize that 'ffmpeg' is installed on my computer (Mac, Intel). When I dove down into the source code to try and find the issue I found that 'mediapy' checks for the installation of 'ffmpeg' by running:

import shutil
import typing
import os

_Path = typing.Union[str, 'os.PathLike[str]']

class _Config:
  ffmpeg_name_or_path: _Path = 'ffmpeg'
  show_save_dir: _Path | None = None

_config = _Config()

def _search_for_ffmpeg_path() -> str | None:
  """Returns a path to the ffmpeg program, or None if not found."""
  if filename := shutil.which(_config.ffmpeg_name_or_path):
    return str(filename)
  return None 

I then navigated to the folder where all of my installed libraries is located opt/anaconda3/envs/myenv/lib/python3.10/site-packages and found that 'ffmpeg' folder containing everything that all other libraries contained. So it clearly exists there. However when I run the above code I get a return of 'None'. Im clearly missing something obvious but I can't seem to find it.

For reference this is the code that prompted the issue:

tippe_top = """
<mujoco model="tippe top">
  <option integrator="RK4"/>

  <asset>
    <texture name="grid" type="2d" builtin="checker" rgb1=".1 .2 .3"
     rgb2=".2 .3 .4" width="300" height="300"/>
    <material name="grid" texture="grid" texrepeat="8 8" reflectance=".2"/>
  </asset>

  <worldbody>
    <geom size=".2 .2 .01" type="plane" material="grid"/>
    <light pos="0 0 .6"/>
    <camera name="closeup" pos="0 -.1 .07" xyaxes="1 0 0 0 1 2"/>
    <body name="top" pos="0 0 .02">
      <freejoint/>
      <geom name="ball" type="sphere" size=".02" />
      <geom name="stem" type="cylinder" pos="0 0 .02" size="0.004 .008"/>
      <geom name="ballast" type="box" size=".023 .023 0.005"  pos="0 0 -.015"
       contype="0" conaffinity="0" group="3"/>
    </body>
  </worldbody>

  <keyframe>
    <key name="spinning" qpos="0 0 0.02 1 0 0 0" qvel="0 0 0 0 1 200" />
  </keyframe>
</mujoco>
"""
model = mujoco.MjModel.from_xml_string(tippe_top)
renderer = mujoco.Renderer(model)
data = mujoco.MjData(model)

duration = 7    # (seconds)
framerate = 60  # (Hz)

# Simulate and display video.
frames = []
mujoco.mj_resetDataKeyframe(model, data, 0)  # Reset the state to keyframe 0
while data.time < duration:
  mujoco.mj_step(model, data)
  if len(frames) < data.time * framerate:
    renderer.update_scene(data, "closeup")
    pixels = renderer.render()
    frames.append(pixels)

media.show_video(frames, fps=framerate)

Followed by the resulting error message:

{
    "name": "RuntimeError",
    "message": "Program 'ffmpeg' is not found; perhaps install ffmpeg using 'apt install ffmpeg'.",
    "stack": "---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[4], line 14
     11     pixels = renderer.render()
     12     frames.append(pixels)
---> 14 media.show_video(frames, fps=framerate)

File ~/opt/anaconda3/envs/Exjobb/lib/python3.10/site-packages/mediapy/__init__.py:1858, in show_video(images, title, **kwargs)
   1835 def show_video(
   1836     images: Iterable[_NDArray], *, title: str | None = None, **kwargs: Any
   1837 ) -> str | None:
   1838   \"\"\"Displays a video in the IPython notebook and optionally saves it to a file.
   1839 
   1840   See `show_videos`.
   (...)
   1856     html string if `return_html` is `True`.
   1857   \"\"\"
-> 1858   return show_videos([images], [title], **kwargs)

File ~/opt/anaconda3/envs/Exjobb/lib/python3.10/site-packages/mediapy/__init__.py:1940, in show_videos(videos, titles, width, height, downsample, columns, fps, bps, qp, codec, ylabel, html_class, return_html, **kwargs)
   1938   video = [resize_image(image, (h, w)) for image in video]
   1939   first_image = video[0]
-> 1940 data = compress_video(
   1941     video, metadata=metadata, fps=fps, bps=bps, qp=qp, codec=codec
   1942 )
   1943 if title is not None and _config.show_save_dir:
   1944   suffix = _filename_suffix_from_codec(codec)

File ~/opt/anaconda3/envs/Exjobb/lib/python3.10/site-packages/mediapy/__init__.py:1777, in compress_video(images, codec, **kwargs)
   1775 with tempfile.TemporaryDirectory() as directory_name:
   1776   tmp_path = pathlib.Path(directory_name) / f'file{suffix}'
-> 1777   write_video(tmp_path, images, codec=codec, **kwargs)
   1778   return tmp_path.read_bytes()

File ~/opt/anaconda3/envs/Exjobb/lib/python3.10/site-packages/mediapy/__init__.py:1747, in write_video(path, images, **kwargs)
   1745   dtype = np.dtype(np.uint16)
   1746 kwargs = {'metadata': getattr(images, 'metadata', None), **kwargs}
-> 1747 with VideoWriter(path, shape=shape, dtype=dtype, **kwargs) as writer:
   1748   for image in images:
   1749     writer.add_image(image)

File ~/opt/anaconda3/envs/Exjobb/lib/python3.10/site-packages/mediapy/__init__.py:1567, in VideoWriter.__enter__(self)
   1566 def __enter__(self) -> 'VideoWriter':
-> 1567   ffmpeg_path = _get_ffmpeg_path()
   1568   input_pix_fmt = self._get_pix_fmt(self.dtype, self.input_format)
   1569   try:

File ~/opt/anaconda3/envs/Exjobb/lib/python3.10/site-packages/mediapy/__init__.py:1167, in _get_ffmpeg_path()
   1165 path = _search_for_ffmpeg_path()
   1166 if not path:
-> 1167   raise RuntimeError(
   1168       f\"Program '{_config.ffmpeg_name_or_path}' is not found;\"
   1169       \" perhaps install ffmpeg using 'apt install ffmpeg'.\"
   1170   )
   1171 return path

RuntimeError: Program 'ffmpeg' is not found; perhaps install ffmpeg using 'apt install ffmpeg'."
}

Any help is well appreciated.

I have tried changing the names of the files the 'shutil.which' command is searching for. I have tried reinstalling the libraries as well as try a different library (there seem to be two 'ffmpeg-python', version 0.2 and ffmpeg (which shows up in my directory as 'imageio_ffmpeg') version 0.4.9 (but it said 1.4 on the pip website)).


Solution

  • moviepy requires the ffmpeg command-line tool, not the ffmpeg-python Python library or the imageio_ffmpeg Python library, so looking in site-packages is useless.

    shutil.which() doesn't look for libraries either, it looks for commands, so changing things there doesn't do you any good either.

    You can find out if you have ffmpeg installed by typing ffmpeg on your command line.

    If you have Homebrew, you can install the tool with

    brew install ffmpeg
    

    or otherwise via ffmpeg.org.