教你web前端实现抖音视频多帧延迟

最近在学习WebAssembly,因为是提升性能,所以一直在使用canvas 做一些尝试。今天就突发奇想以前看见的抖音多帧延迟的装饰,今天就来分析实现下。

在这里插入图片描述

多帧延迟

先简单分析下这个效果,假设咱们有一个视频是宽400x300, 分为100个40x30的小方格,用固定的时间间隔播放格子。

  • 视频顺序播放
async function initVideo() {
        const stream = await navigator.mediaDevices.getUserMedia({
                video: {
                    width:400,
                    height:300
                }
            });
        video = document.querySelector('video');
        video.srcObject = stream;
        video.addEventListener('loadeddata', function(){
            video.play()
            cs.width = video.videoWidth;
            cs.height = video.videoHeight;
            drawCanvas(video);
        }, false);
        });
}
  • 创建数组Array(100);
    let w = Math.floor(cs.width/obj.w);
    let h = Math.floor(cs.height/obj.h);
    list = new Array(w*h);
  • 每个时间间隔往数组里添加视频画面的区域 imageData
function getBlock () {
    let w = Math.floor(cs.width/obj.w);
    let h = Math.floor(cs.height/obj.h);
    let total = w*h;
    for(let i =0; i<w; i++){
        for(let j =0; j<h; j++) {
            if(j*w+i === index) {
                list[index] = {
                    data: ctx.getImageData(i*obj.w,j*obj.h, obj.w,obj.h),
                    x:obj.w*i,
                    y:obj.h*j
                };
                break;
            }
        }
    }
    index ++;
    if(total === index) {
        index =0;
    }
}
  • 把imageData绘制到canvas上 完毕。效果达成
function drawCanvas() {
    ctx.drawImage(video,0,0,cs.width,cs.height);
    getBlock()
    list.forEach((item) => {
      if(item['data']){
          ctx.putImageData(item['data'],item['x'],item['y']);
      }
    })
    requestAnimationFrame(drawCanvas)
}

体验地址:https://ibeeger.com/demo/keyframe.html

文章来源: 教你web前端实现抖音视频多帧延迟