Skip to content

Commit f2dd3d9

Browse files
authored
[video_player] Add setClosedCaptionFile method to VideoPlayerController (flutter-team-archive#5105)
1 parent 755fb82 commit f2dd3d9

4 files changed

Lines changed: 77 additions & 19 deletions

File tree

packages/video_player/video_player/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
## NEXT
1+
## 2.4.0
22

33
* Updates minimum Flutter version to 2.10.
44
* Adds OS version support information to README.
5+
* Adds `setClosedCaptionFile` method to `VideoPlayerController`.
56

67
## 2.3.0
78

packages/video_player/video_player/lib/video_player.dart

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,11 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
207207
/// null. The [package] argument must be non-null when the asset comes from a
208208
/// package and null otherwise.
209209
VideoPlayerController.asset(this.dataSource,
210-
{this.package, this.closedCaptionFile, this.videoPlayerOptions})
211-
: dataSourceType = DataSourceType.asset,
210+
{this.package,
211+
Future<ClosedCaptionFile>? closedCaptionFile,
212+
this.videoPlayerOptions})
213+
: _closedCaptionFileFuture = closedCaptionFile,
214+
dataSourceType = DataSourceType.asset,
212215
formatHint = null,
213216
httpHeaders = const <String, String>{},
214217
super(VideoPlayerValue(duration: Duration.zero));
@@ -225,10 +228,11 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
225228
VideoPlayerController.network(
226229
this.dataSource, {
227230
this.formatHint,
228-
this.closedCaptionFile,
231+
Future<ClosedCaptionFile>? closedCaptionFile,
229232
this.videoPlayerOptions,
230233
this.httpHeaders = const <String, String>{},
231-
}) : dataSourceType = DataSourceType.network,
234+
}) : _closedCaptionFileFuture = closedCaptionFile,
235+
dataSourceType = DataSourceType.network,
232236
package = null,
233237
super(VideoPlayerValue(duration: Duration.zero));
234238

@@ -237,8 +241,9 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
237241
/// This will load the file from the file-URI given by:
238242
/// `'file://${file.path}'`.
239243
VideoPlayerController.file(File file,
240-
{this.closedCaptionFile, this.videoPlayerOptions})
241-
: dataSource = 'file://${file.path}',
244+
{Future<ClosedCaptionFile>? closedCaptionFile, this.videoPlayerOptions})
245+
: _closedCaptionFileFuture = closedCaptionFile,
246+
dataSource = 'file://${file.path}',
242247
dataSourceType = DataSourceType.file,
243248
package = null,
244249
formatHint = null,
@@ -250,9 +255,10 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
250255
/// This will load the video from the input content-URI.
251256
/// This is supported on Android only.
252257
VideoPlayerController.contentUri(Uri contentUri,
253-
{this.closedCaptionFile, this.videoPlayerOptions})
258+
{Future<ClosedCaptionFile>? closedCaptionFile, this.videoPlayerOptions})
254259
: assert(defaultTargetPlatform == TargetPlatform.android,
255260
'VideoPlayerController.contentUri is only supported on Android.'),
261+
_closedCaptionFileFuture = closedCaptionFile,
256262
dataSource = contentUri.toString(),
257263
dataSourceType = DataSourceType.contentUri,
258264
package = null,
@@ -283,13 +289,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
283289
/// Only set for [asset] videos. The package that the asset was loaded from.
284290
final String? package;
285291

286-
/// Optional field to specify a file containing the closed
287-
/// captioning.
288-
///
289-
/// This future will be awaited and the file will be loaded when
290-
/// [initialize()] is called.
291-
final Future<ClosedCaptionFile>? closedCaptionFile;
292-
292+
Future<ClosedCaptionFile>? _closedCaptionFileFuture;
293293
ClosedCaptionFile? _closedCaptionFile;
294294
Timer? _timer;
295295
bool _isDisposed = false;
@@ -397,9 +397,8 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
397397
}
398398
}
399399

400-
if (closedCaptionFile != null) {
401-
_closedCaptionFile ??= await closedCaptionFile;
402-
value = value.copyWith(caption: _getCaptionAt(value.position));
400+
if (_closedCaptionFileFuture != null) {
401+
await _updateClosedCaptionWithFuture(_closedCaptionFileFuture);
403402
}
404403

405404
void errorListener(Object obj) {
@@ -634,6 +633,28 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
634633
return Caption.none;
635634
}
636635

636+
/// Returns the file containing closed captions for the video, if any.
637+
Future<ClosedCaptionFile>? get closedCaptionFile {
638+
return _closedCaptionFileFuture;
639+
}
640+
641+
/// Sets a closed caption file.
642+
///
643+
/// If [closedCaptionFile] is null, closed captions will be removed.
644+
Future<void> setClosedCaptionFile(
645+
Future<ClosedCaptionFile>? closedCaptionFile,
646+
) async {
647+
await _updateClosedCaptionWithFuture(closedCaptionFile);
648+
_closedCaptionFileFuture = closedCaptionFile;
649+
}
650+
651+
Future<void> _updateClosedCaptionWithFuture(
652+
Future<ClosedCaptionFile>? closedCaptionFile,
653+
) async {
654+
_closedCaptionFile = await closedCaptionFile;
655+
value = value.copyWith(caption: _getCaptionAt(value.position));
656+
}
657+
637658
void _updatePosition(Duration position) {
638659
value = value.copyWith(
639660
position: position,

packages/video_player/video_player/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for displaying inline video with other Flutter
33
widgets on Android, iOS, and web.
44
repository: https://github.com/flutter/plugins/tree/main/packages/video_player/video_player
55
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22
6-
version: 2.3.0
6+
version: 2.4.0
77

88
environment:
99
sdk: ">=2.14.0 <3.0.0"

packages/video_player/video_player/test/video_player_test.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
7272

7373
@override
7474
void setCaptionOffset(Duration delay) {}
75+
76+
@override
77+
Future<void> setClosedCaptionFile(
78+
Future<ClosedCaptionFile>? closedCaptionFile,
79+
) async {}
7580
}
7681

7782
Future<ClosedCaptionFile> _loadClosedCaption() async =>
@@ -672,6 +677,37 @@ void main() {
672677
await controller.seekTo(const Duration(milliseconds: 300));
673678
expect(controller.value.caption.text, 'one');
674679
});
680+
681+
test('setClosedCapitonFile loads caption file', () async {
682+
final VideoPlayerController controller = VideoPlayerController.network(
683+
'https://127.0.0.1',
684+
);
685+
686+
await controller.initialize();
687+
expect(controller.closedCaptionFile, null);
688+
689+
await controller.setClosedCaptionFile(_loadClosedCaption());
690+
expect(
691+
(await controller.closedCaptionFile)!.captions,
692+
(await _loadClosedCaption()).captions,
693+
);
694+
});
695+
696+
test('setClosedCapitonFile removes/changes caption file', () async {
697+
final VideoPlayerController controller = VideoPlayerController.network(
698+
'https://127.0.0.1',
699+
closedCaptionFile: _loadClosedCaption(),
700+
);
701+
702+
await controller.initialize();
703+
expect(
704+
(await controller.closedCaptionFile)!.captions,
705+
(await _loadClosedCaption()).captions,
706+
);
707+
708+
await controller.setClosedCaptionFile(null);
709+
expect(controller.closedCaptionFile, null);
710+
});
675711
});
676712

677713
group('Platform callbacks', () {

0 commit comments

Comments
 (0)