HTML5 视频背景颜色与网站背景颜色不匹配 -- 在某些浏览器中,有时

HTML5 video background color not matching background color of website -- in some browsers, sometimes

我有一个客户想要 "seamlessly" 放在网站上的视频。视频的 HEX 背景颜色与网站的 HEX 背景颜色相匹配,并在某些浏览器、某些版本、某些时间呈现这种颜色?

最奇怪的是 Chrome 以不同方式呈现视频背景,直到您打开颜色选择器。然后他们突然匹配。需要明确的是,它只会在我打开颜色选择器而不是调试器后修复它(阅读:这不是重绘问题)。

当我第一次导航到该站点时,Firefox 呈现不同,但如果我按下 cmd+r,它就会变得完美无缝。

看看屏幕截图 - 他们说的比我能说的还要多。

我正在说服客户将视频更改为白色背景,因为这肯定会 "fix",但我非常好奇这是怎么回事/为什么会这样。

各位大侠有什么见解吗?


代码笔: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>

检查此工作 demo

将视频容器的背景颜色定义为#e1dcd8;

或将您现有的 css 替换为以下内容:

 body, html {
  height: 100%;
  margin: 0;
  padding: 0;
}
.background {
    background-color: #e1dcd8;
  width: 100%;
  height: 100%;
}

.video-container{
  background:  #e1dcd8;
}

video {
  margin-left: 5%;
  margin-top: 5%;
}

这似乎是浏览器呈现视频的基础,而不是简单的 CSS/HTML 修复。您的问题听起来类似于 this question。我打赌答案在于渲染引擎和色彩空间差异的某种组合,这可能意味着没有跨浏览器修复它的好方法。

在 firefox 上,您可以尝试调整颜色管理设置,看看是否会改变行为。这不能解决问题,但可以帮助解释问题。在 URL/search 栏中,输入 "about:config"。它应该带你到一个选项页面。页面中将出现另一个搜索栏,输入 "gfx.color_management.mode"。该选项可以取值 0、1、2。尝试将它们切换并重新加载页面(可能需要重新启动 firefox)以查看是否可以获得一致的差异。如果一开始就没有管理颜色,可能不会有任何区别。

同样,您可以尝试在 chrome 中禁用硬件加速视频解码。在chromeURL/search栏中输入"chrome://flags",然后找到标志"Disable hardware-accelerated video decode"。更改任何值,重新启动 chrome,然后再次检查颜色。

这些都不是我意识到的解决方案,这可能更适合作为评论,但我还没有代表。

导出 sRGBAdobe RGB 中的视频和图像应该可以解决此问题。我们有一个颜色配置文件 HD (1-1-1) 的视频,这导致视频背景在 Safari 中比在 Chrome 中稍微亮一些。 已在 macOS 上测试

该问题不仅取决于浏览器,还取决于渲染。一旦浏览器使用硬件加速渲染视频,GPU 首选项就会影响颜色。

例如,如果您使用的是 Nvidia 显卡,则可以在 Nvidia 控制面板中更改颜色首选项。桌面显示器通常使用从 0 到 255 的完整 RGB 范围,但您也可以配置从 16 到 235 的有限 RGB 范围。有限范围一般是电视用的

一方面,显卡驱动程序有时会将桌面显示器的颜色范围默认为有限的 RGB 范围。另一方面,用户可以自己更改此值。 由于您无法影响用户的浏览器设置或显卡驱动程序设置,因此不同的用户总会有所不同。

颜色如何受到影响:

Full RGB range -> limited RGB range
#000000 becomes #161616
#081F3C becomes #172A43
#FFFFFF becomes #EBEBEB

这是我解决这个问题的方法:

我已经在智能手机、Edge、Firefox 和 Internet Explorer 11 上使用 Chrome、Chrome 对其进行了测试。 编辑:测试是从 2017 年开始的,但正如评论中提到的那样 ,它不再适用于 IE11。经过测试,我可以确认,它在 2021 年的 IE11 中不起作用。

一旦视频准备好播放或回放,请检查视频的第一个像素并相应地更改周围容器的背景颜色。无论浏览器设置和渲染配置如何,这都会起作用。

这是代码:

<!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>

play 事件和 setVideoBgColorDelayed 函数适用于像 Internet Explorer 这样的浏览器,它们有时已经触发了 canplay 事件,尽管 [= canvas.

函数的15=]

如果 canplayplay 事件在 canvas 可以获取像素之前被触发,函数 isColorInRange 可以防止剧烈的背景变化。

重要的是,在视频元素之前定义函数。 如果您加载文档末尾的 javascript(由于页面加载性能而经常建议这样做),那么该方法将不起作用。

我觉得这里的正确解决方案是使用绿屏拍摄(您可能已经这样做了)并使用

  1. 透明 webm 视频或
  2. 使用 javascript canvas
  3. 将绿色像素替换为透明像素

可以在此处找到透明视频的示例: https://jakearchibald.com/scratch/alphavid/

如果您的背景是纯黑色或纯白色,您只需稍微增加 css 中的对比度即可完全解决问题:

filter: contrast(101%);

来自 Jack 的原创想法。

导出第二个视频,但仅限于主视频的背景颜色。所以现在你有了你的原始视频,以及第二个长度为 1 秒且只有纯色的视频。

该视频标签应具有以下内容 css:

#bg-video {
    position: fixed;
    width: 100vw;
    z-index: -1;
}

并且视频标签可以位于文档的顶部。

<body>
    <video id="bg-video" src="assets/bg.mp4" muted></video>
    <div>your main site html here</div>
</body> 

由于两个视频的导出方式相同,因此颜色在多个浏览器 and/or 操作系统上也应该呈现相同。

*请注意,您的 'background video' 应该或多或少是 square/rectangle,这样当它缩放时,它将覆盖浏览器的宽度和高度。