cordova-plugin-ionic-webview
cordova-plugin-ionic-webview copied to clipboard
iOS - Playing local video files uses huge amount of memory
Context
I have an app which downloads video files (.mp4) from AWS, stores them locally, and plays them using an HTML5 video tag.
Issue
When the app loads the component, I see a huge peak in RAM usage (my app uses 40mb in average, and I see peaks up to 500mb). This is really an issue because it makes the webview crash (white screen + reloading) with most of my videos (which are 200-300mb each).
If I try to play the video directly from the server, it works fine (no memory peak).
I don't have a lot of experience with videos and streaming, but it seems that the webview tries to load the whole video file when the component is loaded, instead of streaming the video.
Environment
- I'm using Ionic@4 + [email protected].
- I used to play videos the same way with Ionic@3 + cordova-plugin-ionic-webview@2 without any issue
- I use
@ionic-native/file-transfer
to store the files locally - iPad with iOS 11.3
Code
component.html
<video preload="auto">
<source [src]="backgroundVideoURL" type="video/mp4">
</video>
component.ts
import { SafeUrl, DomSanitizer } from '@angular/platform-browser';
...
constructor(private sanitizer: DomSanitizer) { }
...
// assetLocalUrl is the file's local URL on the device, returned by window.Ionic.WebView.convertFileSrc()
this.backgroundVideoURL = this.sanitizer.bypassSecurityTrustUrl(assetLocalUrl);
Were you ever able to resolve this issue? I'm seeing the same problem with large video files.
@jbgtmartin
No, issue still here!
I'm suffering from this as well. Unless i'm mistaken it's a result of this implementation of asset handling:
https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/master/src/ios/IONAssetHandler.m#L40
It seems that ionic-webview is now just loading files, no matter what their size, into memory and sending them over the internal wire rather than implementing range requests as GCDWebServer did.
I'm poking around to see if I can make range requests work but am currently stumped by the need to get the WKWebview client to detect and request data with the Range
header. In the case of GCDWebServer this appears to work correctly when Content-Length
and Content-Type
were both set in the case of mp4 files. Perhaps there is a HEAD
or OPTIONS
request being responded to that isn't setting the Accept-Ranges: bytes
header? If that's the case i'm unsure where that happens though as IONAssetHandler doesn't appear to receive HEAD
or OPTIONS
requests.
Did you get that to work @greggarson ?
I have the same problem. Someone know how to fix or maybe have other the solution how to play local video?
For now I just « fixed » it by using version 2 of the plugin...
Thanks, I will try the same
Previously my app used v2 but App Store Connect started to reject my builds because of non public api usage. Did you try building and uploading to Apple?
I have this exact same issue on version 4.1.1
. Saving of large videos to the iPad and then trying to stream them crashes the app.
When loading large content (like a video) to display on an iOS app, memory usage balloons (:balloon: ) and crashes the webview and app.
I think it definitely has something to do with this line: https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/master/src/ios/IONAssetHandler.m#L40 as @greggarson said.
Reverting to 2.5.1
of the plugin resolves the issue.
@dylanvdmerwe How did you get your app through Apple App Store review? We submitted ours with 2.2 and it was rejected due to the private APIs issue.
What a nightmare... Is there actually a way to play video files without crashing on iOS or is it a core problem with webview on iOS?
I revert to 2.5.1 and it works great, but I worry about AppStore reject. Someone from the ionic team read this issue or no?
Maybe try set <preference name="WKSuspendInBackground" value="false" />
to true
in version 2 of this plugin? This would be the only preference that the AppStore would moan about.
I am seeing the same problem, as @greggarson already said I think it has to do with Range
requests not being supported.
How is the ionic team checking bugs?
An update, I was able to publish an app with version 2.5.1
of this plugin without any issues. Make sure to have this set <preference name="WKSuspendInBackground" value="false" />
.
Hi @dylanvdmerwe , did you add the preference in config.xml in ios platform section?
Thank you
Hi @mateusduraes
I have the following in my config.xml
file:
<platform name="ios">
<preference name="WKSuspendInBackground" value="false" />
<preference name="WKPort" value="8199" />
<preference name="UseScheme" value="true" />
@IonicProSupport any new on this? Would you have any workaround to suggest?
Sadly, as the webview doesn't send Ranges in header, we can't properly stream the files.
I've sent a PR that should reduce memory usage, but it's not a real fix, just a mitigation.
https://github.com/ionic-team/cordova-plugin-ionic-webview/pull/459
Can you give it a try?
Also, I wouldn't recommend having a lot of video tags at the same time, but have only one and change the src to the new videos. In the way the webview works it will try to load all files at once even if it they don't have autoplay on it.
I've reported it to Apple https://bugs.webkit.org/show_bug.cgi?id=203302
@jcesarmobile This is the only answer I have been able to find to fix my problem. Regarding the multiple videos being loaded all at once! This is also a problem on ionic 3 where if I have more than one video tag in the view it only allows one of the videos to load! Worst of all it is random on which video it wants to load and it returns no error in the log when it doesn't load. And it only happens on compiled applications!
Removing the extra videos and dynamically changing the [src] worked for me thank you much!
Do they still accept bug requests for ionic 3 because this really needs to be reported or documented somewhere? I have spent days searching for an answer to this issue.
It’s not an ionic bug, it’s how the webview behaves when there are more than 1 video.
Also not what I mean, even if only plays one, it requests all of them for preloading and that causes a huge amount of memory being used that can crash the app. That’s why I recommend having only one.
@jcesarmobile good to know, do you know of any documentation on this? it would be helpful to read up more about how videos are handled? I havent been able to find any?
I don’t know any docs, I just inspected network requests in safari web inspector
Thanks for reporting the bug! So if I understand correctly, the headers are not sent when using the ionic:// custom scheme, and that's why it's working with version 2 but not version 4?
I didn't have the time to test your fix yet, but for information I have only one video tag, but with a large video (200-300mb)
Yeah, when using version 2 there is a local server running and as uses http the headers are present and the server can manage to return video chunks as expected, when using version 4 it uses ionic scheme and there are no headers, so can’t return the video in chunks.
What I don’t understand is @dylanvdmerwe comment where he says he uses <preference name="UseScheme" value="true" />
, in that chase the plugin will use ionic scheme even in version 2
I've released 4.1.3 with the change that should mitigate the memory usage
I am really looking forward ti see if this will solve the issue.
I tried v4.1.3. It didn't solve my issue, I still have memory peaks over 300mb, leading to a webview crash. I only have 1 video tag in my app, maybe that's why the patch has little effect on the memory usage. Anyway thanks for the release and the bug report, I'll stick with v2 until this is fixed by Apple...
You could in theory add the cordova HTTPD plugin and then use this to access the locally stored videos, this would allow you to send range headers etc as in the earlier implementation of the webview plugin. This just keeps the local webserver "on the side" for serving media when needed I guess.
https://ionicframework.com/docs/native/httpd
edit: doesn't use GCDWebserver