google/ExoPlayer · critical · RuntimeException

Error instantiating FFmpeg extension

Error message

Error instantiating FFmpeg extension

What it means

DefaultRenderersFactory reflectively instantiates the optional FFmpeg audio renderer (com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer) with the (Handler, AudioRendererEventListener, AudioSink) constructor when extension renderer mode is enabled. Any reflective failure other than ClassNotFoundException — meaning the FFmpeg extension classes exist but cannot be constructed — is rethrown as a RuntimeException with the original cause, aborting renderer creation. This typically surfaces as an UnsatisfiedLinkError cause when the ffmpeg .so was not built or shipped correctly.

Source

Thrown at library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java:546

    try {
      // Full class names used for constructor args so the LINT rule triggers if any of them move.
      Class<?> clazz =
          Class.forName("com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer");
      Constructor<?> constructor =
          clazz.getConstructor(
              android.os.Handler.class,
              com.google.android.exoplayer2.audio.AudioRendererEventListener.class,
              com.google.android.exoplayer2.audio.AudioSink.class);
      Renderer renderer =
          (Renderer) constructor.newInstance(eventHandler, eventListener, audioSink);
      out.add(extensionRendererIndex++, renderer);
      Log.i(TAG, "Loaded FfmpegAudioRenderer.");
    } catch (ClassNotFoundException e) {
      // Expected if the app was built without the extension.
    } catch (Exception e) {
      // The extension is present, but instantiation failed.
      throw new RuntimeException("Error instantiating FFmpeg extension", e);
    }
  }

  /**
   * Builds text renderers for use by the player.
   *
   * @param context The {@link Context} associated with the player.
   * @param output An output for the renderers.
   * @param outputLooper The looper associated with the thread on which the output should be called.
   * @param extensionRendererMode The extension renderer mode.
   * @param out An array to which the built renderers should be appended.
   */
  protected void buildTextRenderers(
      Context context,
      TextOutput output,
      Looper outputLooper,
      @ExtensionRendererMode int extensionRendererMode,
      ArrayList<Renderer> out) {

View on GitHub (pinned to dd430f7053)

Solutions

  1. Check RuntimeException.getCause(); UnsatisfiedLinkError means the native library is absent for that ABI, NoSuchMethodException means signature drift.
  2. Rebuild the FFmpeg extension from the same tag as your core library and package all needed ABIs (follow the extensions/ffmpeg README).
  3. Align exoplayer-core and the extension version numbers exactly.
  4. If hardware decoders suffice, use EXTENSION_RENDERER_MODE_OFF to skip FFmpeg entirely.

Example fix

# before — extension built from a different release than core
# after — build extension at the exact core tag
git clone https://github.com/google/ExoPlayer.git
cd ExoPlayer && git checkout v2.19.1
cd extensions/ffmpeg && ./build.sh outputs/ffmpeg  # select codecs when prompted
# then link settings.gradle per README and depend on the project
Defensive patterns

Strategy: try-catch

Validate before calling

static boolean ffmpegNativeAvailable() {
  try {
    System.loadLibrary("ffmpegJNI");
    return true;
  } catch (UnsatisfiedLinkError e) {
    return false;
  }
}
// enable FFmpeg extension mode only when true

Try / catch

try {
  player = new ExoPlayer.Builder(ffmpegFactory).build(context);
} catch (RuntimeException e) {
  if (e.getCause() instanceof UnsatisfiedLinkError) {
    player = new ExoPlayer.Builder(new DefaultRenderersFactory(context)).build(context);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Extension renderer mode ON/PREFER with the ffmpeg extension AAR present, but libffmpegJNI.so missing for the device ABI, or the constructor signature changed between the extension build and core.

Common situations: The FFmpeg extension must be built manually from source with a chosen component set; using a prebuilt or mis-built AAR whose .so does not cover the running ABI; dependency version drift; R8 removing the renderer's constructor.

Related errors


AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14). Data as JSON: /api/errors/b204677f3ba6bce2. Report an issue: GitHub.