[video_player] Add setClosedCaptionFile method to VideoPlayerController (#5105)
diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md
index d9d1983..363546c 100644
--- a/packages/video_player/video_player/CHANGELOG.md
+++ b/packages/video_player/video_player/CHANGELOG.md
@@ -1,7 +1,8 @@
-## NEXT
+## 2.4.0
* Updates minimum Flutter version to 2.10.
* Adds OS version support information to README.
+* Adds `setClosedCaptionFile` method to `VideoPlayerController`.
## 2.3.0
diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart
index b77c530..39cd415 100644
--- a/packages/video_player/video_player/lib/video_player.dart
+++ b/packages/video_player/video_player/lib/video_player.dart
@@ -207,8 +207,11 @@
/// null. The [package] argument must be non-null when the asset comes from a
/// package and null otherwise.
VideoPlayerController.asset(this.dataSource,
- {this.package, this.closedCaptionFile, this.videoPlayerOptions})
- : dataSourceType = DataSourceType.asset,
+ {this.package,
+ Future<ClosedCaptionFile>? closedCaptionFile,
+ this.videoPlayerOptions})
+ : _closedCaptionFileFuture = closedCaptionFile,
+ dataSourceType = DataSourceType.asset,
formatHint = null,
httpHeaders = const <String, String>{},
super(VideoPlayerValue(duration: Duration.zero));
@@ -225,10 +228,11 @@
VideoPlayerController.network(
this.dataSource, {
this.formatHint,
- this.closedCaptionFile,
+ Future<ClosedCaptionFile>? closedCaptionFile,
this.videoPlayerOptions,
this.httpHeaders = const <String, String>{},
- }) : dataSourceType = DataSourceType.network,
+ }) : _closedCaptionFileFuture = closedCaptionFile,
+ dataSourceType = DataSourceType.network,
package = null,
super(VideoPlayerValue(duration: Duration.zero));
@@ -237,8 +241,9 @@
/// This will load the file from the file-URI given by:
/// `'file://${file.path}'`.
VideoPlayerController.file(File file,
- {this.closedCaptionFile, this.videoPlayerOptions})
- : dataSource = 'file://${file.path}',
+ {Future<ClosedCaptionFile>? closedCaptionFile, this.videoPlayerOptions})
+ : _closedCaptionFileFuture = closedCaptionFile,
+ dataSource = 'file://${file.path}',
dataSourceType = DataSourceType.file,
package = null,
formatHint = null,
@@ -250,9 +255,10 @@
/// This will load the video from the input content-URI.
/// This is supported on Android only.
VideoPlayerController.contentUri(Uri contentUri,
- {this.closedCaptionFile, this.videoPlayerOptions})
+ {Future<ClosedCaptionFile>? closedCaptionFile, this.videoPlayerOptions})
: assert(defaultTargetPlatform == TargetPlatform.android,
'VideoPlayerController.contentUri is only supported on Android.'),
+ _closedCaptionFileFuture = closedCaptionFile,
dataSource = contentUri.toString(),
dataSourceType = DataSourceType.contentUri,
package = null,
@@ -283,13 +289,7 @@
/// Only set for [asset] videos. The package that the asset was loaded from.
final String? package;
- /// Optional field to specify a file containing the closed
- /// captioning.
- ///
- /// This future will be awaited and the file will be loaded when
- /// [initialize()] is called.
- final Future<ClosedCaptionFile>? closedCaptionFile;
-
+ Future<ClosedCaptionFile>? _closedCaptionFileFuture;
ClosedCaptionFile? _closedCaptionFile;
Timer? _timer;
bool _isDisposed = false;
@@ -397,9 +397,8 @@
}
}
- if (closedCaptionFile != null) {
- _closedCaptionFile ??= await closedCaptionFile;
- value = value.copyWith(caption: _getCaptionAt(value.position));
+ if (_closedCaptionFileFuture != null) {
+ await _updateClosedCaptionWithFuture(_closedCaptionFileFuture);
}
void errorListener(Object obj) {
@@ -634,6 +633,28 @@
return Caption.none;
}
+ /// Returns the file containing closed captions for the video, if any.
+ Future<ClosedCaptionFile>? get closedCaptionFile {
+ return _closedCaptionFileFuture;
+ }
+
+ /// Sets a closed caption file.
+ ///
+ /// If [closedCaptionFile] is null, closed captions will be removed.
+ Future<void> setClosedCaptionFile(
+ Future<ClosedCaptionFile>? closedCaptionFile,
+ ) async {
+ await _updateClosedCaptionWithFuture(closedCaptionFile);
+ _closedCaptionFileFuture = closedCaptionFile;
+ }
+
+ Future<void> _updateClosedCaptionWithFuture(
+ Future<ClosedCaptionFile>? closedCaptionFile,
+ ) async {
+ _closedCaptionFile = await closedCaptionFile;
+ value = value.copyWith(caption: _getCaptionAt(value.position));
+ }
+
void _updatePosition(Duration position) {
value = value.copyWith(
position: position,
diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml
index 88e45c5..0d654a4 100644
--- a/packages/video_player/video_player/pubspec.yaml
+++ b/packages/video_player/video_player/pubspec.yaml
@@ -3,7 +3,7 @@
widgets on Android, iOS, and web.
repository: https://github.com/flutter/plugins/tree/main/packages/video_player/video_player
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
-version: 2.3.0
+version: 2.4.0
environment:
sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart
index 5e31e22..6411333 100644
--- a/packages/video_player/video_player/test/video_player_test.dart
+++ b/packages/video_player/video_player/test/video_player_test.dart
@@ -72,6 +72,11 @@
@override
void setCaptionOffset(Duration delay) {}
+
+ @override
+ Future<void> setClosedCaptionFile(
+ Future<ClosedCaptionFile>? closedCaptionFile,
+ ) async {}
}
Future<ClosedCaptionFile> _loadClosedCaption() async =>
@@ -672,6 +677,37 @@
await controller.seekTo(const Duration(milliseconds: 300));
expect(controller.value.caption.text, 'one');
});
+
+ test('setClosedCapitonFile loads caption file', () async {
+ final VideoPlayerController controller = VideoPlayerController.network(
+ 'https://127.0.0.1',
+ );
+
+ await controller.initialize();
+ expect(controller.closedCaptionFile, null);
+
+ await controller.setClosedCaptionFile(_loadClosedCaption());
+ expect(
+ (await controller.closedCaptionFile)!.captions,
+ (await _loadClosedCaption()).captions,
+ );
+ });
+
+ test('setClosedCapitonFile removes/changes caption file', () async {
+ final VideoPlayerController controller = VideoPlayerController.network(
+ 'https://127.0.0.1',
+ closedCaptionFile: _loadClosedCaption(),
+ );
+
+ await controller.initialize();
+ expect(
+ (await controller.closedCaptionFile)!.captions,
+ (await _loadClosedCaption()).captions,
+ );
+
+ await controller.setClosedCaptionFile(null);
+ expect(controller.closedCaptionFile, null);
+ });
});
group('Platform callbacks', () {