javascripthtmlhtml5-videobuffering

Video stops buffering


I have a 4 videos and preloader, that should hide when all the videos is fully buffeder

<div id="preload">
    <h1>
        Download...
    </h1>
</div>
<video preload="auto" class="active">
<source src="video1.mp4" type='video/mp4;'>
</video>
<video  preload="auto">
<source src="video2.mp4" type='video/mp4;'>
</video>
<video preload="auto">
<source src="video3.mp4" type='video/mp4;'>
</video>
<video preload="auto">
<source src="video4.mp4" type='video/mp4;'>
</video>

There is the code that checks if videos is buffered

preload = [];
preloadOverlay = document.querySelector('#preload');
videos =  document.querySelectorAll("video")
    [...videos].forEach(function(video, index) {
        video.addEventListener('canplay', function(){
            let timerId = setTimeout(function tick() {
                // console.log(preload)
                // console.log(video.buffered.end(0), video.duration)
                if(preload.length < 4)
                {
                    if(video.buffered.end(0) === video.duration)
                    {
                        preload.push(index)
                    }
                    timerId = setTimeout(tick, 200);
                }
                else if(preload.length === 4)
                {
                    clearTimeout(timerId);
                    preloadOverlay.classList.add('hide');
                }
                
            }, 200);
        })  
    })

but sometimes buffering just stops, for example all the videos are 3 seconds long, but buffering stops at 2 second

i changed my code a little bit to

[...videos].forEach(function(video, index) {
    video.addEventListener("canplaythrough", function() {
        preload.push(index)
      });
      let timerId = setTimeout(function tick() {
        if(preload.length < 4)
        {
            console.log(preload)
            console.log(video.buffered.end(0), video.duration)
            timerId = setTimeout(tick, 200);
        }
        else if(preload.length === 4)
        {
            clearTimeout(timerId)
            preloadOverlay.classList.add('hide')
            layoutAnimation(timeoutClassRemover)
        }        
    }, 200);
})

but still, one or two videos does not load till the end, and stops randomly


Solution

  • I wouldn't use the timer for this task. Promises look more suitable here from my perspective.

    Also, I would recommend removing ; at the end of types video/mp4.

    Please let me know if this helps.

    // just to make the snippet working
    const testVideoUrl = 'https://r2---sn-ntqe6n7r.c.2mdn.net/videoplayback/id/97eca827be163084/itag/15/source/doubleclick/requiressl/yes/ratebypass/yes/mime/video%2Fmp4/ip/0.0.0.0/ipbits/0/expire/2144448000/sparams/expire,id,ip,ipbits,itag,mh,mime,mip,mm,mn,ms,mv,mvi,pl,ratebypass,requiressl,source/signature/160FEBC1E31299C398B4F585BB3AC111D899FB8D.4E8EB91A32577DC9954E0EB1CED4109081DE6B71/key/cms1/cms_redirect/yes/mh/Hp/mip/60.241.173.252/mm/42/mn/sn-ntqe6n7r/ms/onc/mt/1679898045/mv/m/mvi/2/pl/23/file/file.mp4'
    
    const preloadPromises = [];
    const preloadOverlay = document.querySelector('#preload');
    const videos =  document.querySelectorAll("video");
    [...videos].forEach((video, index) => {
      // just for the test the URL is assigned from the script
      video.src = testVideoUrl;
      let resolve;
      const promise = new Promise((_resolve) => {
        resolve = _resolve;
      });
      video.addEventListener('canplaythrough', resolve);
      preloadPromises.push(promise);
    });
    
    // wait for all videos to precache
    Promise.all(preloadPromises).then(() => {
      console.log('all the videos can be played through');
      // all the videos can be played through
      preloadOverlay.classList.add('hide');
    });
    <html>
      <body>
        <div id="preload">
          <h1>
            Download...
          </h1>
        </div>
        <video preload="auto" class="active">
          <source src="video1.mp4" type='video/mp4'>
        </video>
        <video  preload="auto">
          <source src="video2.mp4" type='video/mp4'>
        </video>
        <video preload="auto">
          <source src="video3.mp4" type='video/mp4'>
        </video>
        <video preload="auto">
          <source src="video4.mp4" type='video/mp4'>
        </video>
      </body>
    </html>