Closed timcreatedit closed 2 years ago
Sorry about the poor experience, but can you provide more conditions when you're running into this issue? Such as, is the file
getter always taking so much time? Why would the original file of an HDR photo fail to use?
I'd like to understand the detailed behavior in order to produce more thoughts on how to fix/improve this.
Hi, thank you for your help. Sorry that I didn't provide enough details.
I'm specifically talking about video files. The .file getter is taking that much time for all video files on the first load if isLocal == true. As soon as the video has been loaded once and is cached, it's basically instant, however we can't cache all videos forever due to space constraints.
Original files for HDR video are not really usable, because the colors are completely off, at least when displaying them using video_player, or processing them with FFMPEG. We also can't use the original files for slow motion video, because it just returns the video with high framerate and original speed and ignores the slow motion parts that users selected in the Photos app.
I hope I made it a little clearer, I'm available for questions or any tests that I could run
When loading videos, can you use getMediaUrl
instead when isLocallyAvailable
?
I just took a glance at the file
getter, it'll request an export session that produces a playable media file on the device, which can be I/O related.
I'll give that a try and report back with the results. Thank you!
I can confirm that using getMediaUrl() produces the same results as .originFile. The videos load instantly but are unusable in some cases like HDR or slow motion. I have no idea about how the native iOS part works so forgive me if I sound stupid, but I feel like there should be a solution since picking a video in other apps works quickly, and preserves slow motion for example. Thanks again for your help and time
I don't have iOS devices nearby until tomorrow, did you try with the image_picker
yet? Does it work well with the video_player
? Which picker is available?
I've investigated further using other packages, here are my results:
I was wondering if the exact match between the video duration and the time it takes to load was a coincidence, so I measured some other times: 00:24 HDR (95 MB) - 14s to load 00:11 HDR (52 MB) - 6s to load
So it seems to be a coincidence.
So, from your investigations, can you try with a lower quality here to see if it helps?
Switching to AVAssetExportPresetLowQuality reduces the export time for the 1:40 video to 15 seconds, which is still as long as the compression step from image_picker, however the resulting video clip is much, much worse to a point where it's basically completely unusable.
Thanks for the proof, sound like we can learn from the compressing process of the image_picker
. Are you able to indicate where did the plugin (image_picker
) do the compress?
I can try looking into that. However I don't really understand why a compression step is even necessary. If native iOS apps can display a video in full quality and with all edits instantly, why can't we use the same method for this package (might be a stupid question)?
I've filed a PR for this, please verify if it brings improvement in this case.
TL;DR, no compression was brought here, just copying the asset from private to the sandbox without export sessions when the asset already matched the condition. Also, exporting QuickTime movies instead of MPEG4 might cost less time since they're typically QuickTime movies originally.
Tested with below contents on iPhone 12, and all of them are successful to play with video_player
.
You can see the pre-check improved instantly reply with the copied file in the sandbox, without any compressions.
Duration | Type | Resolution | Format | Pre-check improved | Type improved | Not improved | Size |
---|---|---|---|---|---|---|---|
00:48 | HDR | 1920x1080 | HEVC | 0:00:00.046232 | 0:00:02.161513 | 0:00:09.608286 | 68.6 MB |
01:36 | Network | 1080x1920 | H.264 | 0:00:00.034561 | 0:00:01.113288 | 0:00:01.078738 | 8.9 MB |
00:03 | Slo-mo | 1080x1920 | HEVC | N/A (AVComposition ) |
0:00:01.894947 | 0:00:04.578076 | 23.7 MB |
The conclusion here is when videos are special, here only with Slo-Mo videos, are composited as AVComposition
. When a video is composited, it can only be fetched with at least an export request, otherwise, the original video will be obtained.
Other videos (when they're AVURLAsset
) can be delivered directly without any compressions, but still require a sandbox copy. It only involves with I/O request, so it behaves like instantly obtained without seconds of waiting.
The PR will determine when to obtain the path from AVURLAsset
directly, and when to export a composited video with medium quality (since the medium is most balanced so far).
Sandbox is still required, no luck with that.
FYI @Tom3652, I think the improvement can be also related to some long-retrieving issues you've mentioned.
Thank you for your effort and explanation. For the pull request however, unfortunately the file getter now matches the behavior of originFile for me, meaning that HDR video colors are completely off in video_player, and slow motion videos play in original speed. I've tried the passthrough setting in my investigation yesterday as well with the same results.
unfortunately the file getter now matches the behavior of originFile for me, meaning that HDR video colors are completely off in video_player, and slow motion videos play in original speed.
I can't identify the HDR issue, but the Slo-Mo should be fixed since I didn't push my commit when the above comments were posted. Try 28c68d7.
Hi @AlexV525 thanks for mentioning me here.
It was indeed my requirement as well (load videos as fast as native iOS apps), i have not tested with HDR videos or slow motion actually, and @timcreatedit i am using ´getMediaUrl()´ to fetch the video instantly, then if the user wants to upload it, i load it during my upload process with ´.file´ so there is no bad user experience but the upload is much longer depending on the video.
I will give a try with the HDR / slow motion to see if the video_player is playing them normally based on your comment, and if the URL file also plays the correct file in the browser.
I agree however that native iOS apps seem to be able to fetch videos (without cache for the first time) instantly or almost instantly and use it (edited or not)
If the HDR can be solved by commenting out these, then we might require all assets to be exported.
I agree however that native iOS apps seem to be able to fetch videos (without cache for the first time) instantly or almost instantly and use it (edited or not)
I can't guarantee any solid usage here, since we're a cross-platform plugin. :)
I can't identify the HDR issue, but the Slo-Mo should be fixed since I didn't push my commit when the above comments were posted.
I can confirm that slow-motion plays correctly now, but the quality is abysmal, I think a higher quality preset should be considered, especially if users are unable to choose the export quality themselves.
Regarding HDR, I don't know if it is within the scope of this plugin, since the actual responsibility would be for video_player to be able to play HDR content correctly see this issue. It will also be weird if video_player starts supporting HDR at some point and then all the files obtained from the .file getter are SDR I guess?
It was indeed my requirement as well (load videos as fast as native iOS apps), i have not tested with HDR videos or slow motion actually, and @timcreatedit i am using ´getMediaUrl()´ to fetch the video instantly, then if the user wants to upload it, i load it during my upload process with ´.file´ so there is no bad user experience but the upload is much longer depending on the video.
I've considered this approach as well, however this doesn't work for slow motion videos since the displayed video would vary greatly from the one that would be used in export. Even more so since my app requires selecting a specifically timed clip from a video.
If you're good with the highest preset's duration, I think we should use it for all. Can you try it by modifying the code?
file
getter could be hard to extend since it'll introduce a breaking change. From the overall API design, I don't have a better idea about a customizable parameter for the quality.
I've considered this approach as well, however this doesn't work for slow motion videos since the displayed video would vary greatly from the one that would be used in export. Even more so since my app requires selecting a specifically timed clip from a video.
I will give it a try today with my implementation and see this, i also have this kind of feature in my app so thanks for pointing it out
I think it's more an issue of predictability than of what I need personally, since users of this plugin will be confused if the video quality suffers so significantly. So imo if you're forced to use the export session, we should go with the highest quality.
I think overall this is a good compromise since slow motion videos also tend to be shorter (and more rare) and therefore the export times shouldn't matter as much as for a 1min 4k HDR video for example.
Although the control flow is the same for Slo-Mo videos, it's still optimized by a more accurate file type for export. So I guess we still got improvements for them.
Although the control flow is the same for Slo-Mo videos, it's still optimized by a more accurate file type for export. So I guess we still got improvements for them.
It is noticably quicker! Also it will make it easier to create a good UX since I think users will at least understand why slow motion videos take longer to load. Thank you very much, now we only need HDR support in video_player 😬
So with the version i have got without the above PR i confirm that getMediaUrl
doesn't retrieve the file in Slo-Mo or at least the video_player doesn't play the Slo-Mo i can't tell...
However i have no problem playing HDR videos, with which camera do you record these videos @timcreatedit ?
However i have no problem playing HDR videos,
It's not about playing them, it's about the colors being noticeably off. This is an issue with the video_player package, it could be that you're using better_player, which does play HDR on iOS correctly. There is an open issue for the video_player package about the topic, you can go there for details :) https://github.com/flutter/flutter/issues/91241
So with the version i have got without the above PR i confirm that
getMediaUrl
doesn't retrieve the file in Slo-Mo or at least the video_player doesn't play the Slo-Mo i can't tell...
I think the PR won't fix that, you'll have to use the .file getter for those. It seems like for providing native-like video performance on iOS, we would need to build a video player that can read the metadata of those files to play them correctly.
The PR contains the Slo-Mo composition part when exporting, which means they can be played like a Slo-Mo with file
and getMediaUrl
(if I tested it right). But the originalFile
doesn't.
For a better UX when integrating with iCloud, durations, etc, I still prefer developers to use the file
with a progress handler at first, then use the getMediaUrl
for something like Live Photos.
I think the PR won't fix that, you'll have to use the .file getter for those. It seems like for providing native-like video performance on iOS, we would need to build a video player that can read the metadata of those files to play them correctly.
Yes you are right, getMediaUrl
has not changed (doesn't play the Slo-Mo) but the .file
yes.
-> Edit : Actually it's not true, i have cleared my phone's cache and the getMediaUrl
is working for Slo-Mo as well :) and it took 5sec instead of 7 to fetch the 3sec video still under isLocallyAvailable = true
.
With my performances test, a 3sec Slo-Mo video is loaded in 7 seconds using .file
which is much better than before but still quite long while isLocallyAvailable = true
.
This is only true the first time the asset is fetched though, after it's instantly done.
I have also got a new error but i should make a new issue i think ?
flutter: Error flutter ZonedGuarded : PlatformException(Error Domain=AVFoundationErrorDomain Code=-11823 "Cannot Save" UserInfo={NSLocalizedRecoverySuggestion=Try saving again., NSLocalizedDescription=Cannot Save, NSUnderlyingError=0x280c100f0 {Error Domain=NSOSStatusErrorDomain Code=-12101 "(null)"}}, null, null, null)
StackTrace : #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
#1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:177:18)
<asynchronous suspension>
#2 AssetEntity._getFile (package:photo_manager/src/types/entity.dart:624:26)
<asynchronous suspension>
I have also got a new error but i should make a new issue i think ?
Indeed.
This is only true the first time the asset is fetched though, after it's instantly done.
This is due to caching but be careful with the size of the cache. If you don't clean up after yourself, the cache can easily grow to gigabytes in size if you load lots of videos, at least that's what happened for us.
This is due to caching but be careful with the size of the cache. If you don't clean up after yourself, the cache can easily grow to gigabytes in size if you load lots of videos, at least that's what happened for us.
Thought about this today, I think it'll be a good practice to point out in the README.
It's actually indicated already: https://github.com/fluttercandies/flutter_photo_manager/blob/8afba2745ebaac6af8af75de9cbded9157bc2690/README.md#L435-L436
Describe the bug We're creating an app where we need a custom video picker, however loading the video files via photo_manager is extremely slow on iOS. When obtaining the file for a video for the first time, a 3s video can load for upwards of 5 seconds. For longer videos the loading time is even worse (>1min in some cases), making our app almost unusable on iOS at the moment. Obtaining files through AssetEntity.originFile is almost instant, however some videos are unusable or have unexpected behaviour (HDR, slow motion, etc.) Caching is not really a valid option for us, since we need to provide access to different videos quickly and can't afford the storage that the cache would take up in that case.
To Reproduce
Expected behavior Since other apps, like every messenger for example, can access gallery videos almost instantly, even on first load where caching couldn't have taken place, we expected that the same should hold true for this package as well.
Flutter version [✓] Flutter (Channel stable, 2.10.0, on macOS 12.2 21D49 darwin-arm, locale en-DE) • Flutter version 2.10.0 at /Users/tim/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 5f105a6ca7 (13 days ago), 2022-02-01 14:15:42 -0800 • Engine revision 776efd2034 • Dart version 2.16.0 • DevTools version 2.9.2
Smartphone: