What an app needs on each platform beyond adding a family package. Google's
pinned models (model: VisionModels.faceLandmarker and the like) are bundled
with the app at build time by dart run mediapipe_core:bundle_models (see
Build settings), so an app that bundles its models needs no
network access at run time. The network settings below are only for apps
that set ModelStore.allowDownloads = true to download models at run time
instead.
-
minSdk28 (Android 9) or higher, inandroid/app/build.gradle(.kts). Google's MediaPipe libraries need it, and a lower value fails the build with this fix. -
Each family bundles Google's MediaPipe library for that family (
libmediapipe_tasks_vision.so,libmediapipe_tasks_text.so,libmediapipe_tasks_audio.so), so an app ships only the families it uses: about 13 MB for vision, 15 MB for text and 8 MB for audio on arm64-v8a. No Google AAR or other Gradle dependency is involved. Tasks run on arm64-v8a and x86_64. On 32-bit phones (armeabi-v7a) the vision, classic text and audio tasks run on the CPU; Decision Maker, the retrieval tasks, EmbeddingGemma, the Proofreader and the Summarizer need 64-bit, since their models take more memory than a 32-bit process holds, and their capability queries say so. -
Which ABIs an app carries is the app's choice, and each family bundles its library only for those. A Play App Bundle (
flutter build appbundle) delivers each phone its own ABI's libraries alone, so 32-bit support costs a 64-bit phone nothing.flutter build apk --split-per-abibuilds one APK per ABI, andflutter build apk --target-platform android-arm64(orndk.abiFiltersin Gradle) leaves 32-bit out, about 44 MB lighter with all five families. -
On an emulator only the CPU is offered: it renders OpenGL ES in software (SwiftShader), where Google's GPU inference fails. Phones keep the GPU.
-
To download models at run time, add the
INTERNETpermission toandroid/app/src/main/AndroidManifest.xml. Flutter adds it only to debug and profile builds, so a release build without it cannot download models:<uses-permission android:name="android.permission.INTERNET"/>
When the connection fails, the
ModelDownloadExceptionnames this permission.
- iOS 15.0 or newer. Each family bundles Google's MediaPipe library for that
family (
MediaPipeTasksVisionC,MediaPipeTasksTextC,MediaPipeTasksAudioC,MediaPipeTasksDecisionC,MediaPipeTasksRetrievalC), so an app ships only the families it uses; no CocoaPods or native plugin is involved. The build extracts only the device or simulator slice it needs. - For the App Store, the app's
PrivacyInfo.xcprivacydeclares the required-reason APIs Google's libraries call; see privacy and licenses. - On the iOS Simulator only the CPU is offered: Google's MediaPipe aborts on the simulator's GPU path. Devices keep Metal where a task offers it. The nine vision tasks and Audio Transcriber that offer it were tested on an iPhone 15 Pro (iOS 27) with Google's 1.2.2 library; iPads were not tested.
- Downloaded models live in the app's Application Support folder, excluded from iCloud backup.
-
macOS 14.0 or newer on Apple Silicon. 14.0 is the minimum the packages are built for, but CI no longer runs on it, because GitHub retired its macOS 14 images. The oldest macOS that CI runs on is 15.
-
Build the app for Apple Silicon only. Flutter's release and profile builds (
flutter build macos,flutter run --release) also build an Intel (x86_64) slice by default, and Google's MediaPipe libraries have none, so such a build fails with these instructions. Add these lines tomacos/Runner/Configs/AppInfo.xcconfig:ARCHS = arm64 EXCLUDED_ARCHS = x86_64Or run
flutter config --enable-macos-arm64-only, which does the same for every app that machine builds, CI runners included. Debug builds target only the Mac they run on, so they work either way. Setting the Runner's deployment target (MACOSX_DEPLOYMENT_TARGET) to 14.0 also keeps the app off older macOS, where the libraries cannot load. -
Each family bundles Google's MediaPipe library for that family: about 27 MB for vision, 26 MB for text and 13 MB for audio.
-
To download models at run time, a sandboxed app needs the network client entitlement in
macos/Runner/DebugProfile.entitlementsandRelease.entitlements:<key>com.apple.security.network.client</key> <true/>
- Google's Linux library loads EGL and OpenGL ES even for CPU inference. On
Debian or Ubuntu:
sudo apt-get install libegl1 libgles2. Without them, task creation fails with that instruction. - GPU inference uses OpenGL ES where the vision status table lists it.
- CPU inference. Google's Windows library may wait for a usage-log upload when a task is disposed.
- Workers load Google's pinned
@mediapipe/tasks-*runtime from jsDelivr by default and check every file against its SHA-384 before running it, then load it from ablob:URL. Bundled models load from the app's own assets. Models downloaded at run time (ModelStore.allowDownloads = true) come fromstorage.googleapis.comand are kept in Cache Storage. - To serve the runtimes yourself (offline, an intranet, or a strict policy),
run
dart run mediapipe_core:web_runtime web/mediapipefrom the app root and setMediaPipeWebRuntime.baseUrl = 'mediapipe/';before creating the first task. The same hashes apply. - If the site sends a Content Security Policy, it has to allow what the
loader does:
script-srcandworker-srcfor'self'andblob:,'wasm-unsafe-eval'for the WebAssembly runtime, andconnect-srcfor'self'(bundled models),https://cdn.jsdelivr.net(unless self-hosted) andhttps://storage.googleapis.com(only for models downloaded at run time). CI runs without a policy, so test yours in the browsers you support.
Every setting lives under hooks.user_defines in the app's pubspec.yaml
and applies to all of the app's platforms.
| Key | Values | Effect |
|---|---|---|
mediapipe_core.asset_source |
directory or http(s) URL |
Downloads every pinned runtime from there instead of its URLs; see below |
mediapipe_vision.tasks |
list of task names | Checks the names against the tasks validated on the target (a Windows build fails on interactive_segmenter) |
mediapipe_vision.models, mediapipe_text.models, mediapipe_audio.models |
list of model names from XxxModels.byName |
The models dart run mediapipe_core:bundle_models bundles into assets/mediapipe/, which the app declares under flutter: assets: |
List the models each family uses, declare the folder, and run the command from the app's root whenever the lists change:
flutter:
assets:
- assets/mediapipe/
hooks:
user_defines:
mediapipe_vision:
models: [face_landmarker, hand_landmarker]
mediapipe_audio:
models: [yamnet]dart run mediapipe_core:bundle_models # download, verify, prune
dart run mediapipe_core:bundle_models --check # verify only, for CIWhat the command writes, how a task created with model: finds its model and
how to opt in to run-time downloads are in the core guide's
Bundled models and
On-demand models.
asset_source points the build hooks and bundle_models at a directory or
an internal URL root holding files named by their full SHA-256, and
ModelStore(source: ...) reads models from the same kind of source at run
time. The core guide's
Verified downloads and offline builds
explains both and the tool that fills such a directory from a checkout.