From 7341fea5b3f7f7a03c58cd55a8cff16f749ae8f8 Mon Sep 17 00:00:00 2001 From: Kostia Sokolovskyi Date: Tue, 8 Apr 2025 09:54:18 +0200 Subject: [PATCH 1/2] Fix video_player blank first frame on iOS web. --- .../integration_test/video_player_test.dart | 40 +++++++++++++++++-- .../lib/src/video_player.dart | 6 ++- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/packages/video_player/video_player_web/example/integration_test/video_player_test.dart b/packages/video_player/video_player_web/example/integration_test/video_player_test.dart index b78de966fe81..816f6950f20d 100644 --- a/packages/video_player/video_player_web/example/integration_test/video_player_test.dart +++ b/packages/video_player/video_player_web/example/integration_test/video_player_test.dart @@ -3,6 +3,8 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; @@ -27,6 +29,18 @@ void main() { ..playsInline = false; }); + testWidgets('initialize() calls load', (WidgetTester _) async { + bool loadCalled = false; + + video['load'] = () { + loadCalled = true; + }.toJS; + + VideoPlayer(videoElement: video).initialize(); + + expect(loadCalled, isTrue); + }); + testWidgets('fixes critical video element config', (WidgetTester _) async { VideoPlayer(videoElement: video).initialize(); @@ -130,6 +144,11 @@ void main() { ); }); + tearDown(() { + streamController.close(); + player.dispose(); + }); + testWidgets('buffering dispatches only when it changes', (WidgetTester tester) async { // Take all the "buffering" events that we see during the next few seconds @@ -222,8 +241,7 @@ void main() { expect(events[0].eventType, VideoEventType.initialized); }); - // Issue: https://github.com/flutter/flutter/issues/137023 - testWidgets('loadedmetadata dispatches initialized', + testWidgets('loadedmetadata does not dispatch initialized', (WidgetTester tester) async { video.dispatchEvent(web.Event('loadedmetadata')); video.dispatchEvent(web.Event('loadedmetadata')); @@ -235,8 +253,22 @@ void main() { final List events = await stream; - expect(events, hasLength(1)); - expect(events[0].eventType, VideoEventType.initialized); + expect(events, isEmpty); + }); + + testWidgets('loadeddata does not dispatch initialized', + (WidgetTester tester) async { + video.dispatchEvent(web.Event('loadeddata')); + video.dispatchEvent(web.Event('loadeddata')); + + final Future> stream = timedStream + .where((VideoEvent event) => + event.eventType == VideoEventType.initialized) + .toList(); + + final List events = await stream; + + expect(events, isEmpty); }); // Issue: https://github.com/flutter/flutter/issues/105649 diff --git a/packages/video_player/video_player_web/lib/src/video_player.dart b/packages/video_player/video_player_web/lib/src/video_player.dart index 6ef4ee1939e8..15639079c3b1 100644 --- a/packages/video_player/video_player_web/lib/src/video_player.dart +++ b/packages/video_player/video_player_web/lib/src/video_player.dart @@ -77,8 +77,6 @@ class VideoPlayer { ..playsInline = true; _videoElement.onCanPlay.listen(_onVideoElementInitialization); - // Needed for Safari iOS 17, which may not send `canplay`. - _videoElement.onLoadedMetadata.listen(_onVideoElementInitialization); _videoElement.onCanPlayThrough.listen((dynamic _) { setBuffering(false); @@ -131,6 +129,10 @@ class VideoPlayer { if (src != null) { _videoElement.src = src; } + + // Explicitly triggers media loading in preparation for playback. Needed on + // iOS to ensure the first frame becomes visible before playback begins. + _videoElement.load(); } /// Attempts to play the video. From 9d6a6aa066195fb4b4924fe555955194400c9f08 Mon Sep 17 00:00:00 2001 From: Kostia Sokolovskyi Date: Tue, 8 Apr 2025 12:20:08 +0200 Subject: [PATCH 2/2] Update version and changelog. --- packages/video_player/video_player_web/CHANGELOG.md | 4 ++++ packages/video_player/video_player_web/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_web/CHANGELOG.md b/packages/video_player/video_player_web/CHANGELOG.md index 252f5e75f735..1db5ab258117 100644 --- a/packages/video_player/video_player_web/CHANGELOG.md +++ b/packages/video_player/video_player_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.5 + +* Fixes blank first frame on iOS. + ## 2.3.4 * Adjusts the code to the new platform interface. diff --git a/packages/video_player/video_player_web/pubspec.yaml b/packages/video_player/video_player_web/pubspec.yaml index c13a7578ba2e..67c7628130b6 100644 --- a/packages/video_player/video_player_web/pubspec.yaml +++ b/packages/video_player/video_player_web/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_web description: Web platform implementation of video_player. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.3.4 +version: 2.3.5 environment: sdk: ^3.4.0