根据视频帧率,使用requestAnimationFrame播放动画

发布时间 2023-05-31 14:30:51作者: webHYT

当时使用webRTC进行视频通话时,通常会设置视频流的帧率,行业内一般默认帧数为15或者30,一般每秒只需要渲染15或30次

当要需要对本地视频或者远端视频流进行特殊处理时,通常会使用requestAnimationFrame方法进行再次渲染

requestAnimationFrame,这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数,以满足开发者操作动画的需求。

这个函数类似setTimeout,只调用一次。

function draw() { 
        requestAnimationFrame(draw); 
        // ... Code for Drawing the FrameRate ... 
}

递归调用,就可以实现定时器。回调函数执行次数通常是每秒 60 次。

但是,这样完全跟浏览器帧频同步了,无法根据视频帧率渲染,会造成一定程度的CPU和GPU资源的浪费

自行控制时间跨度:

var fps = 30;
var now;
var then = Date.now();
var interval = 1000/fps;
var delta;
var reqId = null;
function tick() {   regId = requestAnimationFrame(tick);   now = Date.now();   delta = now - then;   if (delta > interval) {     // 这里不能简单then=now,否则会出现细微时间差问题。例如fps=10,每帧100ms,而现在每16ms(60fps)执行一次draw。16*7=112>100,需要7次才实际绘制一次。这个情况下,实际10帧需要112*10=1120ms>1000ms才绘制完成。     then = now - (delta % interval);     draw(); // ... Code for Drawing the Frame ...   } } tick();

针对低版本浏览器再优化:

var fps = 30;
var now;
var then = Date.now();
var interval = 1000/fps;
var delta;
var reqId = null;
var timeId = null; window.requestAnimationFrame
= window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; function tick() {   if(window.requestAnimationFrame) {    reqId = requestAnimationFrame(tick);    now = Date.now();    delta = now - then;    if (delta > interval) { // 这里不能简单then=now,否则还会出现细微时间差问题。例如fps=10,每帧100ms,而现在每16ms(60fps)执行一次draw。16*7=112>100,需要7次才实际绘制一次。这个情况下,实际10帧需要112*10=1120ms>1000ms才绘制完成。      then = now - (delta % interval);      draw(); // ... Code for Drawing the Frame ...    } } else { timeId = setTimeout(tick, interval);
    draw(); } } tick();

停止动画

if(window.requestAnimationFrame){
    cancelAnimationFrame(regId)
}else{
    clearTimeout(timeId)
}

参考文档:js:指定FPS帧频,requestAnimationFrame播放动画