cordova-plugin-ionic-webview icon indicating copy to clipboard operation
cordova-plugin-ionic-webview copied to clipboard

iOS - Playing local video files uses huge amount of memory

Open jbgtmartin opened this issue 5 years ago • 35 comments

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);

jbgtmartin avatar Jun 17 '19 10:06 jbgtmartin

Were you ever able to resolve this issue? I'm seeing the same problem with large video files.

@jbgtmartin

alex-nikos avatar Jul 08 '19 13:07 alex-nikos

No, issue still here!

jbgtmartin avatar Jul 08 '19 13:07 jbgtmartin

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.

greggarson avatar Jul 15 '19 23:07 greggarson

Did you get that to work @greggarson ?

Textras avatar Jul 31 '19 20:07 Textras

I have the same problem. Someone know how to fix or maybe have other the solution how to play local video?

webquali avatar Aug 22 '19 08:08 webquali

For now I just « fixed » it by using version 2 of the plugin...

jbgtmartin avatar Aug 22 '19 11:08 jbgtmartin

Thanks, I will try the same

webquali avatar Aug 22 '19 11:08 webquali

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?

dwolner avatar Aug 22 '19 18:08 dwolner

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 avatar Aug 23 '19 14:08 dylanvdmerwe

@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.

gsfioravanti avatar Aug 23 '19 17:08 gsfioravanti

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?

deliverymanager avatar Aug 23 '19 17:08 deliverymanager

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?

webquali avatar Aug 23 '19 19:08 webquali

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.

dylanvdmerwe avatar Aug 24 '19 12:08 dylanvdmerwe

I am seeing the same problem, as @greggarson already said I think it has to do with Range requests not being supported.

doender avatar Aug 28 '19 08:08 doender

How is the ionic team checking bugs?

webquali avatar Aug 29 '19 19:08 webquali

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" /> .

dylanvdmerwe avatar Aug 29 '19 20:08 dylanvdmerwe

Hi @dylanvdmerwe , did you add the preference in config.xml in ios platform section?

Thank you

mateusduraes avatar Sep 10 '19 15:09 mateusduraes

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" />

dylanvdmerwe avatar Sep 11 '19 07:09 dylanvdmerwe

@IonicProSupport any new on this? Would you have any workaround to suggest?

jbgtmartin avatar Oct 08 '19 16:10 jbgtmartin

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 avatar Oct 23 '19 12:10 jcesarmobile

@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.

blundercode avatar Oct 24 '19 00:10 blundercode

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 avatar Oct 24 '19 08:10 jcesarmobile

@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?

blundercode avatar Oct 24 '19 18:10 blundercode

I don’t know any docs, I just inspected network requests in safari web inspector

jcesarmobile avatar Oct 24 '19 20:10 jcesarmobile

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)

jbgtmartin avatar Oct 25 '19 07:10 jbgtmartin

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

jcesarmobile avatar Oct 25 '19 08:10 jcesarmobile

I've released 4.1.3 with the change that should mitigate the memory usage

jcesarmobile avatar Oct 30 '19 15:10 jcesarmobile

I am really looking forward ti see if this will solve the issue.

deliverymanager avatar Oct 30 '19 17:10 deliverymanager

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...

jbgtmartin avatar Nov 04 '19 12:11 jbgtmartin

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

ghenry22 avatar Apr 15 '20 02:04 ghenry22