I have a video that the client wants to sit "seamlessly" in the website. The background HEX color of the video matches the HEX background color of the website, and renders as such in some browsers, some versions, some of the time?
What is most curious is Chrome renders the background of the video differently, until you open the color picker. Then they suddenly match. To be clear, it only fixes it once I open the color picker, not the debugger (read: this not a repainting issue).
Firefox renders differently when I first navigate to the site, but if I hit cmd+r, it becomes perfectly seamless.
Take a look at the screenshots - they say more than I can with words.
I'm in the process of convincing the client to change to white background for the video as that will certainly "fix" it, but I'm super curious as to what /why this is happening.
Any insights from you wizards out there?
Codepen: http://codepen.io/anon/pen/zrJVpX
<div class="background" style="background-color: #e1dcd8; width: 100%; height: 100%;"> <div class="video-container"> <video id="video" poster="" width="90%" height="auto" preload="" controls style="margin-left: 5%; margin-top: 5%;"> <source id="mp4" src="http://bigtomorrowdev.wpengine.com/wp-content/themes/bigtomorrow/images/videos/bt-process.mp4" type="video/mp4"> <source id="webm" src="http://bigtomorrowdev.wpengine.com/wp-content/themes/bigtomorrow/images/videos/bt-process.webm" type="video/webm"> <source id="ogg" src="http://bigtomorrowdev.wpengine.com/wp-content/themes/bigtomorrow/images/videos/bt-process.ogv" type="video/ogg"> We're sorry. This video is unable to be played on your browser. </video> </div> </div>
Check the style inspector to make sure background-color is not being overridden. You might want to include your stylesheet after bootstrap. Don't load your external script files within divs. That's not necessary, It should either go before the closing body tag or in the head section.
Colors in HTML. a color name. HTML used to recognize 16 color names ("black", "white", "gray", "silver", "maroon", "red", "purple", "fushsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", and "aqua"), but new browsers can recognize 147 CSS3 color names.
The issue is not solely browser dependent but render dependent. As soon as the browser renders the video with hardware acceleration the GPU preferences affect the color.
For instance, if you are using an Nvidia graphics card, you can change the color preferences in the Nvidia Control Panel. Desktop monitors usually use the full RGB range from 0 to 255, but you can also configure the limited RGB range from 16 to 235. The limited range is generally used by TVs.
On the one hand graphic card drivers sometimes default the color range of desktop monitors to the limited RGB range. On the other hand users may change this value themselves. Since you can't influence the user's browser settings nor the graphic card driver settings, there will always be differences for distinct users.
Full RGB range -> limited RGB range #000000 becomes #161616 #081F3C becomes #172A43 #FFFFFF becomes #EBEBEB
I've tested it with Chrome, Chrome on Smartphone, Edge, Firefox and Internet Explorer 11. Edit: the tests are from 2017, but as mentioned in the comments by Jomal Johny, it doesn't work in IE11 anymore. After a test, I can confirm, that it doesn't work in IE11 in 2021.
As soon as the video is ready to be played or played back, check the first pixel of the video and change the background color of the surrounding container accordingly. This will work regardless of browser settings and rendering configuration.
This is the code:
<!doctype html> <html> <head> <title>Video</title> <script> function isColorInRange(expectedColor, givenColor) { const THRESHOLD = 40; for (var i = 0; i < 3; i++) { if (((expectedColor[i] - THRESHOLD) > givenColor[i]) || ((expectedColor[i] + THRESHOLD) < givenColor[i])) { return false; } } return true; } function setVideoBgColor(vid, nativeColor) { if (vid) { var vidBg = vid.parentElement; if (vidBg) { // draw first pixel of video to a canvas // then get pixel color from that canvas var canvas = document.createElement("canvas"); canvas.width = 1; canvas.height = 1; var ctx = canvas.getContext("2d"); ctx.drawImage(vid, 0, 0, 1, 1); var p = ctx.getImageData(0, 0, 1, 1).data; //console.log("rgb(" + p[0] + "," + p[1] + "," + p[2] + ")"); if (isColorInRange(nativeColor, p)) { vidBg.style.backgroundColor = "rgb(" + p[0] + "," + p[1] + "," + p[2] + ")"; } } } } function setVideoBgColorDelayed(vid, nativeColor) { setTimeout(setVideoBgColor, 100, vid, nativeColor); } </script> <style> body { margin: 0; } #my-video-bg { height: 100vh; display: flex; align-items: center; background-color: rgb(8,31,60); } #my-video { max-width: 100%; margin: 0 auto; } </style> </head> <body> <div id="my-video-bg"> <video id="my-video" preload="metadata" onplay="setVideoBgColorDelayed(this,[8,31,60])" oncanplay="setVideoBgColorDelayed(this,[8,31,60])" controls> <source src="video.mp4" type="video/mp4"> </video> </div> </body> </html>
The play
event and setVideoBgColorDelayed
function are for browsers like Internet Explorer, which sometimes already fire the canplay
event, although the video data is not yet available to the drawImage
function of the canvas.
The function isColorInRange
prevents harsh background changes, if the canplay
or play
events are fired before the canvas can get the pixel.
It is important, that the functions are defined before the video element. If you load up the javascript at the end of the document, as it is often suggested because of page loading performance, then the approach won't work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With