diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index 9f23fd099c03..2513b20feee3 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.12 + +* iOS: Validate size only when assets contain video tracks. + ## 2.2.11 * Removes dependency on `meta`. diff --git a/packages/video_player/video_player/example/assets/Audio.mp3 b/packages/video_player/video_player/example/assets/Audio.mp3 new file mode 100644 index 000000000000..355eb9b2e1fb Binary files /dev/null and b/packages/video_player/video_player/example/assets/Audio.mp3 differ diff --git a/packages/video_player/video_player/example/integration_test/video_player_test.dart b/packages/video_player/video_player/example/integration_test/video_player_test.dart index d652c042cf72..0c2252bf7447 100644 --- a/packages/video_player/video_player/example/integration_test/video_player_test.dart +++ b/packages/video_player/video_player/example/integration_test/video_player_test.dart @@ -272,4 +272,68 @@ void main() { skip: !(kIsWeb || defaultTargetPlatform == TargetPlatform.android), ); }); + + // Audio playback is tested to prevent accidental regression, + // but could be removed in the future. + group('asset audios', () { + setUp(() { + _controller = VideoPlayerController.asset('assets/Audio.mp3'); + }); + + testWidgets('can be initialized', (WidgetTester tester) async { + await _controller.initialize(); + + expect(_controller.value.isInitialized, true); + expect(_controller.value.position, const Duration(seconds: 0)); + expect(_controller.value.isPlaying, false); + // Due to the duration calculation accurancy between platforms, + // the milliseconds on Web will be a slightly different from natives. + // The audio was made with 44100 Hz, 192 Kbps CBR, and 32 bits. + expect( + _controller.value.duration, + Duration(seconds: 5, milliseconds: kIsWeb ? 42 : 41), + ); + }); + + testWidgets('can be played', (WidgetTester tester) async { + await _controller.initialize(); + // Mute to allow playing without DOM interaction on Web. + // See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes + await _controller.setVolume(0); + + await _controller.play(); + await tester.pumpAndSettle(_playDuration); + + expect(_controller.value.isPlaying, true); + expect( + _controller.value.position, + (Duration position) => position > const Duration(milliseconds: 0), + ); + }); + + testWidgets('can seek', (WidgetTester tester) async { + await _controller.initialize(); + await _controller.seekTo(const Duration(seconds: 3)); + + expect(_controller.value.position, const Duration(seconds: 3)); + }); + + testWidgets('can be paused', (WidgetTester tester) async { + await _controller.initialize(); + // Mute to allow playing without DOM interaction on Web. + // See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes + await _controller.setVolume(0); + + // Play for a second, then pause, and then wait a second. + await _controller.play(); + await tester.pumpAndSettle(_playDuration); + await _controller.pause(); + final Duration pausedPosition = _controller.value.position; + await tester.pumpAndSettle(_playDuration); + + // Verify that we stopped playing after the pause. + expect(_controller.value.isPlaying, false); + expect(_controller.value.position, pausedPosition); + }); + }); } diff --git a/packages/video_player/video_player/example/pubspec.yaml b/packages/video_player/video_player/example/pubspec.yaml index 6fa02c459c53..eef6eb7ab63b 100644 --- a/packages/video_player/video_player/example/pubspec.yaml +++ b/packages/video_player/video_player/example/pubspec.yaml @@ -36,3 +36,4 @@ flutter: - assets/Butterfly-209.webm - assets/bumble_bee_captions.srt - assets/bumble_bee_captions.vtt + - assets/Audio.mp3 diff --git a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m index b581cd8b7b5e..d5bea174e61d 100644 --- a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m @@ -337,12 +337,14 @@ - (void)updatePlayingState { - (void)setupEventSinkIfReadyToPlay { if (_eventSink && !_isInitialized) { + BOOL hasVideoTracks = + [[self.player.currentItem.asset tracksWithMediaType:AVMediaTypeVideo] count] != 0; CGSize size = [self.player currentItem].presentationSize; CGFloat width = size.width; CGFloat height = size.height; - // The player has not yet initialized. - if (height == CGSizeZero.height && width == CGSizeZero.width) { + // The player has not yet initialized when it contains video tracks. + if (hasVideoTracks && height == CGSizeZero.height && width == CGSizeZero.width) { return; } // The player may be initialized but still needs to determine the duration. @@ -375,7 +377,10 @@ - (int64_t)position { } - (int64_t)duration { - return FLTCMTimeToMillis([[_player currentItem] duration]); + // Note: https://openradar.appspot.com/radar?id=4968600712511488 + // `[AVPlayerItem duration]` can be `kCMTimeIndefinite`, + // use `[[AVPlayerItem asset] duration]` instead. + return FLTCMTimeToMillis([[[_player currentItem] asset] duration]); } - (void)seekTo:(int)location { diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index 0eb7a4ed41df..e725db74509c 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for displaying inline video with other Flutter widgets on Android, iOS, and web. repository: https://github.com/flutter/plugins/tree/master/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.2.11 +version: 2.2.12 environment: sdk: ">=2.14.0 <3.0.0"