Javascript 如何正确卸载/销毁 VIDEO 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3258587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:55:06  来源:igfitidea点击:

How to properly unload/destroy a VIDEO element

javascriptjquerydommemory-managementhtml

提问by sparkey0

I'm working on a realtime media browsing/playback application that uses <video>objects in the browser for playback, when available.

我正在开发一个实时媒体浏览/播放应用程序,该应用程序<video>在可用时使用浏览器中的对象进行播放。

I'm using a mix of straight javascript, and jQuery,

我混合使用了 javascript 和 jQuery,

My concern is specifically with memory. The application never reloads in the window, and the user can watch many videos, so memory management becomes a large concern over time. In testing today, I see the memory profile jumping by the size of the video to be streamed with each subsequent load, and never dropping back down to the baseline.

我特别关心的是记忆。应用程序永远不会在窗口中重新加载,并且用户可以观看许多视频,因此随着时间的推移,内存管理成为一个大问题。在今天的测试中,我看到内存配置文件随着每次后续加载要流式传输的视频大小而跳跃,并且永远不会回落到基线。

I've tried the following things with the same result:

我尝试了以下结果相同的事情:

1 - Empty the parent container containing the created element, eg:

1 - 清空包含创建元素的父容器,例如:

$(container_selector).empty();

2 - Pause and remove children matching 'video', and then empty the parent container:

2 - 暂停并移除与“视频”匹配的子项,然后清空父容器:

$(container_selector).children().filter("video").each(function(){
    this.pause();
    $(this).remove();
});
$(container_selector).empty();

Has anyone else run into this issue, and is there a better way to do this?

有没有其他人遇到过这个问题,有没有更好的方法来做到这一点?

回答by toon lite

It is very tricky to dispose video from the DOM structure. It may lead to browser crashing. Here is the solution that helped me in my project.

从 DOM 结构处理视频非常棘手。这可能会导致浏览器崩溃。这是在我的项目中帮助我的解决方案。

var videoElement = document.getElementById('id_of_the_video_element_here');
videoElement.pause();
videoElement.removeAttribute('src'); // empty source
videoElement.load();

this will reset everything, silent without errors !

这将重置一切,无错误无声!

Edit: Here are the full details as recommended in the Standard: https://html.spec.whatwg.org/multipage/media.html#best-practices-for-authors-using-media-elements

编辑:以下是标准中推荐的完整细节:https: //html.spec.whatwg.org/multipage/media.html#best-practices-for-authors-using-media-elements

Hope it resolve your query.

希望它能解决您的疑问。

回答by Ken Redler

