-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[video_player] #60048 ios picture in picture #3500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[video_player] #60048 ios picture in picture #3500
Conversation
@hellohuanlin & @stuartmorgan I did the migration from flutter/plugins#6284 to here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
carrying over the stamp from previous PR
@tarrinneal can I assist you with the review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial pass. A few changes to be made. Good work on this!
packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart
Outdated
Show resolved
Hide resolved
packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart
Outdated
Show resolved
Hide resolved
packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m
Outdated
Show resolved
Hide resolved
packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m
Outdated
Show resolved
Hide resolved
packages/video_player/video_player_avfoundation/ios/Classes/FLTVideoPlayerPlugin.m
Outdated
Show resolved
Hide resolved
packages/video_player/video_player_platform_interface/CHANGELOG.md
Outdated
Show resolved
Hide resolved
# Conflicts: # packages/video_player/video_player/CHANGELOG.md # packages/video_player/video_player/lib/video_player.dart # packages/video_player/video_player/pubspec.yaml # packages/video_player/video_player_android/example/lib/mini_controller.dart # packages/video_player/video_player_avfoundation/CHANGELOG.md # packages/video_player/video_player_avfoundation/example/lib/mini_controller.dart # packages/video_player/video_player_avfoundation/lib/src/avfoundation_video_player.dart # packages/video_player/video_player_avfoundation/pubspec.yaml
…tsPictureInPicture
@tarrinneal I updated my pull request fully retested it to make sure it does what I expect. |
Seems like you still have a few broken tests. I should be able to get this re-reviewed this week, if you can git them sorted out. |
@tarrinneal the tests are failing on camera because of the dependency overrides. How should I handle this? Because the dependency override script doesn't update it in the camera package. I will fix the merge conflicts today |
Hi @vanlooverenkoen, |
Either one is fine; usually when people pick up unfinished PRs they aren't able to push to them so make a new PR, but since that's not an issue here continuing with the same PR shouldn't have any issues. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of quick notes on the updated version until I have time for a full review.
#import "./include/video_player_avfoundation/AVAssetTrackUtils.h" | ||
#import "AVAssetTrackUtils.h" | ||
#import "FVPDisplayLink.h" | ||
#import "messages.g.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Local imports need to use project-relative paths; fixing that should fix the build_all CI failures.
@@ -4,10 +4,14 @@ | |||
|
|||
#import "./include/video_player_avfoundation/FVPVideoPlayer.h" | |||
#import "./include/video_player_avfoundation/FVPVideoPlayer_Test.h" | |||
#import "./include/video_player_avfoundation/AVAssetTrackUtils.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is incorrect; please see the style guide rules for header import ordering.
@@ -1,7 +1,7 @@ | |||
// Copyright 2013 The Flutter Authors. All rights reserved. | |||
// Use of this source code is governed by a BSD-style license that can be | |||
// found in the LICENSE file. | |||
// Autogenerated from Pigeon (v22.5.0), do not edit directly. | |||
// Autogenerated from Pigeon (v22.7.2), do not edit directly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was video_player_android
Pigeon code regenerated for this PR?
This comment was marked as off-topic.
This comment was marked as off-topic.
Hi @vanlooverenkoen, we are using your fork already for a while in production and it works very well. Our released version was still from the end of last year. We've just updated the library and noticed a strange animation happening when setting the pip overlay rect. Also when changing page the video remains visible for a while. See the video below: TEST.Simulator.Screen.Recording.-.iPhone.16.-.2025-02-20.at.15.39.09.mp4 |
Hi @philipgiuliani , |
Thanks for the quick response and checking it! We pinned the commit, but we had to update the package because the old video_player cannot build on Android with Flutter 3.29. |
It seems to work perfectly fine by adding the following code back in the _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
// picture-in-picture shows a placeholder where the original video was playing.
// This is a native overlay that does not scroll with the rest of the Flutter UI.
// That is why we need to set the opacity of the overlay.
// Setting it to 0 would result in the picture-in-picture not working.
// Setting it to 1 would result in the picture-in-picture overlay always showing over other
// widget. Setting it to 0.001 makes the placeholder invisible, but still allows the
// picture-in-picture.
_playerLayer.opacity = 0.001;
[self.flutterViewLayer addSublayer:_playerLayer]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies, doing another review pass had fallen off my radar since the review state was never switched back to review request. I've done an initial pass over the current state.
@@ -18,6 +18,7 @@ dependencies: | |||
sdk: flutter | |||
path_provider: ^2.0.0 | |||
video_player: ^2.7.0 | |||
video_player_platform_interface: ^6.2.3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this addition necessary?
### Picture-in-Picture | ||
|
||
#### iOS | ||
To enable picture-in-picture functionality, you need to add the **Background Modes** capabilities for **Audio, AirPlay, and Picture in Picture** as described in [Configuring your app for media playback > Configure the background modes](https://developer.apple.com/documentation/AVFoundation/configuring-your-app-for-media-playback#Configure-the-background-modes). Resulting in a new string entry `audio` in the array value of the entry `UIBackgroundModes` in your `Info.plist` file, which is located in `<project root>/ios/Runner/Info.plist`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second sentence here is a fragment. It should probably say something like "Adding this mode will result in ..."
### Picture-in-Picture | ||
|
||
#### iOS | ||
To enable picture-in-picture functionality, you need to add the **Background Modes** capabilities for **Audio, AirPlay, and Picture in Picture** as described in [Configuring your app for media playback > Configure the background modes](https://developer.apple.com/documentation/AVFoundation/configuring-your-app-for-media-playback#Configure-the-background-modes). Resulting in a new string entry `audio` in the array value of the entry `UIBackgroundModes` in your `Info.plist` file, which is located in `<project root>/ios/Runner/Info.plist`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything from "which is located in" on can be removed; documenting basic iOS project structure isn't necessary here.
> Failing to add the `audio` **Background Modes** capability will result in a silent failure to start picture-in-picture playback. | ||
|
||
Example: | ||
 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
READMEs should never have references to non-pinned URLs, as it means old versions' READMEs can change or break at any time. E.g., renaming the plugin in the future would break all previous READMEs.
This will need to be added in a follow-up PR, using a hash instead of main
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should be listed in a .pubignore
.
), | ||
); | ||
}, | ||
child: const Text('Set picture-in-picture overlay rect'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this something that clients have to call manually? Shouldn't the controller be determining this information from the widget as needed?
} | ||
|
||
/// Sets the location of the video player view in order to animate the picture-in-picture view. | ||
Future<void> setPictureInPictureOverlaySettings({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per my comment in the example code, it's not clear to me why this needs to be public API.
); | ||
} | ||
|
||
/// Starts picture-in-picture mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The methods that require isPictureInPictureSupported
to be true in order to call them should all be commented accordingly.
@@ -664,6 +664,30 @@ - (void)testSeekToleranceWhenSeekingToEnd { | |||
XCTAssertNil(error); | |||
XCTAssertEqual(avPlayer.volume, 0.1f); | |||
|
|||
// Set picture-in-picture |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs to be resolved.
@@ -31,6 +32,34 @@ - (void)testPlayVideo { | |||
XCTAssertTrue([playButton waitForExistenceWithTimeout:30.0]); | |||
[playButton tap]; | |||
|
|||
if ([AVPictureInPictureController isPictureInPictureSupported]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs to be resolved.
Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.
List which issues are fixed by this PR. You must list at least one issue.
This feature is only available on iOS because android has a different implementation. simple_pip_mode can be used for Android
Fixes flutter/flutter#60048
Migration from flutter/plugin to flutter/packages is done with this pr
old pr: flutter/plugins#6284
No migration needed this is an addon
If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.