前端如何製作出透明背景視頻

近期項目需求做一個透明背景的視頻疊加攝像頭的交互,於是去了解了一下透明背景視頻的實現方法。

1、webm視頻格式

首先想到的當然是先跟動畫大哥交流能否製作出透明背景的視頻,給出的答案是webm格式的視頻是可以背景透明的,OK,拿到視頻,放到項目中,chorme打開,完美播放,這也太簡單了吧,但移動端是不會同意讓你這麼輕易就播放視頻的,Safari,微信,都不支持,沒辦法,只能繼續尋找方案。

2、CSS 樣式去掉背景

利用css樣式 mix-blend-mode 混合模式,有一個屬性 screen 就是黑色和其它元素進行混合的時候表現爲透明。但這種方法有一種情況沒法解決,就是如果視頻中有元素是半透明的就無法成功了。

有關這種方法詳細描述可以參考鏈接:如何讓MP4 video視頻背景色變成透明?

3、webgl 渲染帶透明通道的視頻

首先,你需要一個這樣的視頻

或者一個這樣的視頻

儘量使得視頻尺寸寬高比爲1:2或者2:1,這樣渲染出來的視頻就是1:1大小了。然後用webgl將視頻渲染在畫布上,渲染的同時將視頻上下,或者左右進行疊加計算。

webgl渲染可以用three.js,上下疊加的代碼如下:

let videoWidth=1080; //視頻實際的寬度
//定義渲染器
var renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
    });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(new THREE.Color("lightgrey"), 0);
renderer.setSize(videoWidth, videoWidth);
//居中顯示
renderer.domElement.style.position = "absolute";
renderer.domElement.style.top = (window.innerHeight - videoWidth) / 2 + "px";
renderer.domElement.style.left = (window.innerWidth - videoWidth) / 2 + "px";
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.Camera();
scene.add(camera);
//播放視頻
var video = document.getElementById("video");
video.play();
//獲取視頻紋理
var texture = new THREE.VideoTexture(video);
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.format = THREE.RGBFormat;
//定義幾何體
var geometry = new THREE.PlaneBufferGeometry(1, 1);

//處理視頻紋理
var uniforms = {
        time: { type: "f", value: 1.0 },
        texture: { type: "sampler2D", value: texture }
    };
var material = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: 
    `varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }`,
    fragmentShader: 
    `#ifdef GL_ES
    precision highp float;
    #endif
    
    uniform float time;
    uniform sampler2D texture;
    varying vec2 vUv;
    
    void main( void ) {
      gl_FragColor = vec4(
      texture2D(texture, vec2(vUv.x, 0.5 + vUv.y/2.)).rgb,
      texture2D(texture, vec2(vUv.x, vUv.y/2.)).r
      );
    }`,
    transparent: true
});
var mesh = new THREE.Mesh(geometry, material)
scene.add(mesh);


var animate = function() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
    };
requestAnimationFrame(animate);

如果是左右,只需要改一下疊加的方向就行,代碼中的 fragmentShader 屬性改爲如下:

fragmentShader: 
    `#ifdef GL_ES
    precision highp float;
    #endif
    
    uniform float time;
    uniform sampler2D texture;
    varying vec2 vUv;
    
    void main( void ) {
      gl_FragColor = vec4(
      texture2D(texture, vec2(vUv.x/2., vUv.y)).rgb,
      texture2D(texture, vec2(vUv.x/2., vUv.y)).r
      );
    }`,

以上,完美解決視頻背景透明問題。

本文結。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章