[video_player] Add audio track management support to platform interface (#10171)
## Description
platform interface pr for #9925
#### Core Features
- **Added `VideoAudioTrack` model** with comprehensive metadata fields: `id`, `label`, `language`, `isSelected`, `bitrate`, `sampleRate`, `channelCount`, `codec`
- **Added [getAudioTracks()]() method** to retrieve all available audio tracks with real metadata
- **Added [selectAudioTrack()]() method** to switch between audio tracks during playback
### Breaking Changes
None - all changes are additive and backward compatible.
## Pre-Review Checklist
diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md
index 024cca4..6d7fd75 100644
--- a/packages/video_player/video_player_platform_interface/CHANGELOG.md
+++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 6.6.0
+
+* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods for audio track management.
+
## 6.5.0
* Adds a `setAllowBackgroundPlayback` method to dynamically control background playback.
diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart
index 1037e55..6525d3b 100644
--- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart
+++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart
@@ -128,6 +128,31 @@
Future<void> setWebOptions(int playerId, VideoPlayerWebOptions options) {
throw UnimplementedError('setWebOptions() has not been implemented.');
}
+
+ /// Gets the available audio tracks for the video.
+ Future<List<VideoAudioTrack>> getAudioTracks(int playerId) {
+ throw UnimplementedError('getAudioTracks() has not been implemented.');
+ }
+
+ /// Selects which audio track is chosen for playback from its [trackId]
+ Future<void> selectAudioTrack(int playerId, String trackId) {
+ throw UnimplementedError('selectAudioTrack() has not been implemented.');
+ }
+
+ /// Returns whether audio track selection is supported on this platform.
+ ///
+ /// This method allows developers to query at runtime whether the current
+ /// platform supports audio track selection functionality. This is useful
+ /// for platforms like web where audio track selection may not be available.
+ ///
+ /// Returns `true` if [getAudioTracks] and [selectAudioTrack] are supported,
+ /// `false` otherwise.
+ ///
+ /// The default implementation returns `false`. Platform implementations
+ /// should override this to return `true` if they support audio track selection.
+ bool isAudioTrackSupportAvailable() {
+ return false;
+ }
}
class _PlaceholderImplementation extends VideoPlayerPlatform {}
@@ -536,3 +561,94 @@
/// The type of view to be used for displaying the video player
final VideoViewType viewType;
}
+
+/// Represents an audio track in a video with its metadata.
+@immutable
+class VideoAudioTrack {
+ /// Constructs an instance of [VideoAudioTrack].
+ const VideoAudioTrack({
+ required this.id,
+ required this.label,
+ required this.language,
+ required this.isSelected,
+ this.bitrate,
+ this.sampleRate,
+ this.channelCount,
+ this.codec,
+ });
+
+ /// Unique identifier for the audio track.
+ final String id;
+
+ /// Human-readable label for the track.
+ ///
+ /// May be null if not available from the platform.
+ final String? label;
+
+ /// Language code of the audio track (e.g., 'en', 'es', 'und').
+ ///
+ /// May be null if not available from the platform.
+ final String? language;
+
+ /// Whether this track is currently selected.
+ final bool isSelected;
+
+ /// Bitrate of the audio track in bits per second.
+ ///
+ /// May be null if not available from the platform.
+ final int? bitrate;
+
+ /// Sample rate of the audio track in Hz.
+ ///
+ /// May be null if not available from the platform.
+ final int? sampleRate;
+
+ /// Number of audio channels.
+ ///
+ /// May be null if not available from the platform.
+ final int? channelCount;
+
+ /// Audio codec used (e.g., 'aac', 'mp3', 'ac3').
+ ///
+ /// May be null if not available from the platform.
+ final String? codec;
+
+ @override
+ bool operator ==(Object other) {
+ return identical(this, other) ||
+ other is VideoAudioTrack &&
+ runtimeType == other.runtimeType &&
+ id == other.id &&
+ label == other.label &&
+ language == other.language &&
+ isSelected == other.isSelected &&
+ bitrate == other.bitrate &&
+ sampleRate == other.sampleRate &&
+ channelCount == other.channelCount &&
+ codec == other.codec;
+ }
+
+ @override
+ int get hashCode => Object.hash(
+ id,
+ label,
+ language,
+ isSelected,
+ bitrate,
+ sampleRate,
+ channelCount,
+ codec,
+ );
+
+ @override
+ String toString() =>
+ 'VideoAudioTrack('
+ 'id: $id, '
+ 'label: $label, '
+ 'language: $language, '
+ 'isSelected: $isSelected, '
+ 'bitrate: $bitrate, '
+ 'sampleRate: $sampleRate, '
+ 'channelCount: $channelCount, '
+ 'codec: $codec)';
+}
diff --git a/packages/video_player/video_player_platform_interface/pubspec.yaml b/packages/video_player/video_player_platform_interface/pubspec.yaml
index 2c53743..d310fee 100644
--- a/packages/video_player/video_player_platform_interface/pubspec.yaml
+++ b/packages/video_player/video_player_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 6.5.0
+version: 6.6.0
environment:
sdk: ^3.7.0
diff --git a/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart b/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart
index ad5938a..2d92016 100644
--- a/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart
+++ b/packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart
@@ -19,4 +19,25 @@
throwsUnimplementedError,
);
});
+
+ test('default implementation getAudioTracks throws unimplemented', () async {
+ await expectLater(
+ () => initialInstance.getAudioTracks(1),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
+ 'default implementation selectAudioTrack throws unimplemented',
+ () async {
+ await expectLater(
+ () => initialInstance.selectAudioTrack(1, 'trackId'),
+ throwsUnimplementedError,
+ );
+ },
+ );
+
+ test('default implementation isAudioTrackSupportAvailable returns false', () {
+ expect(initialInstance.isAudioTrackSupportAvailable(), false);
+ });
}