Skip to content

[video_player] Add forwardBufferDuration to cap network read-ahead#11950

Open
mhmdfathy96 wants to merge 4 commits into
flutter:mainfrom
mhmdfathy96:video_player_forward_buffer_duration
Open

[video_player] Add forwardBufferDuration to cap network read-ahead#11950
mhmdfathy96 wants to merge 4 commits into
flutter:mainfrom
mhmdfathy96:video_player_forward_buffer_duration

Conversation

@mhmdfathy96

@mhmdfathy96 mhmdfathy96 commented Jun 21, 2026

Copy link
Copy Markdown

Description

Adds an optional VideoPlayerOptions.forwardBufferDuration so apps can cap how
far ahead of the playhead the player buffers from the network.

Today buffering is fully automatic and aggressive — ExoPlayer's DefaultLoadControl
buffers ~50s, and AVPlayer can prefetch most of a short file on iOS. That wastes
bandwidth whenever a user abandons a video or seeks away. This has been requested
for years without an implementation:

VideoPlayerController.networkUrl(
  uri,
  videoPlayerOptions: VideoPlayerOptions(
    forwardBufferDuration: const Duration(seconds: 10), // null = unchanged default
  ),
);

The option is threaded through VideoCreationOptions and the pigeon
CreationOptions to the engines:

  • Android → ExoPlayer DefaultLoadControl (VideoPlayer.cappedLoadControl,
    with playback-start thresholds clamped to the cap).
  • iOS/macOSAVPlayerItem.preferredForwardBufferDuration (exposed via the
    FVPAVPlayerItem test abstraction).

null preserves current behavior on every platform.

Tests

  • Dart: umbrella forwards the option into VideoCreationOptions; android &
    avfoundation pass forwardBufferDurationMs and default to null.
  • Android native (Robolectric): cappedLoadControl null/non-null + small-cap
    threshold clamping.
  • iOS native (swift-testing): the value is applied to the player item and left
    untouched when null.

All pass locally.

Pre-Review Checklist

  • I signed the CLA.
  • Unit tests (Dart + Android + iOS) added and passing locally.
  • Added/updated CHANGELOG and version bumps for all four packages.
  • Listed issues fixed above.
  • Generated Dart regenerated with dart run pigeon (android 26.1.5,
    avfoundation 26.3.4 — each matching its committed header) + dart format
    at page width 100. Kotlin/Swift generated files have only the single added
    field in the existing ktfmt/swift-format style.

Adds an optional VideoPlayerOptions.forwardBufferDuration so apps can limit
how far ahead of the playhead the player buffers from the network. Upstream
defaults to aggressive read-ahead (ExoPlayer ~50s; AVPlayer may fetch most of
the file), which wastes bandwidth when a user abandons or seeks away. Requested
in flutter/flutter#40931, #141511, #163918.

null preserves current behavior. Threaded through VideoCreationOptions and the
pigeon CreationOptions to:
- Android: ExoPlayer DefaultLoadControl (VideoPlayer.cappedLoadControl, clamped
  playback-start thresholds).
- iOS/macOS: AVPlayerItem.preferredForwardBufferDuration.
@google-cla

google-cla Bot commented Jun 21, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

- Dart: umbrella passes the option into VideoCreationOptions; android &
  avfoundation pass forwardBufferDurationMs (and default to null).
- Android native: VideoPlayer.cappedLoadControl null/non-null + threshold
  clamping; fixes existing VideoPlayerPluginTest for the new create() arity.
- iOS native: forwardBufferDuration applied to the player item / left untouched
  when null.

Also exposes preferredForwardBufferDuration on the FVPAVPlayerItem abstraction
(protocol + default impl) so the Swift plugin can set it and tests can verify it.
@mhmdfathy96 mhmdfathy96 marked this pull request as ready for review June 21, 2026 06:09

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for a new forwardBufferDuration option to VideoPlayerOptions and VideoCreationOptions across the video_player packages, allowing users to cap network buffering. The implementation spans the platform interface, Android (ExoPlayer), and iOS/macOS (AVFoundation) implementations, along with corresponding tests. Feedback suggests adding non-negative assertions to the Dart constructors, clamping the duration on Android to prevent integer overflow, and clamping it on iOS/macOS to prevent potential crashes from negative values.

Replaces the hand-edited generated Dart with proper `dart run pigeon` output
(android: pigeon 26.1.5, avfoundation: 26.3.4 — matching each package's committed
header) formatted at the repo's page width 100, so the generated-code CI check
matches. Native generated files (Messages.kt / VideoPlayerPluginMessages.g.swift)
are unchanged; their single added field already matches ktfmt/swift-format style.
… values

- platform_interface: assert forwardBufferDuration is non-negative in
  VideoPlayerOptions (the user-facing entry point).
- Android: clamp to Integer.MAX_VALUE before the int cast in cappedLoadControl.
- iOS/macOS: clamp preferredForwardBufferDuration to >= 0 (a negative value
  raises an exception per Apple's docs).

VideoCreationOptions keeps its const constructor (an isNegative assert isn't
const-evaluable); it's only built internally from an already-validated
VideoPlayerOptions.
@mhmdfathy96

Copy link
Copy Markdown
Author

Thanks for the review! Addressed in bdc6655:

  • iOS negative clamp (high): preferredForwardBufferDuration is now max(0.0, …) to avoid the exception on negative values.
  • Android overflow: cappedLoadControl clamps to Integer.MAX_VALUE before the int cast.
  • VideoPlayerOptions assert: added the non-negative assertion on the user-facing constructor.
  • VideoCreationOptions assert: not added — that constructor is const, and Duration.isNegative isn't a const expression. It's only built internally from an already-validated VideoPlayerOptions, so the user-facing assert above covers it.

@mhmdfathy96 mhmdfathy96 force-pushed the video_player_forward_buffer_duration branch from bdc6655 to fd7120c Compare June 21, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant