воспроизводить видео в l oop, используя setTimeout - PullRequest
4 голосов
/ 11 марта 2020

Я хочу воспроизвести видео на всех oop. По какой-то причине я не хочу менять видео sr c на завершенном событии. Поэтому я создал элементы видео для каждого видео в al oop. Также у меня есть видео sr c и длительности в массиве.

вот моя идея: может быть виден только текущий тег воспроизведения видео. Другие будут скрыты. Вместо того, чтобы использовать завершенное событие, я хочу использовать функцию setTimeout. Продолжительность видео будет параметром задержки.

Но все они воспроизводятся вместе. Я не мог заставить их играть по порядку.

Вот что я сделал до сих пор:

videoArray = [
    {"video":video1.mp4, "duration": 5},
    {"video":video2.mp4, "duration": 7},
    {"video":video3.mp4, "duration": 9},
    {"video":video4.mp4, "duration": 10},
]

for (var j = 0; j < videoArray.length; j++){
    var video = document.createElement("video");
    video.src=videoArray[j];
    video.id="video-"+j;
    video.preload = "metadata";
    video.type="video/mp4";
    video.autoplay = true; 
    video.style.display="none";
    document.body.appendChild(video); 
}

for (var count = 0; count < videoArray.length; count++) {
    (function(num){
        setTimeout(function() {
            videoArray[num].video.style.display="block";
            videoArray[num].video.play();
        }, 1000 * videoArray[num].duration);
        videoArray[num].video.style.display="none";
    })(count);
}

Ответы [ 3 ]

9 голосов
/ 18 марта 2020

Отказ от ответственности

Я знаю, что вопрос был задан без события ended, но я не думаю, что установленное время ожидания - это способ go.
Подумайте о В сценарии, где у вас есть буферизация видео или замедление по какой-либо причине, ваш setTimeout будет не синхронизирован c.

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

Решение

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

Еще одним преимуществом является то, что вам не нужно знать продолжительность видео в первую очередь.

PS. прослушиватель событий, который вам нужно прослушать, это video.addEventListener("ended", callback);

Вы можете запустить код или взглянуть на рабочий пример, который я создал для вас

Рабочий пример

    const videoUrls = [
        'https://videos-play-loop.netlify.com/video1.mp4',
        'https://videos-play-loop.netlify.com//video2.mp4',
        'https://videos-play-loop.netlify.com//video3.mp4',
    ];

    const createVideo = ({id, src, width, cls = 'video', display = 'block', playbackRate = 1, muted = true, type = 'video/mp4', autoplay = false, controls = true}) => {
        const videoElement = document.createElement("video");
        videoElement.id = id;
        videoElement.src = src;
        videoElement.classList.add(src);
        videoElement.type = type;
        videoElement.autoplay = autoplay;
        videoElement.controls = controls;
        videoElement.style.display = display;
        videoElement.muted = muted;
        videoElement.playbackRate = playbackRate;
        return videoElement;
    };


    const addVideos = (container, videoUrls) => {
        const videos = videoUrls.map((url, index) => {
            const first = index === 0;
            const display = first ? 'block' : 'none';
            return createVideo({id: `video-${index}`, src: url,display, width: 640, autoplay: first, playbackRate: 3});
        });
        videos.forEach((video, index) => {
            const last = index === videos.length - 1;
            const playNext = (element) => {
                element.target.style.display = "none";
                const nextElementIndex = last ? 0 : index + 1;
                const nextElement = videos[nextElementIndex];
                nextElement.autoplay = true;
                nextElement.style.display="block";
                nextElement.load();
            };
            video.addEventListener("ended", playNext);
            container.appendChild(video)
        });
    };
    const videoWrapper = document.getElementById('video-wrapper');
    addVideos(videoWrapper, videoUrls);
#video-wrapper video {
    max-width: 600px;
}
<div id="video-wrapper"></div>

Рабочий раствор с setTimeout (используйте решение выше)

