Как правильно разгрузить/уничтожить элемент VIDEO
Я работаю над приложением для просмотра/воспроизведения в реальном времени, которое использует <video>
объекты в браузере для воспроизведения, если доступно.
Я использую сочетание прямого javascript и jQuery,
Моя забота касается памяти. Приложение никогда не перезагружается в окне, и пользователь может смотреть много видео, поэтому управление памятью становится большой проблемой с течением времени. При тестировании сегодня я вижу, что профиль памяти прыгает по размеру видео, которое будет передаваться с каждой последующей загрузкой, и никогда не отбрасывается обратно к базовой линии.
Я пробовал следующие вещи с тем же результатом:
1 - очистить родительский контейнер, содержащий созданный элемент, например:
$(container_selector).empty();
2 - Приостановить и удалить дочерние элементы, соответствующие "видео", а затем очистить родительский контейнер:
$(container_selector).children().filter("video").each(function(){
this.pause();
$(this).remove();
});
$(container_selector).empty();
Кто-нибудь еще сталкивается с этой проблемой, и есть ли лучший способ сделать это?
Ответы
Ответ 1
Располагать видео из структуры DOM очень сложно. Это может привести к сбою браузера. Вот решение, которое помогло мне в моем проекте.
var videoElement = document.getElementById('id_of_the_video_element_here');
videoElement.pause();
videoElement.removeAttribute('src'); // empty source
videoElement.load();
это все сбросит, молчит без ошибок!
Изменение: Вот полная информация, как рекомендуется в стандарте: https://html.spec.whatwg.org/multipage/media.html#best-practices-for-authors-using-media-elements
Надеюсь, это разрешит ваш запрос.
Ответ 2
Сообщается, что это "решение" работает, по-видимому, потому, что оно сделает эти объекты видеоконтента доступными для сбора мусора (см. примечание ниже для обсуждения того, почему 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();
Примечание.. Несомненно, что ключевое слово delete
указано только для удаления свойств объектов (как указывали другие в комментариях). Ведение журнала this
на консоли как до, так и после строки delete this
, приведенной выше, каждый раз показывает один и тот же результат. delete this
ничего не должен делать и не имеет значения. Тем не менее этот ответ по-прежнему получает просачивание голосов, и люди сообщают, что исключение delete this
заставляет его перестать работать. Возможно, странность в том, как некоторые браузерные JS-механизмы реализуют delete
, или необычное взаимодействие между браузером delete
и тем, что jQuery делает с this
.
Итак, просто имейте в виду, что если этот ответ решает вашу проблему, если он работает, то не понятно, почему это дело, и он как можно скорее перестает работать по ряду причин.
Ответ 3
В reset видео в Blank без его удаления
$("#video-intro").first().attr('src','')
Он останавливает видео
Ответ 4
delete(this);
- это не решение. Если это сработало для x или y, это неправильное поведение браузера. Прочитайте здесь:
Оператор delete удаляет свойство из объекта.
По правде говоря, некоторые браузеры (например, Firefox) будут кэшировать в памяти видеобуфер, когда включено свойство автовоспроизведения. Это боль, с которой приходится иметь дело.
Удаление тега видео из DOM или приостановка его может привести к нестабильным результатам. Вы должны выгрузить буфер.
var video = document.getElementById('video-id');
video.src = "";
Мой эксперимент показывает, что это делается так, но, к сожалению, это реализация браузера, не полностью указанная spec. Вам не нужно вызывать load() после смены src. При изменении src тега видео вы неявно называете load() на нем, это указано в спецификации W3C.
Ответ 5
Просто, чтобы уточнить, для кого это было позже, решение было следующим: (подтверждено видео h264 в Safari 5.0, еще не проверено в FF/opera)
$(container_selector).children().filter("video").each(function(){
this.pause();
delete(this);
$(this).remove();
});
$(container_selector).empty();
Ответ 6
Этот фрагмент не делает никаких эффективных манипуляций с DOM (без удаления тегов) и не запускает событие error
для <video>
в отличие от этого ответа:
var video = document.getElementById('video');
video.removeAttribute('src');
video.load();
Кроме того, он не запускает событие loadstart
. И он вроде бы должен работать - нет видео, без загрузки.
Проверено в Chrome 54/FF 49.
Ответ 7
ok, здесь простое решение, которое, безусловно, работает:
var bodypage = document.getElementsByTagName('body')[0];
var control_to_remove = document.getElementById('id_of_the_element_here');
bodypage.removeChild(control_to_remove);
Ответ 8
В соответствии с этой ошибкой:
https://bugs.chromium.org/p/chromium/issues/detail?id=255456&can=2&q=255456&colspec=ID%20Pri%20M%20Stars%20ReleaseBlock%20Component%20Status%20Owner%20Summary%20OS%20Modified
это, кажется, проблема с утечкой памяти в Chrome!
Ответ 9
var video = document.getElementById('video');
if (video.firstChild) {
video.removeChild(video.firstChild);
video.load();
}
Ответ 10
Вот ответ о том, как закрыть камеру - не только пауза. Это поток, который нужно остановить, а не ссылку на видеоэлементы:
stream.stop()
Ответ 11
Не очень сложно. Просто установите свой src на ноль.
Eg: document.querySelector('#yourVideo').src = null;
Это удалит ваш атрибут видео src
. Готово.
Ответ 12
Я столкнулся с этой проблемой на более сложном уровне, когда мы загружаем ~ 80 видео на странице и испытываем проблемы с управлением памятью в IE и Edge. Я разместил наше решение по аналогичному вопросу, который я задал специально о нашей проблеме: fooobar.com/questions/16338044/...
Ответ 13
Это то, что я сделал, чтобы решить эту проблему. Я создал 2 видеоэлемента (video1 и video2). После окончания использования video1 получите значение атрибута source (src), а затем удалите video1 из DOM.
Затем установите источник видео2 (src) на любое значение, которое вы получили от видео1.
Не используйте поток из video1, поскольку он кэшируется в памяти.
Надеюсь, это поможет.
Ответ 14
Одно из решений, которое сработало для меня в AngularJS, использует следующий код:
Если вы не хотите удалять исходный URL и сбросить его до начала видео
let videoElement = $document[0].getElementById('video-id');
videoElement.pause();
videoElement.seekable.start(0);
videoElement.load();
А если вы хотите удалить источник из тега видео:
let videoElement = $document[0].getElementById('video-id');
videoElement.pause();
videoElement.src="";
videoElement.load();
Надеюсь, кто-то найдет это полезным.