This "solution" is reported to work, presumably because it would make those video container objects available for garbage collection (see the note below for a discussion of why deleteshouldn't be making a difference). In any case, your results are likely to vary by browser:

据报道,这个“解决方案”有效,大概是因为它会使这些视频容器对象可用于垃圾收集(请参阅下面的注释以讨论为什么delete不应该有所作为)。无论如何,您的结果可能因浏览器而异:

$(container_selector).children().filter("video").each(function(){
    this.pause(); // can't hurt
    delete this; // @sparkey reports that this did the trick (even though it makes no sense!)
    $(this).remove(); // this is probably what actually does the trick
});
$(container_selector).empty();


Note:There's no doubt that the deletekeyword is specified only to remove properties from objects (as others have pointed out in the comments). Logging thisto the console both before and after the delete thisline, above, shows the same result each time. delete thisshould do nothing and make no difference. Yet this answer continues to receive a trickle of votes, and people have reported that omitting delete thismakes it stop working. Perhaps there's strangeness in how some browser JS engines implement delete, or an unusual interaction between a browser's deleteand what jQuery is doing with this.

注意:毫无疑问,delete指定关键字只是为了从对象中删除属性(正如其他人在评论中指出的那样)。thisdelete this上面的行之前和之后记录到控制台,每次都显示相同的结果。delete this应该什么都不做,没有区别。然而,这个答案继续获得少量选票,并且人们报告说省略delete this会使其停止工作。也许某些浏览器 JS 引擎的实现方式有些奇怪delete,或者浏览器的 JS 引擎delete与 jQuery 使用this.

So, just be aware, if this answer solves your problem, that if it does work, it's not clear why that's the case, and it's just as likely to stop working for any number of reasons.

因此,请注意,如果此答案解决了您的问题,并且它确实有效,则不清楚为什么会这样,并且由于多种原因而停止工作的可能性也一样。

回答by Bishoy Hanna

To reset the video to Blank without removing it

将视频重置为空白而不删除它

$("#video-intro").first().attr('src','')

It stops the video

它停止视频

回答by Arnaud Leyder

delete(this); 

is nota solution. If it worked for x or y it is a browser misbehaviour. Read here:

不是一个解决方案。如果它适用于 x 或 y,则是浏览器的不当行为。在这里阅读:

The delete operator removes a property from an object.

delete 运算符从对象中删除属性。

The truth is that some browsers (Firefox for example) will cache in memory the video buffer when autoplay property is on. It is a pain to deal with.

事实是,当自动播放属性打开时,某些浏览器(例如 Firefox)会将视频缓冲区缓存在内存中。处理起来很痛苦。

Removing the video tag from the DOM or pausing it can only produce unstable results. You have to unload the buffer.

从 DOM 中移除 video 标签或暂停它只会产生不稳定的结果。您必须卸载缓冲区。

var video = document.getElementById('video-id');
video.src = "";

My experiment shows that it is done as so but unfortunately this is browser implementation not completely specified by the spec. You do not need to call load() after src change. When changing the src of a video tag you implicitly call a load() on it, this is stated in the W3C spec.

我的实验表明它是这样做的,但不幸的是,这是规范未完全指定的浏览器实现。您不需要在 src 更改后调用 load() 。在更改视频标签的 src 时,您隐式调用了一个 load(),这在 W3C 规范中有所说明。

回答by sparkey0

Just to clarify for anyone trying this later, the solution was this: (confirmed with h264 videos in Safari 5.0, untested in FF/opera yet)

只是为了向稍后尝试此操作的任何人澄清,解决方案是这样的:(已在 Safari 5.0 中使用 h264 视频确认,尚未在 FF/opera 中进行测试)

$(container_selector).children().filter("video").each(function(){
    this.pause();
    delete(this);
    $(this).remove();
});
$(container_selector).empty();

回答by Paul Annekov

This snippet doesn't do any effecient DOM manipulations (no tag removal) and doesn't fire errorevent for <video>unlike this answer:

此代码段不执行任何有效的 DOM 操作(不删除标签),并且不会触发与此答案不同的error事件:<video>

var video = document.getElementById('video');
video.removeAttribute('src');
video.load();

Furthermore, it doesn't fire loadstartevent. And it's like it should work - no video, no load start.

此外,它不会触发loadstart事件。就像它应该工作一样 - 没有视频,没有加载开始。

Checked in Chrome 54 / FF 49.

已检查 Chrome 54 / FF 49。

回答by Quan Quan

var video = document.getElementById('video');
        if (video.firstChild) {
            video.removeChild(video.firstChild);
            video.load();
        }

回答by Ganzert

ok, here's a simple solution which certainly works:

好的,这是一个简单的解决方案,它肯定有效:

var bodypage = document.getElementsByTagName('body')[0];
var control_to_remove = document.getElementById('id_of_the_element_here');
bodypage.removeChild(control_to_remove);

回答by BBaysinger

I've encountered this problem on a more complicated level where we are loading ~80 videos on a page, and having problems with memory management in IE and Edge. I posted our solution on a similar question I asked specifically about our issue: https://stackoverflow.com/a/52119742/1253298

我在更复杂的层面上遇到过这个问题,我们在一个页面上加载了大约 80 个视频,并且在 IE 和 Edge 中遇到了内存管理问题。我在一个类似的问题上发布了我们的解决方案,我专门询问了我们的问题:https: //stackoverflow.com/a/52119742/1253298