Skip to content

Commit 9905c4a

Browse files
authored
[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
1 parent bbf96a0 commit 9905c4a

File tree

4 files changed

+142
-1
lines changed

4 files changed

+142
-1
lines changed

packages/video_player/video_player_platform_interface/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 6.6.0
2+
3+
* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods for audio track management.
4+
15
## 6.5.0
26

37
* Adds a `setAllowBackgroundPlayback` method to dynamically control background playback.

packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,31 @@ abstract class VideoPlayerPlatform extends PlatformInterface {
128128
Future<void> setWebOptions(int playerId, VideoPlayerWebOptions options) {
129129
throw UnimplementedError('setWebOptions() has not been implemented.');
130130
}
131+
132+
/// Gets the available audio tracks for the video.
133+
Future<List<VideoAudioTrack>> getAudioTracks(int playerId) {
134+
throw UnimplementedError('getAudioTracks() has not been implemented.');
135+
}
136+
137+
/// Selects which audio track is chosen for playback from its [trackId]
138+
Future<void> selectAudioTrack(int playerId, String trackId) {
139+
throw UnimplementedError('selectAudioTrack() has not been implemented.');
140+
}
141+
142+
/// Returns whether audio track selection is supported on this platform.
143+
///
144+
/// This method allows developers to query at runtime whether the current
145+
/// platform supports audio track selection functionality. This is useful
146+
/// for platforms like web where audio track selection may not be available.
147+
///
148+
/// Returns `true` if [getAudioTracks] and [selectAudioTrack] are supported,
149+
/// `false` otherwise.
150+
///
151+
/// The default implementation returns `false`. Platform implementations
152+
/// should override this to return `true` if they support audio track selection.
153+
bool isAudioTrackSupportAvailable() {
154+
return false;
155+
}
131156
}
132157

133158
class _PlaceholderImplementation extends VideoPlayerPlatform {}
@@ -536,3 +561,94 @@ class VideoCreationOptions {
536561
/// The type of view to be used for displaying the video player
537562
final VideoViewType viewType;
538563
}
564+
565+
/// Represents an audio track in a video with its metadata.
566+
@immutable
567+
class VideoAudioTrack {
568+
/// Constructs an instance of [VideoAudioTrack].
569+
const VideoAudioTrack({
570+
required this.id,
571+
required this.label,
572+
required this.language,
573+
required this.isSelected,
574+
this.bitrate,
575+
this.sampleRate,
576+
this.channelCount,
577+
this.codec,
578+
});
579+
580+
/// Unique identifier for the audio track.
581+
final String id;
582+
583+
/// Human-readable label for the track.
584+
///
585+
/// May be null if not available from the platform.
586+
final String? label;
587+
588+
/// Language code of the audio track (e.g., 'en', 'es', 'und').
589+
///
590+
/// May be null if not available from the platform.
591+
final String? language;
592+
593+
/// Whether this track is currently selected.
594+
final bool isSelected;
595+
596+
/// Bitrate of the audio track in bits per second.
597+
///
598+
/// May be null if not available from the platform.
599+
final int? bitrate;
600+
601+
/// Sample rate of the audio track in Hz.
602+
///
603+
/// May be null if not available from the platform.
604+
final int? sampleRate;
605+
606+
/// Number of audio channels.
607+
///
608+
/// May be null if not available from the platform.
609+
final int? channelCount;
610+
611+
/// Audio codec used (e.g., 'aac', 'mp3', 'ac3').
612+
///
613+
/// May be null if not available from the platform.
614+
final String? codec;
615+
616+
@override
617+
bool operator ==(Object other) {
618+
return identical(this, other) ||
619+
other is VideoAudioTrack &&
620+
runtimeType == other.runtimeType &&
621+
id == other.id &&
622+
label == other.label &&
623+
language == other.language &&
624+
isSelected == other.isSelected &&
625+
bitrate == other.bitrate &&
626+
sampleRate == other.sampleRate &&
627+
channelCount == other.channelCount &&
628+
codec == other.codec;
629+
}
630+
631+
@override
632+
int get hashCode => Object.hash(
633+
id,
634+
label,
635+
language,
636+
isSelected,
637+
bitrate,
638+
sampleRate,
639+
channelCount,
640+
codec,
641+
);
642+
643+
@override
644+
String toString() =>
645+
'VideoAudioTrack('
646+
'id: $id, '
647+
'label: $label, '
648+
'language: $language, '
649+
'isSelected: $isSelected, '
650+
'bitrate: $bitrate, '
651+
'sampleRate: $sampleRate, '
652+
'channelCount: $channelCount, '
653+
'codec: $codec)';
654+
}

packages/video_player/video_player_platform_interface/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/video_player/
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
55
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
66
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
7-
version: 6.5.0
7+
version: 6.6.0
88

99
environment:
1010
sdk: ^3.7.0

packages/video_player/video_player_platform_interface/test/video_player_platform_interface_test.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,25 @@ void main() {
1919
throwsUnimplementedError,
2020
);
2121
});
22+
23+
test('default implementation getAudioTracks throws unimplemented', () async {
24+
await expectLater(
25+
() => initialInstance.getAudioTracks(1),
26+
throwsUnimplementedError,
27+
);
28+
});
29+
30+
test(
31+
'default implementation selectAudioTrack throws unimplemented',
32+
() async {
33+
await expectLater(
34+
() => initialInstance.selectAudioTrack(1, 'trackId'),
35+
throwsUnimplementedError,
36+
);
37+
},
38+
);
39+
40+
test('default implementation isAudioTrackSupportAvailable returns false', () {
41+
expect(initialInstance.isAudioTrackSupportAvailable(), false);
42+
});
2243
}

0 commit comments

Comments
 (0)