# canvas 对视频处理# 1. 使用 canvas 动态截取视频# 1. 截取画面1 2 3 4 5 6 7 8 9 10 11 //可以使用drawImage截取视频当前播放的这一帧画面。 this.ctx.drawImage(video,0,0,width,height) //与处理图片一样可以使用getImageData获取某一帧的画面的rgba数据 let data = this.ctx.getImageData(0,0,width,height) //处理后使用putImageData将某画面绘制到canvas上。 this.ctx.putImageData(data,0,0) 最后绘制时注意,视频的大小以及画布的大小,如果视频大于画布的大小可以考虑使用scale缩小坐标系,不过这样会导致画面变糊,不建议这样解决。众所周知,canvas有两个宽高,一个是画布的宽高,这个获取dom后设置即可,另一个是展示的宽高,这个用style设置即可。先获取视频的大小,将画布的大小设置成视频的大小,由于展示的画布大小小于视频这时会自动对画布的内容缩小。 video.onloadeddata=()=>{ canvas.width = video.videoWidth canvas.height = video.videoHeight }//视频加载完成后触发的一个事件
# 2. canvas 处理视频1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 //绘制视频 function record(){ ctx.drawImage(video,0,0) //绘制视频 setTimeout(()=>{ record() },16) //每隔16ms调用自己 } 既然都拿到视频画面了,可以对视频每一帧处理,比如将图片变为灰度图片。 function record(){ ctx.drawImage(video,0,0) //绘制视频 let imageData = ctx.getImageData(0,0,canvas.width,canvas.height) for(let i=0;i<imageData.data.length;i+=4){ let r = imageData.data[i] let g = imageData.data[i+1] let b = imageData.data[i+2] let avg = .299 * r + .587 * g + .114 * b imageData.data[i] = avg imageData.data[i+1] = avg imageData.data[i+2] = avg } ctx.putImageData(imageData,0,0) setTimeout(()=>{ record() },16) //每隔16ms调用自己 }//不过这样处理之后,绘制的视频掉帧严重。
# 3. 合成视频如果有一段绿幕视频,只要将这个画面用 drawImage 绘制,然后用 getImageData 获取画面的 rgba 数据,将所有纯绿色的像素点即 rb 为 0,g 为 255 的像素点的透明度改为 0 即完全透明,再将这个画面绘制到另一个视频即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <video src="./video/1.mp4" id="video" style="width: 600px; height: 400px;" controls></video> <video src="./video/蓝幕.mp4" id="blue" style="width: 600px; height: 400px;" controls></video> <button id="play">播放</button> <canvas id="canvas" style="width: 600px; height: 400px;"></canvas> let video = document.querySelector('#video') let blue = document.querySelector('#blue') let play = document.querySelector('#play') let canvasblue = document.createElement('canvas') let canvas = document.querySelector('#canvas') let ctx = canvas.getContext('2d') let ctxblue = canvasblue.getContext('2d') //视频加载完成后,将画布的宽高设置成视频的宽高 blue.onloadeddata = ()=>{ canvasblue.width = blue.videoWidth canvasblue.height = blue.videoHeight } video.onloadeddata = ()=>{ canvas.width = video.videoWidth canvas.height = video.videoHeight } play.addEventListener('click',()=>{ blue.play() video.play() }) video.addEventListener('play',()=>{ setInterval(()=>{ ctxblue.drawImage(blue,0,0) //用画布绘制蓝幕视频 let data = ctxblue.getImageData(0,0,blue.videoWidth,blue.videoHeight) for(let i=0;i<data.data.length;i+=4){ if(data.data[i+2]==255) data.data[i+3] = 0 //如果像素点蓝色为255则将其变为完全透明 } ctxblue.putImageData(data,0,0) //将更改的数据绘制会原画布 ctx.drawImage(video,0,0) //绘制原视频 ctx.drawImage(canvasblue,0,0) //将绘制蓝幕的画布绘制到原视频。最后发现原视频掉帧严重。 },16) 每隔16ms绘制一次。 })
使用 canvas 处理视频 - Web API 接口参考 | MDN (mozilla.org)