const videoUrls = [{
    url: `https://videos-play-loop.netlify.com/video3.mp4`,
    duration: 3,
  },
  {
    url: `https://videos-play-loop.netlify.com/video2.mp4`,
    duration: 4
  },
  {
    url: `https://videos-play-loop.netlify.com/video1.mp4`,
    duration: 5
  }
];


const createVideo = ({
  id,
  src,
  width,
  cls = 'video',
  display = 'block',
  duration,
  playbackRate = 1,
  muted = true,
  type = 'video/mp4',
  autoplay = false,
  controls = true
}) => {
  const videoElement = document.createElement("video");
  videoElement.id = id;
  videoElement.src = src;
  videoElement.classList.add(src);
  videoElement.type = type;
  videoElement.autoplay = autoplay;
  videoElement.controls = controls;
  videoElement.style.display = display;
  videoElement.muted = muted;
  videoElement.playbackRate = playbackRate;
  videoElement.setAttribute('data-duration', duration);
  return videoElement;
};

const playNext = (videos, index) => {
  const current = videos[index];
  const activeVideoDuration = parseInt(current.dataset.duration) * 1000;
  setTimeout(() => {
    const last = index === videos.length - 1;
    current.style.display = "none";
    current.pause();
    const activeVideoIndex = last ? 0 : index + 1;
    const next = videos[activeVideoIndex];
    next.autoplay = true;
    next.style.display = "block";
    next.load();
    next.play();
    playNext(videos, activeVideoIndex);
  }, activeVideoDuration);
};


const addVideos = (container, videoUrls) => {
  const videos = videoUrls.map((video, index) => {
    const {
      url,
      duration
    } = video;
    const first = index === 0;
    const display = first ? 'block' : 'none';
    return createVideo({
      id: `video-${index}`,
      src: url,
      duration,
      display,
      width: 640,
      autoplay: first,
    });
  });

  videos.forEach(video => container.appendChild(video));
  playNext(videos, 0);
};

const videoWrapper = document.getElementById('video-wrapper');
addVideos(videoWrapper, videoUrls);
#video-wrapper video {
  max-width: 600px;
}
<div id="video-wrapper"></div>
1 голос
/ 14 марта 2020

Вы можете хранить продолжительность видео в переменной и накапливать эту переменную с предыдущей продолжительностью видео и установить ее длительность setTimeOut.

Обратите внимание, что время видео указано в секундах. И для первого воспроизведения видео пользователь должен взаимодействовать, иначе видео не будет воспроизводиться.

Рабочий пример:

function startVideos(event) {
 event.target.style.display= "none";
        (function() {
          videoArray = [
            {
              video:
                "http://techslides.com/demos/sample-videos/small.mp4",
              duration: 5
            },
            {
              video:
                "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",
              duration: 60
            },
            {
              video:
                "https://mobamotion.mobatek.net/samples/sample-mp4-video.mp4",
              duration: 120
            },
            {
              video:
                "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
              duration: 600
            }
          ];

          let videArrayElem = [];

          for (var j = 0; j < videoArray.length; j++) {
            var video = document.createElement("video");
            video.src = videoArray[j].video;
            video.id = "video-" + j;
            video.preload = "metadata";
            video.type = "video/mp4";
            video.autoplay = false;
            video.controls= true;
            video.style.display = "none";
            videArrayElem.push(video);
            document.body.appendChild(video);
          }

          let prviousVideoDuration = 0;
          for (var count = 0; count < videoArray.length; count++) {
            (function(num) {
              setTimeout(function() {
                videArrayElem[num].style.display = "block";
                videArrayElem[num].play();
              }, prviousVideoDuration);
              prviousVideoDuration += 1000 * videoArray[num].duration;
              videArrayElem[num].style.display = "none";
            })(count);
          }
        })();
      }
video {
        height: 100px;
        width: 100px;
        display: inline-block;
        margin: 4px;
        float: left;
      }
