背景:有个需求,需要接收一个包含了好几个窗口的视频流截取其中一个展示给用户。
HTML:一个video标签接收原始流,一个video标签用于展示效果,一个canvas用于裁切,其中canvas的长宽就是裁切之后的长宽
<body>
<div>↓裁切后↓</div>
<video id="video"></video>
<div>↓原始流↓</div>
<video id="oldVideo"></video>
<div>↓裁切canvas↓</div>
<canvas id="canvas" width="100" height="100"></canvas>
</body>
JS:这里我使用浏览器的共享窗口模拟原始流
<script type="text/javascript">
//这里先获取到上面的HTML元素
const canvas = document.getElementById('canvas');
const oldVideo = document.getElementById('oldVideo');
const video = document.getElementById('video');
//创建一个画布对象
const ctx = canvas.getContext('2d');
//这里是需要裁切获得的画面的左上角坐标
const x = 0;
const y = 0;
//获取屏幕流
navigator.mediaDevices.getDisplayMedia({
video: true,
audio: false
}).then(function (stream) {
//将屏幕流赋值给oldVideo
oldVideo.srcObject = stream;
oldVideo.play();
}).catch(function (err) {
//处理错误
console.log(err);
});
//当oldVideo播放时绘制到canvas上
oldVideo.addEventListener('play', function () {
var draw = async function () {
if (oldVideo.paused || oldVideo.ended) return;
//这里将oldVideo的画面绘制到canvas上
//ctx.drawImage(oldVideo,左上角的width,左上角的height, canvas.width, canvas.height,0,0, canvas.width, canvas.height);
ctx.drawImage(oldVideo, x, y, canvas.width, canvas.height,0,0, canvas.width, canvas.height);
//requestAnimationFrame可以控制每帧执行
//这里我们使用它来循环绘制
requestAnimationFrame(draw);
};
requestAnimationFrame(draw);
//获取canvas的画面流
const cstream = canvas.captureStream();
//将canvas的画面流赋值给video
video.srcObject = cstream;
video.play();
});
</script>
效果:
如果只需要展示最终结果给canvas和oldVideo给一个style="display: none;"就可以了
<body>
<div>↓裁切后↓</div>
<video id="video"></video>
<div style="display: none;">↓原始流↓</div>
<video id="oldVideo" style="display: none;"></video>
<div style="display: none;">↓裁切canvas↓</div>
<canvas id="canvas" width="100" height="100" style="display: none;"></canvas>
</body>
效果: