Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.6.0

* Adds `VideoAudioTrack` class and `getAudioTracks()`, `selectAudioTrack()`, `isAudioTrackSupportAvailable()` methods to platform interface for audio track management.

## 6.5.0

* Adds a `setAllowBackgroundPlayback` method to dynamically control background playback.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,30 @@ abstract class VideoPlayerPlatform extends PlatformInterface {
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 an audio track by its ID.
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.
Future<bool> isAudioTrackSupportAvailable() {
throw UnimplementedError(
'isAudioTrackSupportAvailable() has not been implemented.',
);
}
}

class _PlaceholderImplementation extends VideoPlayerPlatform {}
Expand Down Expand Up @@ -536,3 +560,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)';
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
});
}