Как удалить зацикливание при создании HTML5-video, чтобы использование рабочей памяти не увеличивалось?

140
17 января 2019, 04:10

Мне нужно, чтобы между воспроизведением несколько идущих друг за другом видео не было прерываний и поэтому я с помощью свойства preload = 'auto' во время воспроизведения первого видео подгружаю уже следующее видео и затем сменяю одно на другое посредством функции Node.replaceChild().

Но трудность заключается в том, что где-то происходит зацикливание и если открыть в Windows диспетчер задач на вкладке производительность, то мы увидим, что использование рабочей памяти постоянно увеличивается и видео при воспроизведении тормозят (не каждое и не всегда). Всего этого не должно быть и не наблюдается в самом последнем примере (внизу вопроса).

//функция используется в EventListener "loadedmetadata", в createVideoElement() 
function createNextVideo() 
{ 
    if(++activeVideo == 2) 
        activeVideo = 0; 
 
    this.nextVideoElement = createVideoElement(); 
    this.nextVideoElement.src = vidSources[activeVideo]; 
    this.nextVideoElement.pause(); 
} 
 
//функция используется в EventListener "ended", в createVideoElement() 
function startNextVideo() 
{ 
    var oldVideo = videoContainer.firstChild; 
     
    this.nextVideoElement.play(); 
    videoContainer.replaceChild(this.nextVideoElement, oldVideo); 
     
    oldVideo.removeEventListener('loadedmetadata', createNextVideo); 
    oldVideo.removeEventListener('ended', startNextVideo); 
} 
 
//функция используется в createNextVideo() 
function createVideoElement() 
{ 
    var video = document.createElement('video'); 
    video.preload = 'auto'; //но без autoplay, т.к. оно отменяет preload 
 
    video.addEventListener('loadedmetadata', createNextVideo); 
    video.addEventListener('ended', startNextVideo); 
 
    return video 
} 
 
var videoContainer = document.getElementById('videoContainer'), 
    activeVideo = 0, 
    vidSources = 
    [ 
        "http://www.w3schools.com/html/mov_bbb.mp4", 
        "http://www.w3schools.com/html/movie.mp4" 
    ]; 
 
var vidElement = createVideoElement(vidSources[0]); 
vidElement.autoplay = true; 
vidElement.src = vidSources[0]; 
videoContainer.appendChild(vidElement);
video{background-color: red}
<div id="videoContainer"></div>

Как этот код выглядел до попытки решить эту задачу:

function createVideoElement() 
{ 
    var video = document.createElement('video'); 
    video.preload = 'auto'; 
 
    video.addEventListener('loadedmetadata', function(e) 
    { 
        if(++activeVideo == 2) 
            activeVideo = 0; 
 
        this.nextVideoElement = createVideoElement(); 
        this.nextVideoElement.src = vidSources[activeVideo]; 
        this.nextVideoElement.pause(); 
    }); 
 
    video.addEventListener('ended', function(e) 
    { 
        this.nextVideoElement.play(); 
        videoContainer.replaceChild(this.nextVideoElement, videoContainer.firstChild); 
    }); 
 
    return video 
} 
 
var videoContainer = document.getElementById('videoContainer'), 
    activeVideo = 0, 
    vidSources = 
    [ 
        "http://www.w3schools.com/html/mov_bbb.mp4", 
        "http://www.w3schools.com/html/movie.mp4" 
    ]; 
 
var vidElement = createVideoElement(vidSources[0]); 
vidElement.autoplay = true; 
vidElement.src = vidSources[0]; 
videoContainer.appendChild(vidElement);
video{background-color: red}
<div id="videoContainer"></div>

Как мне кажется, в самом первом примере видео тормозит немного меньше, но не намного. Я надеюсь, что этот код более прост для понимания, нежели предыдущий.

Тот самый последний пример:

Чтобы развеять ваши сомнения (если у кого-то такие есть) о том, что с этими видео что-то не так, в нижеследующем примере вы можете убедиться, что с этими видео всё в порядке:

