# MediaPipe disables the GPU unless you set one environment variable to 0

> MediaPipe is Google's on-device machine learning library for live and streaming media, used through cross-platform Tasks APIs and pre-trained models, with a lower-level Framework layer underneath built on graphs, packets, and calculators. The build story is where the surprises are: the Python packaging script turns the GPU off by default, and the environment variable that re-enables it accepts exactly one value.

**google-ai-edge/mediapipe** — Cross-platform, customizable ML solutions for live and streaming media.

- Repository: https://github.com/google-ai-edge/mediapipe
- Website: https://ai.google.dev/edge/mediapipe
- Stars: 37,118 · Forks: 6,171
- Language: C++
- License: Apache-2.0
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/google-ai-edge-mediapipe

## The packaging script turns the GPU off unless the variable equals the string 0

The first thing to know about building the Python package is that GPU support is not the default. setup.py decides it with one line:

```python
MP_DISABLE_GPU = os.environ.get('MEDIAPIPE_DISABLE_GPU') != '0'
```

The variable is read and compared against the literal string `0`. If the variable is unset, the comparison succeeds and GPU work is disabled. If it is set to anything other than that exact string, the comparison also succeeds, and the GPU stays off. So what this cannot do is accept a conventional falsy value. Setting `MEDIAPIPE_DISABLE_GPU=false` or setting it to `no` leaves the GPU disabled without any error, because only the literal 0 flips the condition. The consequence is that a build that looks GPU-enabled in your environment is not, and the flag that would have told you so is one you have to check rather than infer, because the failure surfaces later as an unexplained CPU path.

## Enabling the GPU swaps in X11 suppression flags and a macOS-only buffer define

Turning the GPU on is not a single switch, it is a different set of build defines. The script holds two lists. The disabled one is:

```python
GPU_OPTIONS_DISABLED = ['--define=MEDIAPIPE_DISABLE_GPU=1']
GPU_OPTIONS_ENABLED = [
    '--copt=-DTFLITE_GPU_EXTRA_GLES_DEPS',
    '--copt=-DMEDIAPIPE_OMIT_EGL_WINDOW_BIT',
    '--copt=-DMESA_EGL_NO_X11_HEADERS',
    '--copt=-DEGL_NO_X11',
]
```

Three of those four defines exist to take X11 out of the picture, and one asks for extra GLES dependencies in the TFLite layer. On macOS a fifth define is appended at runtime, a buffer flag for using a CV pixel buffer. So what the GPU build cannot do is be one configuration across platforms, and the EGL_NO_X11 pair means anything expecting an X11-backed EGL window surface is deliberately excluded. The consequence is that a GPU build is really two builds, and the one you can reproduce is the one matching your platform's branch in that script.

## The build image installs Clang 16 from a script and symlinks it over the default

The container build starts from ubuntu:22.04 and assembles the toolchain in stages. The compiler step is a downloaded script rather than a package:

```dockerfile
RUN wget https://apt.llvm.org/llvm.sh
RUN chmod +x llvm.sh
RUN ./llvm.sh 16
RUN ln -sf /usr/bin/clang-16 /usr/bin/clang
RUN ln -sf /usr/bin/clang++-16 /usr/bin/clang++
RUN ln -sf /usr/bin/clang-format-16 /usr/bin/clang-format
```

The symlinks are what make clang 16 the default compiler for anything later in the build. The same image also installs openjdk-21-jdk, the Mesa EGL and GLES development packages, mesa-utils, nodejs and npm, ffmpeg, and six separate libopencv development packages. At the root of the repository the build is driven by Bazel, and it carries both a WORKSPACE file and a MODULE.bazel alongside a .bazelversion and a .bazelrc, so the legacy and module-based build systems are both present. The consequence is that reproducing a build means reproducing that exact toolchain, and a compiler installed elsewhere can be shadowed by these symlinks without any warning.

## Five lock files, one for each Python minor version from 3.10 to 3.14

The repository root carries a requirements.txt and, beside it, six resolved sets: requirements_lock.txt plus one file per minor version named requirements_lock_3_10, _3_11, _3_12, _3_13, and _3_14. So the supported Python range spans five minor versions, each with its own pinned resolution rather than one set that stretches across all of them. What a single lock file cannot do is serve every version, which is presumably why there are five. The consequence is that adding a new Python minor release means producing another lock file, and that a contributor picking the wrong one can get a resolution that was never tested for their interpreter. The unpinned requirements.txt beside them stays minimal, with the notable entries being absl-py, certifi, numpy, sounddevice, flatbuffers, opencv-contrib-python, and matplotlib.

## The version in the source tree is the string dev while the tags say 1.0.0

setup.py hardcodes its own version rather than reading a manifest:

```python
__version__ = 'dev'
```

