bbc / VideoContext

An experimental HTML5 & WebGL video composition and rendering API.
http://bbc.github.io/VideoContext/
Apache License 2.0
1.32k stars 156 forks source link

Garbage collection #188

Closed hrueger closed 4 years ago

hrueger commented 4 years ago

I have an Electron application which plays videos with videocontext. When I click on a button, a new video node and a crossfade transition is added. How can I remove the "old" video node after the transition has finished? If I take a look at the task manager, the memory usage is increasing every time until it uses 90% of my memory and then it starts lagging...

germain-gg commented 4 years ago

Hi @hrueger ,

I don't think that I have observed that behaviour in the past. Could you maybe create a small test case that highlights the memory leak that you describe? How do you measure the memory usage?

hrueger commented 4 years ago

Sure, just take a look at this project. You can use npm i to install the dependencies and npm start to run it. The relevant lines are: https://github.com/hrueger/AGView/blob/bf800b1dbb4736cc474849c6022fa7a00a99f962/src/app/_components/dashboard/dashboard.component.ts#L55-L77 After you dropped some videos in the drop zone and then played them multiple times by doubleclicking on the thumbnail, you will see that it starts lagging after some time.

I'd like to remove the "old" videonode after the transition has ended (like in the comment in setTimeout). But if I run the disconnect method of either the video node or the transition node, I get a black canvas...

I mesured the memory usage by looking at the task manager on the electron process. At first usage is only about 250 MB, and with every video it increases. After 6 videos it looks like in the attachment. My videos are very long, so about 300 MB each.

grafik

germain-gg commented 4 years ago

I believe a reduced test case would be very useful here. Still a bit unsure if removing a video node after the transition is finished would have a big impact on performance. In here it is a bit difficult to pinpoint the source of the problem.

The browser is in charge of decoding the video and put the content in a buffer. That buffer has a max length and the browser will garbage collect the things it does not need anymore.

If I understand your use case correctly, your user will upload some content and you will play that straight away?

It is usually recommended to encode and downscale the videos. It will make it easier for the rendering engine to run smoothly. Make sure that the drawing buffer of your canvas is as small as it can be

Happy to look further into this problem but probably won't be able to make a big difference without a reduced test case

hrueger commented 4 years ago

I created a reduced test case for you. Just use npm i and then npm start. After playing a couple of videos, the memory usage is very high.

If I understand your use case correctly, your user will upload some content and you will play that straight away?

As it is a electron application, my application runs in an embedded chromium browser. The video doesn't need to be uploaded, instead the open dialog (here) returns the local path of the video. Then it is played (I think) using the file:/// protocol.

hrueger commented 4 years ago

Any update on this?

germain-gg commented 4 years ago

Looking at your example above I do not think that the issue is related to a memory leak. Running an analysis in the devtools that the memory in the JS heap gets deallocated correctly

Screenshot 2019-11-11 at 21 50 56

Your code keeps on creating new video nodes and does not de-reference the old ones. A good performance improvement would be to set an end time for the node that is faded out. Otherwise, video context's rendering graph will keep on drawing the texture for that video node that you essentially do not see anymore.

Another tip in here would be to make sure that you optimise the encoding of the videos that you playback. You have a bit of guidance regarding that in the README.md https://github.com/bbc/VideoContext#videonode

hrueger commented 4 years ago

I already added a function which automatically encodes the videos correctly. But calling the videoNode.end(time) function worked perfectly! I just didn't know that this would free the memory used by that video. Thank you.

But I've got another question: If I have some videos, which have different aspect ratios that my canvas, can I tell videocontext to leave black bars instead of stretching?

germain-gg commented 4 years ago

AFAIK you will have to use an EffectNode to position your video. But you'll have to know the aspect ratio and do the calculation yourself.

@richski can you close this issue 👍 ?

hrueger commented 4 years ago

Thanks!