diff --git a/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java b/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java index 53d81e9158..b1a09fb72f 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/MediaItem.java @@ -77,6 +77,8 @@ public final class MediaItem { @Nullable private Object tag; @Nullable private MediaMetadata mediaMetadata; private long liveTargetOffsetMs; + private long liveMinOffsetMs; + private long liveMaxOffsetMs; private float liveMinPlaybackSpeed; private float liveMaxPlaybackSpeed; @@ -88,6 +90,8 @@ public final class MediaItem { streamKeys = Collections.emptyList(); subtitles = Collections.emptyList(); liveTargetOffsetMs = C.TIME_UNSET; + liveMinOffsetMs = C.TIME_UNSET; + liveMaxOffsetMs = C.TIME_UNSET; liveMinPlaybackSpeed = C.RATE_UNSET; liveMaxPlaybackSpeed = C.RATE_UNSET; } @@ -102,6 +106,8 @@ public final class MediaItem { mediaId = mediaItem.mediaId; mediaMetadata = mediaItem.mediaMetadata; liveTargetOffsetMs = mediaItem.liveConfiguration.targetLiveOffsetMs; + liveMinOffsetMs = mediaItem.liveConfiguration.minLiveOffsetMs; + liveMaxOffsetMs = mediaItem.liveConfiguration.maxLiveOffsetMs; liveMinPlaybackSpeed = mediaItem.liveConfiguration.minPlaybackSpeed; liveMaxPlaybackSpeed = mediaItem.liveConfiguration.maxPlaybackSpeed; @Nullable PlaybackProperties playbackProperties = mediaItem.playbackProperties; @@ -436,6 +442,32 @@ public final class MediaItem { return this; } + /** + * Sets the optional minimum offset from the live edge for live streams, in milliseconds. + * + *

See {@code Player#getCurrentLiveOffset()}. + * + * @param liveMinOffsetMs The minimum allowed live offset, in milliseconds, or {@link + * C#TIME_UNSET} to use the media-defined default. + */ + public Builder setLiveMinOffsetMs(long liveMinOffsetMs) { + this.liveMinOffsetMs = liveMinOffsetMs; + return this; + } + + /** + * Sets the optional maximum offset from the live edge for live streams, in milliseconds. + * + *

See {@code Player#getCurrentLiveOffset()}. + * + * @param liveMaxOffsetMs The maximum allowed live offset, in milliseconds, or {@link + * C#TIME_UNSET} to use the media-defined default. + */ + public Builder setLiveMaxOffsetMs(long liveMaxOffsetMs) { + this.liveMaxOffsetMs = liveMaxOffsetMs; + return this; + } + /** * Sets the optional minimum playback speed for live stream speed adjustment. * @@ -519,7 +551,12 @@ public final class MediaItem { clipRelativeToDefaultPosition, clipStartsAtKeyFrame), playbackProperties, - new LiveConfiguration(liveTargetOffsetMs, liveMinPlaybackSpeed, liveMaxPlaybackSpeed), + new LiveConfiguration( + liveTargetOffsetMs, + liveMinOffsetMs, + liveMaxOffsetMs, + liveMinPlaybackSpeed, + liveMaxPlaybackSpeed), mediaMetadata != null ? mediaMetadata : new MediaMetadata.Builder().build()); } } @@ -712,7 +749,7 @@ public final class MediaItem { /** A live playback configuration with unset values. */ public static final LiveConfiguration UNSET = - new LiveConfiguration(C.TIME_UNSET, C.RATE_UNSET, C.RATE_UNSET); + new LiveConfiguration(C.TIME_UNSET, C.TIME_UNSET, C.TIME_UNSET, C.RATE_UNSET, C.RATE_UNSET); /** * Target live offset, in milliseconds, or {@link C#TIME_UNSET} to use the media-defined @@ -720,6 +757,18 @@ public final class MediaItem { */ public final long targetLiveOffsetMs; + /** + * The minimum allowed live offset, in milliseconds, or {@link C#TIME_UNSET} to use the + * media-defined default. + */ + public final long minLiveOffsetMs; + + /** + * The maximum allowed live offset, in milliseconds, or {@link C#TIME_UNSET} to use the + * media-defined default. + */ + public final long maxLiveOffsetMs; + /** Minimum playback speed, or {@link C#RATE_UNSET} to use the media-defined default. */ public final float minPlaybackSpeed; @@ -731,14 +780,24 @@ public final class MediaItem { * * @param targetLiveOffsetMs Target live offset, in milliseconds, or {@link C#TIME_UNSET} to use * the media-defined default. + * @param minLiveOffsetMs The minimum allowed live offset, in milliseconds, or {@link + * C#TIME_UNSET} to use the media-defined default. + * @param maxLiveOffsetMs The maximum allowed live offset, in milliseconds, or {@link + * C#TIME_UNSET} to use the media-defined default. * @param minPlaybackSpeed Minimum playback speed, or {@link C#RATE_UNSET} to use the * media-defined default. * @param maxPlaybackSpeed Maximum playback speed, or {@link C#RATE_UNSET} to use the * media-defined default. */ public LiveConfiguration( - long targetLiveOffsetMs, float minPlaybackSpeed, float maxPlaybackSpeed) { + long targetLiveOffsetMs, + long minLiveOffsetMs, + long maxLiveOffsetMs, + float minPlaybackSpeed, + float maxPlaybackSpeed) { this.targetLiveOffsetMs = targetLiveOffsetMs; + this.minLiveOffsetMs = minLiveOffsetMs; + this.maxLiveOffsetMs = maxLiveOffsetMs; this.minPlaybackSpeed = minPlaybackSpeed; this.maxPlaybackSpeed = maxPlaybackSpeed; } @@ -754,6 +813,8 @@ public final class MediaItem { LiveConfiguration other = (LiveConfiguration) obj; return targetLiveOffsetMs == other.targetLiveOffsetMs + && minLiveOffsetMs == other.minLiveOffsetMs + && maxLiveOffsetMs == other.maxLiveOffsetMs && minPlaybackSpeed == other.minPlaybackSpeed && maxPlaybackSpeed == other.maxPlaybackSpeed; } @@ -761,6 +822,8 @@ public final class MediaItem { @Override public int hashCode() { int result = (int) (targetLiveOffsetMs ^ (targetLiveOffsetMs >>> 32)); + result = 31 * result + (int) (minLiveOffsetMs ^ (minLiveOffsetMs >>> 32)); + result = 31 * result + (int) (maxLiveOffsetMs ^ (maxLiveOffsetMs >>> 32)); result = 31 * result + (minPlaybackSpeed != 0 ? Float.floatToIntBits(minPlaybackSpeed) : 0); result = 31 * result + (maxPlaybackSpeed != 0 ? Float.floatToIntBits(maxPlaybackSpeed) : 0); return result; diff --git a/library/common/src/test/java/com/google/android/exoplayer2/MediaItemTest.java b/library/common/src/test/java/com/google/android/exoplayer2/MediaItemTest.java index 31aa8bbff2..683e3cbf7f 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/MediaItemTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/MediaItemTest.java @@ -295,7 +295,7 @@ public class MediaItemTest { } @Test - public void builderSetLiveTargetLatencyMs_setsLiveTargetLatencyMs() { + public void builderSetLiveTargetOffsetMs_setsLiveTargetOffsetMs() { MediaItem mediaItem = new MediaItem.Builder().setUri(URI_STRING).setLiveTargetOffsetMs(10_000).build(); @@ -318,6 +318,22 @@ public class MediaItemTest { assertThat(mediaItem.liveConfiguration.maxPlaybackSpeed).isEqualTo(1.1f); } + @Test + public void builderSetMinLiveOffset_setsMinLiveOffset() { + MediaItem mediaItem = + new MediaItem.Builder().setUri(URI_STRING).setLiveMinOffsetMs(1234).build(); + + assertThat(mediaItem.liveConfiguration.minLiveOffsetMs).isEqualTo(1234); + } + + @Test + public void builderSetMaxLiveOffset_setsMaxLiveOffset() { + MediaItem mediaItem = + new MediaItem.Builder().setUri(URI_STRING).setLiveMaxOffsetMs(1234).build(); + + assertThat(mediaItem.liveConfiguration.maxLiveOffsetMs).isEqualTo(1234); + } + @Test public void buildUpon_equalsToOriginal() { MediaItem mediaItem = @@ -346,6 +362,8 @@ public class MediaItemTest { .setLiveTargetOffsetMs(20_000) .setLiveMinPlaybackSpeed(.9f) .setLiveMaxPlaybackSpeed(1.1f) + .setLiveMinOffsetMs(2222) + .setLiveMaxOffsetMs(4444) .setSubtitles( Collections.singletonList( new MediaItem.Subtitle( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java index 62a40b0110..a4b97219d2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java @@ -110,6 +110,8 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { @Nullable private List streamKeys; @Nullable private LoadErrorHandlingPolicy loadErrorHandlingPolicy; private long liveTargetOffsetMs; + private long liveMinOffsetMs; + private long liveMaxOffsetMs; private float liveMinSpeed; private float liveMaxSpeed; @@ -161,6 +163,8 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { supportedTypes[i] = mediaSourceFactories.keyAt(i); } liveTargetOffsetMs = C.TIME_UNSET; + liveMinOffsetMs = C.TIME_UNSET; + liveMaxOffsetMs = C.TIME_UNSET; liveMinSpeed = C.RATE_UNSET; liveMaxSpeed = C.RATE_UNSET; } @@ -201,6 +205,30 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { return this; } + /** + * Sets the minimum offset from the live edge for live streams, in milliseconds. + * + * @param liveMinOffsetMs The minimum allowed live offset, in milliseconds, or {@link + * C#TIME_UNSET} to use the media-defined default. + * @return This factory, for convenience. + */ + public DefaultMediaSourceFactory setLiveMinOffsetMs(long liveMinOffsetMs) { + this.liveMinOffsetMs = liveMinOffsetMs; + return this; + } + + /** + * Sets the maximum offset from the live edge for live streams, in milliseconds. + * + * @param liveMaxOffsetMs The maximum allowed live offset, in milliseconds, or {@link + * C#TIME_UNSET} to use the media-defined default. + * @return This factory, for convenience. + */ + public DefaultMediaSourceFactory setLiveMaxOffsetMs(long liveMaxOffsetMs) { + this.liveMaxOffsetMs = liveMaxOffsetMs; + return this; + } + /** * Sets the minimum playback speed for live streams. * @@ -294,7 +322,11 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { || (mediaItem.liveConfiguration.minPlaybackSpeed == C.RATE_UNSET && liveMinSpeed != C.RATE_UNSET) || (mediaItem.liveConfiguration.maxPlaybackSpeed == C.RATE_UNSET - && liveMaxSpeed != C.RATE_UNSET)) { + && liveMaxSpeed != C.RATE_UNSET) + || (mediaItem.liveConfiguration.minLiveOffsetMs == C.TIME_UNSET + && liveMinOffsetMs != C.TIME_UNSET) + || (mediaItem.liveConfiguration.maxLiveOffsetMs == C.TIME_UNSET + && liveMaxOffsetMs != C.TIME_UNSET)) { mediaItem = mediaItem .buildUpon() @@ -310,6 +342,14 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { mediaItem.liveConfiguration.maxPlaybackSpeed == C.RATE_UNSET ? liveMaxSpeed : mediaItem.liveConfiguration.maxPlaybackSpeed) + .setLiveMinOffsetMs( + mediaItem.liveConfiguration.minLiveOffsetMs == C.TIME_UNSET + ? liveMinOffsetMs + : mediaItem.liveConfiguration.minLiveOffsetMs) + .setLiveMaxOffsetMs( + mediaItem.liveConfiguration.maxLiveOffsetMs == C.TIME_UNSET + ? liveMaxOffsetMs + : mediaItem.liveConfiguration.maxLiveOffsetMs) .build(); } MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/DefaultLivePlaybackSpeedControlTest.java b/library/core/src/test/java/com/google/android/exoplayer2/DefaultLivePlaybackSpeedControlTest.java index 61c0f88b48..50fcf96283 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/DefaultLivePlaybackSpeedControlTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/DefaultLivePlaybackSpeedControlTest.java @@ -42,7 +42,11 @@ public class DefaultLivePlaybackSpeedControlTest { new DefaultLivePlaybackSpeedControl.Builder().build(); defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( - /* targetLiveOffsetMs= */ 42, /* minPlaybackSpeed= */ 1f, /* maxPlaybackSpeed= */ 1f)); + /* targetLiveOffsetMs= */ 42, + /* minLiveOffsetMs= */ 200, + /* maxLiveOffsetMs= */ 400, + /* minPlaybackSpeed= */ 1f, + /* maxPlaybackSpeed= */ 1f)); assertThat(defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs()).isEqualTo(42_000); } @@ -55,7 +59,11 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setTargetLiveOffsetOverrideUs(123_456_789); defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( - /* targetLiveOffsetMs= */ 42, /* minPlaybackSpeed= */ 1f, /* maxPlaybackSpeed= */ 1f)); + /* targetLiveOffsetMs= */ 42, + /* minLiveOffsetMs= */ 200, + /* maxLiveOffsetMs= */ 400, + /* minPlaybackSpeed= */ 1f, + /* maxPlaybackSpeed= */ 1f)); long targetLiveOffsetUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs(); @@ -82,7 +90,11 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setTargetLiveOffsetOverrideUs(123_456_789); defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( - /* targetLiveOffsetMs= */ 42, /* minPlaybackSpeed= */ 1f, /* maxPlaybackSpeed= */ 1f)); + /* targetLiveOffsetMs= */ 42, + /* minLiveOffsetMs= */ 200, + /* maxLiveOffsetMs= */ 400, + /* minPlaybackSpeed= */ 1f, + /* maxPlaybackSpeed= */ 1f)); defaultLivePlaybackSpeedControl.setTargetLiveOffsetOverrideUs(C.TIME_UNSET); long targetLiveOffsetUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs(); @@ -97,6 +109,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -113,6 +127,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -138,6 +154,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -157,6 +175,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -176,6 +196,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -194,6 +216,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -212,6 +236,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ 2f)); @@ -230,6 +256,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ 0.2f, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -247,6 +275,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -270,6 +300,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); @@ -278,6 +310,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); float adjustedSpeed2 = @@ -293,6 +327,8 @@ public class DefaultLivePlaybackSpeedControlTest { defaultLivePlaybackSpeedControl.setLiveConfiguration( new LiveConfiguration( /* targetLiveOffsetMs= */ 2_000, + /* minLiveOffsetMs= */ C.TIME_UNSET, + /* maxLiveOffsetMs= */ C.TIME_UNSET, /* minPlaybackSpeed= */ C.RATE_UNSET, /* maxPlaybackSpeed= */ C.RATE_UNSET)); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java index 29fe5c690e..08200f93f3 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactoryTest.java @@ -246,6 +246,8 @@ public final class DefaultMediaSourceFactoryTest { MediaItem mediaItemFromSource = mediaSource.getMediaItem(); assertThat(mediaItemFromSource.liveConfiguration.targetLiveOffsetMs).isEqualTo(C.TIME_UNSET); + assertThat(mediaItemFromSource.liveConfiguration.minLiveOffsetMs).isEqualTo(C.TIME_UNSET); + assertThat(mediaItemFromSource.liveConfiguration.maxLiveOffsetMs).isEqualTo(C.TIME_UNSET); assertThat(mediaItemFromSource.liveConfiguration.minPlaybackSpeed).isEqualTo(C.RATE_UNSET); assertThat(mediaItemFromSource.liveConfiguration.maxPlaybackSpeed).isEqualTo(C.RATE_UNSET); } @@ -255,6 +257,8 @@ public final class DefaultMediaSourceFactoryTest { DefaultMediaSourceFactory defaultMediaSourceFactory = new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()) .setLiveTargetOffsetMs(20) + .setLiveMinOffsetMs(2222) + .setLiveMaxOffsetMs(4444) .setLiveMinSpeed(.1f) .setLiveMaxSpeed(2.0f); MediaItem mediaItem = new MediaItem.Builder().setUri(URI_MEDIA + "/file.mp4").build(); @@ -263,6 +267,8 @@ public final class DefaultMediaSourceFactoryTest { MediaItem mediaItemFromSource = mediaSource.getMediaItem(); assertThat(mediaItemFromSource.liveConfiguration.targetLiveOffsetMs).isEqualTo(20); + assertThat(mediaItemFromSource.liveConfiguration.minLiveOffsetMs).isEqualTo(2222); + assertThat(mediaItemFromSource.liveConfiguration.maxLiveOffsetMs).isEqualTo(4444); assertThat(mediaItemFromSource.liveConfiguration.minPlaybackSpeed).isEqualTo(.1f); assertThat(mediaItemFromSource.liveConfiguration.maxPlaybackSpeed).isEqualTo(2.0f); } @@ -272,12 +278,16 @@ public final class DefaultMediaSourceFactoryTest { DefaultMediaSourceFactory defaultMediaSourceFactory = new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext()) .setLiveTargetOffsetMs(20) + .setLiveMinOffsetMs(2222) + .setLiveMinOffsetMs(4444) .setLiveMinSpeed(.1f) .setLiveMaxSpeed(2.0f); MediaItem mediaItem = new MediaItem.Builder() .setUri(URI_MEDIA + "/file.mp4") .setLiveTargetOffsetMs(10) + .setLiveMinOffsetMs(1111) + .setLiveMinOffsetMs(3333) .setLiveMinPlaybackSpeed(20.0f) .setLiveMaxPlaybackSpeed(20.0f) .build();