The release history tells a different story. The tags are v1.0.0, dated 2026-07-28, then v0.10.35 and v0.10.33, and the repository is not archived with a last push of 2026-09-29. So what the source cannot tell you is which release you are running, because the packaged version string does not come from the tag. There is a VERSION-style file elsewhere in the tree, but the Python path does not read it. The consequence is that anything reporting a version at runtime from a source build will say dev, which makes it useless for bug reports and for support threads, and a user comparing two installations has to fall back to the commit rather than to the version.

## sounddevice in the default requirements pulls in a system audio library

The requirements list is short and mostly floating, with only two entries carrying a compatible-release constraint, absl-py at 2.3 and sounddevice at 0.5. Everything else, including certifi, numpy, flatbuffers, opencv-contrib-python, and matplotlib, is unpinned. The sounddevice entry is the one that catches people out, because it is a Python binding to a native audio interface rather than a self-contained package, so a pip install can succeed and still leave the import failing until the underlying system audio library is present. So what the requirements file cannot do is guarantee a working import on a bare machine, because it describes Python packages and not the native libraries behind them. The consequence is that a Docker image with no audio device installed is a different environment from the one these requirements were written for, and the failure appears at import time rather than at install time.

## Legacy solutions lost support on March 1, 2023 and stay available as-is

The README is explicit that support for the MediaPipe Legacy Solutions ended as of March 1, 2023, and that all other legacy solutions will be upgraded to a new MediaPipe Solution. The mitigation is stated in the same breath: the code repository and the prebuilt binaries for all legacy solutions will continue to be provided on an as-is basis. So what the legacy path cannot offer is a fix, and as-is means exactly that. The consequence is that an application still on a legacy solution is running against binaries that will not be patched, and the documentation carries both eras at once, which is why searching for MediaPipe guidance returns material for an API generation that no longer receives support. There is a second documentation notice in the same file, saying the primary developer documentation site moved to developers.google.com as of April 3, 2023, which is a different URL from the homepage the repository metadata carries.

## Input stays on the device, metrics go to Google, and the consent duty is yours

The privacy notice, last modified on June 5, 2026, is unusually specific and worth reading in full rather than skimming. It states that when you use MediaPipe Tasks, processing of the input data, meaning images, video, and text, takes place on device, and that MediaPipe does not send that input data to Google servers. From that it draws the conclusion that the Tasks APIs can be used for data that should not leave the device. The same notice then says the APIs do send metrics about the performance and utilization of the APIs in your app to Google, which uses that to measure performance, usage, debug, maintain, and improve the APIs. The last line places the obligation on you: you are responsible for obtaining informed consent from your app users about Google's processing of that metrics data as required by applicable law. So what the on-device claim cannot do is extend to telemetry, and the consequence is that a privacy review has two data flows to assess rather than one.

## Conclusion

MediaPipe suits an application that must process camera or audio input locally across several platforms and wants a single Tasks API with a ready-made model rather than a graph pipeline written by hand. It is a poor fit if you need a reproducible GPU build without pinning the toolchain, since the default is CPU and the escape hatch is a single literal value. Before you start, decide whether you need the Tasks layer or the Framework, note that the legacy solutions lost support on March 1, 2023, and read the privacy notice, because input stays on device but usage metrics are sent to Google and the consent duty lands on you.

## FAQ

### What is a MediaPipe used for?

It provides cross-platform, customizable machine learning solutions for live and streaming media, intended for on-device inference across mobile on Android and iOS, web, desktop, edge devices, and IoT. The entry points are MediaPipe Tasks for the cross-platform APIs and MediaPipe models for pre-trained, ready-to-run models.

### Is MediaPipe still supported?

The repository is not archived and its last push is dated 2026-09-29, with v1.0.0 tagged on 2026-07-28. Separately, support for the Legacy Solutions ended as of March 1, 2023, and their code and prebuilt binaries continue to be provided on an as-is basis. The README also labels MediaPipe Solutions Preview an early release.

### Is MediaPipe owned by Google?

The project is published by Google under the Apache License 2.0, and its privacy notice says the Tasks APIs send performance and utilization metrics to Google, which uses that data to measure, maintain, and improve them. The same notice states that input data is processed on device and is not sent to Google servers.

### how to install mediapipe in python

The README points to setup guides for Android, web apps, and Python hosted on developers.google.com. The repository requirements include numpy, opencv-contrib-python, sounddevice, flatbuffers, absl-py, certifi, and matplotlib, and there are separate resolved lock files for Python 3.10 through 3.14 alongside the base requirements file.

### Is MediaPipe better than OpenCV?

The project publishes no such comparison. What it does state is that the Tasks layer is a set of cross-platform APIs and libraries for deploying solutions using pre-trained models, that OpenCV appears as both a Python requirement and a set of development packages in the container build, and that the repository ships a setup_opencv.sh script alongside per-platform example build scripts.

## Sources

- [Official documentation](https://ai.google.dev/edge/mediapipe)
- [Official README](https://github.com/google-ai-edge/mediapipe#readme)
- [Project repository](https://github.com/google-ai-edge/mediapipe)
- [Release notes](https://github.com/google-ai-edge/mediapipe/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/google-ai-edge-mediapipe
