diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java
index d17820a71f..2982d9f299 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java
@@ -1573,6 +1573,10 @@ public interface ExoPlayer extends Player {
*
The following limitations exist for using {@linkplain Effect video effects}:
*
*
+ * - The {@code androidx.media3:media3-effect} module must be available on the runtime
+ * classpath. {@code androidx.media3:media3-exoplayer} does not explicitly depend on the
+ * effect module, so apps must make sure it's available themselves. It must be the same
+ * version as the rest of the {@code androidx.media3} modules being used by the app.
*
- This feature works only with the default {@link MediaCodecVideoRenderer} and not custom
* or extension {@linkplain Renderer video renderers}.
*
- This feature does not work with {@linkplain Effect effects} updating the timestamps.
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java
index de0301b149..7c32751027 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java
@@ -81,6 +81,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.Tracks;
+import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue;
import androidx.media3.common.text.CueGroup;
@@ -1277,6 +1278,13 @@ import java.util.concurrent.TimeoutException;
@Override
public void setVideoEffects(List videoEffects) {
verifyApplicationThread();
+ try {
+ // LINT.IfChange(set_video_effects)
+ Class.forName("androidx.media3.effect.PreviewingSingleInputVideoGraph$Factory")
+ .getConstructor(VideoFrameProcessor.Factory.class);
+ } catch (ClassNotFoundException | NoSuchMethodException e) {
+ throw new IllegalStateException("Could not find required lib-effect dependencies.", e);
+ }
sendRendererMessage(TRACK_TYPE_VIDEO, MSG_SET_VIDEO_EFFECTS, videoEffects);
}
diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java
index d30d26ca3a..d8c9d610da 100644
--- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java
+++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java
@@ -14254,6 +14254,14 @@ public final class ExoPlayerTest {
assertThat(metadataAfterTransition.title).isEqualTo("title");
}
+ @Test
+ public void setVideoEffects_failsWithoutLibEffectsDep() {
+ ExoPlayer player = new TestExoPlayerBuilder(context).build();
+ IllegalStateException expected =
+ assertThrows(IllegalStateException.class, () -> player.setVideoEffects(ImmutableList.of()));
+ assertThat(expected).hasMessageThat().contains("lib-effect dependencies");
+ }
+
// Internal methods.
private void addWatchAsSystemFeature() {