<button type="button" onclick="startVideos(event)">Start Video Demo</button>
0 голосов
/ 14 марта 2020

Помимо фактов, что вы пытаетесь достичь чего-то странного, и что ваш пример кода не будет компилироваться. Как я вижу, у вас это есть. Единственное, чего не хватает, это pause() и display = "none". С минимальными правками у вас есть то, что вам нужно.

const videoArray = [
    {"video":"video1.mp4", "duration": 5}, // of cause you need "" 
    {"video":"video2.mp4", "duration": 7},
    {"video":"video3.mp4", "duration": 9},
    {"video":"video4.mp4", "duration": 10},
]

for (let j = 0; j < videoArray.length; j++){
    const video = document.createElement("video");
    // you need to save DOM nodes somewhere to use them in the second loop
    videoArray[j].video_el = video
    video.src=videoArray[j].video; // `.video` is added
    video.id="video-"+j;
    video.preload = "metadata";
    video.type="video/mp4";
    video.autoplay = true; 
    video.style.display="none";
    document.body.appendChild(video); 
}

for (var count = 0; count < videoArray.length; count++) {
    (function(num){
        setTimeout(function() {
            // add this to hide previous video node and stop video from playing 
            if( num ) {
                videoArray[num-1].video_el.style.display="none";
                videoArray[num-1].video_el.pause()
            }
            // videoArray[num].video - is a string, not a DOM node
            // so, you need to change this:
            // videoArray[num].video.style.display="block";
            // for this:
            videoArray[num].video_el.style.display="block";
            // no need. `autoplay` is set to `true` in the first loop
            // videoArray[num].video_el.play();
        }, 1000 * videoArray[num].duration);
        // no need. already done in the first loop
        // videoArray[num].video_el.style.display="none";
    })(count);
}

Но много fl aws:

  1. setTimeout все равно о задержках в сети и других проблемах, связанных с временем, поэтому, скорее всего, ваша видеопоследовательность не будет воспроизводиться без проблем.
  2. Из-за первого потока и потому, что я сомневаюсь, что значения duration являются точными, вы должны использовать pause().
  3. Как отметил @IslamElshobokshy в комментариях к вашему вопросу, использование play/pause не так просто.
  4. Если пользователь откроет страницу и больше ничего не сделает, вы получите:

    Uncaught (в обещании) DOMException: play () не удалось, потому что пользователь не взаимодействовал с документом первым.

    в Chrome. И

    Автозапуск разрешен только в случае одобрения пользователем, активации сайта пользователем или отключения звука.
    NotAllowedError: метод воспроизведения не разрешен ни пользовательским агентом, ни платформа в текущем контексте, возможно, потому что пользователь отказал в разрешении.

    в Firefox.

Так что вам, вероятно, будет лучше с * Событие 1039 * в конце концов и с атрибутом muted (для смягчения последней проблемы):

for (let j = 0; j < videoArray.length; j++){
    const video = document.createElement("video")
    videoArray[j].video_el = video

    video.src      = videoArray[j].video
    video.id       = "video-"+j
    video.preload  = "metadata"
    video.type     = "video/mp4"
    video.autoplay = true

    // show the first video right away
    if( j !== 0 ) video.style.display = "none"
    // set muted attribute
    video.muted = "muted"
    // play next video after the previous had ended
    video.addEventListener('ended', (num => function() {
        this.style.display = "none";
        if( num !== videoArray.length-1 ) {
            videoArray[num+1].video_el.style.display="block";
            // only needed if `muted` is not set 
            videoArray[num+1].video_el.play();
        }
    })(j), false);

    document.body.appendChild(video); 
}

Если атрибут muted не является опцией, вы можете добавить некоторые прослушиватели событий в body позвонить play() на первом видео, как только пользователь начнет взаимодействие со страницей. А может быть, вы хотели бы узнать больше о autoplay здесь: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide

...