Skip to content

Commit a1c3689

Browse files
[video_player]: reduce video player position update interval from 500ms to 100ms (#8346)
Description reduce video player position update interval from 500ms to 100ms to fix the issue of fast captions not showing for their intended time *List which issues are fixed by this PR. You must list at least one issue.* flutter/flutter#160855
1 parent f2e2987 commit a1c3689

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

packages/video_player/video_player/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.9.4
2+
3+
* Reduces the position update interval from 500ms to 100ms.
4+
15
## 2.9.3
26

37
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.

packages/video_player/video_player/lib/video_player.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,10 +585,9 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
585585
if (value.isPlaying) {
586586
await _videoPlayerPlatform.play(_textureId);
587587

588-
// Cancel previous timer.
589588
_timer?.cancel();
590589
_timer = Timer.periodic(
591-
const Duration(milliseconds: 500),
590+
const Duration(milliseconds: 100),
592591
(Timer timer) async {
593592
if (_isDisposed) {
594593
return;

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/packages/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.9.3
6+
version: 2.9.4
77

88
environment:
99
sdk: ^3.4.0

packages/video_player/video_player/test/video_player_test.dart

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,45 @@ void main() {
757757
});
758758

759759
group('caption', () {
760+
test('works when position updates', () async {
761+
final VideoPlayerController controller =
762+
VideoPlayerController.networkUrl(
763+
_localhostUri,
764+
closedCaptionFile: _loadClosedCaption(),
765+
);
766+
767+
await controller.initialize();
768+
await controller.play();
769+
770+
// Optionally record caption changes for later verification.
771+
final Map<int, String> recordedCaptions = <int, String>{};
772+
773+
controller.addListener(() {
774+
// Record the caption for the current position (in milliseconds).
775+
final int ms = controller.value.position.inMilliseconds;
776+
recordedCaptions[ms] = controller.value.caption.text;
777+
});
778+
779+
const Duration updateInterval = Duration(milliseconds: 100);
780+
const int totalDurationMs = 350;
781+
782+
// Simulate continuous playback by incrementing in 50ms steps.
783+
for (int ms = 0; ms <= totalDurationMs; ms += 50) {
784+
fakeVideoPlayerPlatform._positions[controller.textureId] =
785+
Duration(milliseconds: ms);
786+
await Future<void>.delayed(updateInterval);
787+
}
788+
789+
// Now, given your closed caption file and the 100ms update interval,
790+
// you expect:
791+
// • at 100ms: caption should be 'one'
792+
// • at 250ms: no caption (i.e. '')
793+
// • at 300ms: caption should be 'two'
794+
expect(recordedCaptions[100], 'one');
795+
expect(recordedCaptions[250], '');
796+
expect(recordedCaptions[300], 'two');
797+
});
798+
760799
test('works when seeking', () async {
761800
final VideoPlayerController controller =
762801
VideoPlayerController.networkUrl(
@@ -995,6 +1034,41 @@ void main() {
9951034
});
9961035
});
9971036

1037+
test('updates position', () async {
1038+
final VideoPlayerController controller = VideoPlayerController.networkUrl(
1039+
_localhostUri,
1040+
videoPlayerOptions: VideoPlayerOptions(),
1041+
);
1042+
1043+
await controller.initialize();
1044+
1045+
const Duration updatesInterval = Duration(milliseconds: 100);
1046+
1047+
final List<Duration> positions = <Duration>[];
1048+
final Completer<void> intervalUpdateCompleter = Completer<void>();
1049+
1050+
// Listen for position updates
1051+
controller.addListener(() {
1052+
positions.add(controller.value.position);
1053+
if (positions.length >= 3 && !intervalUpdateCompleter.isCompleted) {
1054+
intervalUpdateCompleter.complete();
1055+
}
1056+
});
1057+
await controller.play();
1058+
for (int i = 0; i < 3; i++) {
1059+
await Future<void>.delayed(updatesInterval);
1060+
fakeVideoPlayerPlatform._positions[controller.textureId] =
1061+
Duration(milliseconds: i * updatesInterval.inMilliseconds);
1062+
}
1063+
1064+
// Wait for at least 3 position updates
1065+
await intervalUpdateCompleter.future;
1066+
1067+
// Verify that the intervals between updates are approximately correct
1068+
expect(positions[1] - positions[0], greaterThanOrEqualTo(updatesInterval));
1069+
expect(positions[2] - positions[1], greaterThanOrEqualTo(updatesInterval));
1070+
});
1071+
9981072
group('DurationRange', () {
9991073
test('uses given values', () {
10001074
const Duration start = Duration(seconds: 2);

0 commit comments

Comments
 (0)