Skip to content

Conversation

@nateshmbhat
Copy link
Contributor

@nateshmbhat nateshmbhat commented Dec 27, 2025

This PR adds video track selection (quality switching) support to the video_player plugin for Android and iOS platforms. This allows users to programmatically get available video quality variants and select a specific quality track, similar to the existing audio track selection feature.

Addresses issue : flutter/flutter#58854

Pre-Review Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] page, which explains my responsibilities.
  • I read and followed the [relevant style guides] and ran [the auto-formatter].
  • I signed the [CLA].
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I [linked to at least one issue that this PR fixes] in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the [pub versioning philosophy], or I have commented below to indicate which [version change exemption] this PR falls under[^1].
  • I updated CHANGELOG.md to add a description of the change, [following repository CHANGELOG style], or I have commented below to indicate which [CHANGELOG exemption] this PR falls under[^1].
  • I updated/added any relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or I have commented below to indicate which [test exemption] this PR falls under[^1].
  • All existing and new tests are passing.

Copy link

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

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 introduces video track (quality) selection support for Android and iOS in the video_player plugin. It adds getVideoTracks, selectVideoTrack, and isVideoTrackSupportAvailable methods to the VideoPlayerController and the platform interface. The Android implementation leverages ExoPlayer's track selection, including a workaround for resolution changes, while the iOS implementation uses AVAssetVariant for iOS 15+ and preferredPeakBitRate. The web platform includes stub implementations since the feature is not supported there. The changes are well-structured, with corresponding updates to the example app and comprehensive tests. I have one suggestion to improve the example app's robustness by avoiding the use of BuildContext across asynchronous gaps.

Comment on lines 122 to 153
Future<void> _selectVideoTrack(VideoTrack? track) async {
final VideoPlayerController? controller = _controller;
if (controller == null) {
return;
}

try {
await controller.selectVideoTrack(track);

setState(() {
_isAutoQuality = track == null;
});

// Reload tracks to update selection status
await _loadVideoTracks();

if (!mounted) {
return;
}
final String message = track == null
? 'Switched to automatic quality'
: 'Selected video track: ${_getTrackLabel(track)}';
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
} catch (e) {
if (!mounted) {
return;
}
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Failed to select video track: $e')));
}
}

Choose a reason for hiding this comment

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

medium

Avoid using BuildContext across asynchronous gaps. The context might be invalid after an await. It's safer to get a reference to ScaffoldMessenger before the async calls.

  Future<void> _selectVideoTrack(VideoTrack? track) async {
    final VideoPlayerController? controller = _controller;
    if (controller == null) {
      return;
    }
    final ScaffoldMessengerState scaffoldMessenger = ScaffoldMessenger.of(context);

    try {
      await controller.selectVideoTrack(track);

      setState(() {
        _isAutoQuality = track == null;
      });

      // Reload tracks to update selection status
      await _loadVideoTracks();

      if (!mounted) {
        return;
      }
      final String message = track == null
          ? 'Switched to automatic quality'
          : 'Selected video track: ${_getTrackLabel(track)}';
      scaffoldMessenger.showSnackBar(SnackBar(content: Text(message)));
    } catch (e) {
      if (!mounted) {
        return;
      }
      scaffoldMessenger
          .showSnackBar(SnackBar(content: Text('Failed to select video track: $e')));
    }
  }

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