var video = document.querySelector('video'), 
    activeVideo = 0; 
    videoSources = 
    [ 
        "http://www.w3schools.com/html/mov_bbb.mp4", 
        "http://www.w3schools.com/html/movie.mp4" 
    ]; 
 
video.addEventListener('ended', function(e) 
{ 
    if(++activeVideo == videoSources.length) 
        activeVideo = 0; 
 
    video.src = videoSources[activeVideo]; 
    video.play(); 
});
video { background-color: red }
<video src="http://www.w3schools.com/html/mov_bbb.mp4" autoplay></video>

В этом примере, как вы видите, возникают прерывания между воспроизведением видео и именно поэтому мне пришлось придумать вышеследующее решение, у которого теперь другие трудности / ошибки.

Итак, мне нужно решить такие задачи:

  1. Как удалить зацикливание так, чтобы освобождалась память, а не увеличивалась как сейчас?
  2. Как сделать так, чтобы видео при воспроизведении не тормозили? Возможно даже, что с удалением зацикливания это исчезнет.

Если есть вопросы, то, пожалуйста, спрашивайте!

Пожалуйста, помогите решить эти задачи!

Answer 1

В общем всё решил сам. Нужно просто было удалить постоянное создание новых видео объектов, и оставить только два: проигрываемый и следующий (подгружаемый). Также использование события onloadedmetadata было неправильным, т.к. при его использовании мы получаем беЗконечный цикл подгрузки.

Вместо него взял событие onplaying. Теперь всё работает без затормаживания и память тоже не перегружается.

var videoContainer = document.getElementById('videoContainer'), 
    nextActiveVideo = 0, 
    nextVideo, 
    videoObjects = 
    [ 
        document.createElement('video'), 
        document.createElement('video') 
    ], 
    vidSources = 
    [ 
        "http://www.w3schools.com/html/mov_bbb.mp4", 
        "http://www.w3schools.com/html/movie.mp4" 
    ]; 
 
videoObjects[0].inx = 0; //установить index 
videoObjects[1].inx = 1; 
 
initVideoElement(videoObjects[0]); 
initVideoElement(videoObjects[1]); 
 
videoObjects[0].autoplay = true; 
videoObjects[0].src = vidSources[0]; 
videoContainer.appendChild(videoObjects[0]); 
 
videoObjects[1].style.display = 'none'; 
videoContainer.appendChild(videoObjects[1]); 
 
function initVideoElement(video) 
{ 
    video.preload = 'auto'; //но без autoplay, т.к. оно отменяет preload 
 
    //loadedmetadata неправильно, т.к. при его использовании мы получаем беЗконечный цикл 
    video.onplaying = function(e) 
    { 
        if(++nextActiveVideo == 2) 
            nextActiveVideo = 0; 
 
        //заменяем video elements друг на друга: 
        if(this.inx == 0) 
            nextVideo = videoObjects[1]; 
        else 
            nextVideo = videoObjects[0]; 
 
        nextVideo.src = vidSources[nextActiveVideo]; 
        nextVideo.pause(); 
    }; 
 
    video.onended = function(e) 
    { 
        this.style.display = 'none'; 
        nextVideo.style.display = 'block'; 
        nextVideo.play(); 
    }; 
}
video{background-color: red}
<div id="videoContainer"></div>

READ ALSO
Actions и JavaScript в Фотошопе

Actions и JavaScript в Фотошопе

В фотошоп есть такая очень удобная штука, как Batch, где с ее помощью, можно картинки из одной папки, обработать с помощью Action и сразу сохранить...

264
Проблема с require

Проблема с require

Имеется у меня 2 файла: BinaryTreejs и index

145
Передать в Google Api кастомные параметры

Передать в Google Api кастомные параметры

Как реализовать функцию, которая будет принимать в аргументе Email, subject, text, и передавать их в сообщение, которое отправляется через GMail Api? На javascript...

182
Парсинг класа - js

Парсинг класа - js

есть вот такой кусочек скрипта, который получает h3 с классом "r"и выводит true/false, но теперь r есть всегда и я хочу сделать так - если один r - это...

212