Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS background-image transition makes video tag buffer

I have a video tag that I want to play continuously while a user can simultaneously do stuff on the site. However I have found that if the background transitions between background images that the video starts buffering. I have a runnable example in the snippet below.

Note: The buffering does not seem to occur if the snippet is run normally, but does occur if you put the snippet in 'full page'.

function changeBackground() {
  const randomColor = '#'+Math.floor(Math.random()*16777215).toString(16);
  const element = document.getElementById('background');
  const currentOpacity = element.style.opacity;
  const currentBackground = element.style.backgroundImage;
  
  switch (currentBackground) {
    case 'url("https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png")': {
      element.style.backgroundImage = 'url("https://i5.walmartimages.ca/images/Large/428/5_r/6000195494285_R.jpg")';
      break;
    }
    case 'url("https://i5.walmartimages.ca/images/Large/428/5_r/6000195494285_R.jpg")': {
      element.style.backgroundImage = 'url("https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png")';
      break;
    }
    default: {
      break;
    }
  }
}
 
 const element = document.getElementById('background');
 element.style.backgroundImage = 'url("https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png")'
#background {
  display: flex;
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -10;
  
  background-size: contain;
  
  transition: background-image 3s ease-in-out;
}

#button {
  display: flex;
  width: 200px;
  height: 100px;
  background-color: orange;
  text-align: center;
}

#video {
  display: flex;
  position: absolute;
  top: 0;
  right: 0;
  width: 400px;
  height: 350px;
}
<div id='root' style='width: 100%; height: 500px'>
    <div id='background'></div>
    <div id='button' onClick="changeBackground()">Click me to change the background!</div>
    <video
      id='video'
      autoplay
      muted
      loop
      controls
      src="https://s3.amazonaws.com/codecademy-content/courses/React/react_video-cute.mp4"/>
</div>

What could be the cause and is there a way to prevent the video from buffering while still having a background image transition?

Edit: May be important to add that I'm on Chrome on MacOS.

Edit 2: From the responses I have gathered not everyone can reproduce the problem, so I went to an old-timey windows PC and tried it there. Found out that the background-transition was being really slow and laggy but the video kept playing without problem. It also works on safari on MacOS so this appears to be a Chrome MacOS-only problem.

like image 775
ApplePearPerson Avatar asked May 21 '19 08:05

ApplePearPerson


2 Answers

I have to admit I'm not entirely sure of what happens here... Given it's not a 100% repro case, it's also hard to be sure any workaround actually works...

But here are some comments and ideas.


It seems this happens only with .mp4 files. I could reproduce with other .mp4 videos but never with any .webm file.
So one thing you may want to try is to reencode your video in webm, it could be that Chrome's mp4 decoder has some issues.


It seems that CSS animations do not cause this issue. So you could rewrite your transition code into a CSS animation, with the major problem that you won't be able to stop it in the middle (but it seems background-transitions are bad at this anyway).

function changeBackground() {
  const element = document.getElementById('background');
  if(element.classList.contains('apple')) {
    element.classList.remove('apple');
    element.classList.add('so');
  }
  else {
    element.classList.add('apple');
    element.classList.remove('so');
  }

}
#background {
  display: flex;
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -10;
  
  background-size: contain;
  background-image: url("https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png");
}
#background.apple {
  animation: apple-to-SO 3s ease-in-out forwards;
}
#background.so {
  animation: SO-to-apple 3s ease-in-out forwards;
}
@keyframes apple-to-SO {
  from {
    background-image: url("https://i5.walmartimages.ca/images/Large/428/5_r/6000195494285_R.jpg")
  }
  to {
    background-image: url("https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png");
  }
}
@keyframes SO-to-apple {
  from {
    background-image: url("https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png");
  }
  to {
    background-image: url("https://i5.walmartimages.ca/images/Large/428/5_r/6000195494285_R.jpg")
  }
}

#button {
  display: flex;
  width: 200px;
  height: 100px;
  background-color: orange;
  text-align: center;
}

#video {
  display: flex;
  position: absolute;
  top: 0;
  right: 0;
  width: 400px;
  height: 350px;
}
<div id='root' style='width: 100%; height: 500px'>
    <div id='background'></div>
    <div id='button' onClick="changeBackground()">Click me to change the background!</div>
    <video
      id='video'
      autoplay
      muted
      loop
      controls
      src="https://s3.amazonaws.com/codecademy-content/courses/React/react_video-cute.mp4"/>
</div>

Now if you prefer js control, it seems that Web-Animations aren't affected either.

let current = 1;
const urls = [
  "https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png",
  "https://i5.walmartimages.ca/images/Large/428/5_r/6000195494285_R.jpg"
];
function changeBackground() {
  const element = document.getElementById('background');
  element.animate({
      backgroundImage: ['url(' + urls[current] + ')', 'url(' + urls[+(!current)] + ')']
      }
    , {
      duration: 3000,
      iterations: 1,
      fill: 'both'
    }
  );
  current  = (current + 1) % 2;
}
#background {
  display: flex;
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -10;
  
  background-size: contain;
  background-image: url(https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png);
}


#button {
  display: flex;
  width: 200px;
  height: 100px;
  background-color: orange;
  text-align: center;
}

#video {
  display: flex;
  position: absolute;
  top: 0;
  right: 0;
  width: 400px;
  height: 350px;
}
<div id='root' style='width: 100%; height: 500px'>
    <div id='background'></div>
    <div id='button' onClick="changeBackground()">Click me to change the background!</div>
    <video
      id='video'
      autoplay
      muted
      loop
      controls
      src="https://s3.amazonaws.com/codecademy-content/courses/React/react_video-cute.mp4"/>
</div>
like image 163
Kaiido Avatar answered Oct 09 '22 06:10

Kaiido


Try to enable / disable hardware-acceleration on Chrome.

like image 35
Marius Danciu Avatar answered Oct 09 '22 04:10

Marius Danciu