深水
深水
发布于 2024-07-19 / 30 阅读
0
0

使用canvas对视频流进行裁切

背景:有个需求,需要接收一个包含了好几个窗口的视频流截取其中一个展示给用户。

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>

效果:


评论