From 6b0de5f15e35868c61212eaf54fd9a582168e63b Mon Sep 17 00:00:00 2001 From: nateshmbhat Date: Sat, 4 Oct 2025 13:17:49 +0530 Subject: [PATCH 1/5] feat(video_player): add audio track management support to platform interface --- .../CHANGELOG.md | 3 +- .../lib/video_player_platform_interface.dart | 107 ++++++++++++++++++ .../pubspec.yaml | 2 +- 3 files changed, 110 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index b6f5a93013f..f536e72b13d 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 6.5.0 +* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()` methods to platform interface for audio track management. * Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. ## 6.4.0 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 801de5ad816..964309267fb 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 @@ -121,6 +121,30 @@ abstract class VideoPlayerPlatform extends PlatformInterface { Future setWebOptions(int playerId, VideoPlayerWebOptions options) { throw UnimplementedError('setWebOptions() has not been implemented.'); } + + /// Gets the available audio tracks for the video. + Future> getAudioTracks(int playerId) { + throw UnimplementedError('getAudioTracks() has not been implemented.'); + } + + /// Selects an audio track by its ID. + Future 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. + Future isAudioTrackSupportAvailable() { + throw UnimplementedError( + 'isAudioTrackSupportAvailable() has not been implemented.', + ); + } } class _PlaceholderImplementation extends VideoPlayerPlatform {} @@ -529,3 +553,86 @@ class VideoCreationOptions { /// 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. + final String label; + + /// Language code of the audio track (e.g., 'en', 'es', 'und'). + 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 647225dd5bb..2c53743addb 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 @@ repository: https://github.com/flutter/packages/tree/main/packages/video_player/ 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.4.0 +version: 6.5.0 environment: sdk: ^3.7.0 From 12fd73f61df1611559ed9fd6856c960b47228684 Mon Sep 17 00:00:00 2001 From: Natesh Bhat Date: Mon, 13 Oct 2025 13:32:16 +0530 Subject: [PATCH 2/5] Update packages/video_player/video_player_platform_interface/CHANGELOG.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../video_player/video_player_platform_interface/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index f536e72b13d..71ffc13a0ac 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 6.5.0 -* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()` methods to platform interface for audio track management. +* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods to platform interface for audio track management. * Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. ## 6.4.0 From 680c5e6cb93376a6769a3b1dd427395b5ea41a4a Mon Sep 17 00:00:00 2001 From: nateshmbhat Date: Mon, 13 Oct 2025 13:34:14 +0530 Subject: [PATCH 3/5] feat(video_player): add isAudioTrackSupportAvailable method to platform interface --- .../CHANGELOG.md | 2 +- .../video_player_platform_interface_test.dart | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index f536e72b13d..71ffc13a0ac 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 6.5.0 -* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()` methods to platform interface for audio track management. +* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods to platform interface for audio track management. * Updates minimum supported SDK version to Flutter 3.29/Dart 3.7. ## 6.4.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 ad5938afcee..e398b82d243 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,28 @@ void main() { 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 throws unimplemented', + () async { + await expectLater( + () => initialInstance.isAudioTrackSupportAvailable(), + throwsUnimplementedError, + ); + }); } From d5d1563aa5cb55c3c0483b73c6583c664f9f6d82 Mon Sep 17 00:00:00 2001 From: nateshmbhat Date: Thu, 16 Oct 2025 22:24:32 +0530 Subject: [PATCH 4/5] refactor(video_player): make language and label nullable in VideoAudioTrack and update audio track support check --- .../lib/video_player_platform_interface.dart | 17 +++++++------ .../video_player_platform_interface_test.dart | 25 ++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) 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 1058db55eeb..226cb4f707f 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 @@ -134,7 +134,7 @@ abstract class VideoPlayerPlatform extends PlatformInterface { throw UnimplementedError('getAudioTracks() has not been implemented.'); } - /// Selects an audio track by its ID. + /// Selects which audio track is chosen for playback from its [trackId] Future selectAudioTrack(int playerId, String trackId) { throw UnimplementedError('selectAudioTrack() has not been implemented.'); } @@ -147,10 +147,11 @@ abstract class VideoPlayerPlatform extends PlatformInterface { /// /// Returns `true` if [getAudioTracks] and [selectAudioTrack] are supported, /// `false` otherwise. - Future isAudioTrackSupportAvailable() { - throw UnimplementedError( - 'isAudioTrackSupportAvailable() has not been implemented.', - ); + /// + /// The default implementation returns `false`. Platform implementations + /// should override this to return `true` if they support audio track selection. + bool isAudioTrackSupportAvailable() { + return false; } } @@ -580,10 +581,12 @@ class VideoAudioTrack { final String id; /// Human-readable label for the track. - final String label; + /// May be null if not available from the platform. + final String? label; /// Language code of the audio track (e.g., 'en', 'es', 'und'). - final String language; + /// May be null if not available from the platform. + final String? language; /// Whether this track is currently selected. final bool isSelected; 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 e398b82d243..2d920161ec9 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 @@ -27,20 +27,17 @@ void main() { ); }); - test('default implementation selectAudioTrack throws unimplemented', - () async { - await expectLater( - () => initialInstance.selectAudioTrack(1, 'trackId'), - throwsUnimplementedError, - ); - }); - test( - 'default implementation isAudioTrackSupportAvailable throws unimplemented', - () async { - await expectLater( - () => initialInstance.isAudioTrackSupportAvailable(), - throwsUnimplementedError, - ); + 'default implementation selectAudioTrack throws unimplemented', + () async { + await expectLater( + () => initialInstance.selectAudioTrack(1, 'trackId'), + throwsUnimplementedError, + ); + }, + ); + + test('default implementation isAudioTrackSupportAvailable returns false', () { + expect(initialInstance.isAudioTrackSupportAvailable(), false); }); } From 926f7841a4931e173af145e77e757884e2930f33 Mon Sep 17 00:00:00 2001 From: nateshmbhat Date: Sat, 25 Oct 2025 13:46:27 +0530 Subject: [PATCH 5/5] chore(video_player): enhance audio track documentation and changelog - Added detailed documentation comments for VideoAudioTrack properties explaining null cases - Updated CHANGELOG.md to use more concise language for audio track management features - Improved code readability by adding spacing between property documentation blocks --- .../video_player_platform_interface/CHANGELOG.md | 2 +- .../lib/video_player_platform_interface.dart | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index 234067842ef..6d7fd75aa7a 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 6.6.0 -* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods to platform interface for audio track management. +* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods for audio track management. ## 6.5.0 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 226cb4f707f..6525d3bab33 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 @@ -581,10 +581,12 @@ class VideoAudioTrack { 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; @@ -592,18 +594,22 @@ class VideoAudioTrack { 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;