通过webrtc+canvas+css实现简单的电脑滤镜拍照效果

这里我们用的是webrtc中的MediaDevices.getUserMedia()的浏览器api进行的效果实现,MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道类型。

它返回一个Promise对象,成功后会resolve回调一个MediaStream对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promisereject回调一个 PermissionDeniedError 或者 NotFoundError

代码:

HTML:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>webrtc实现拍照和滤镜</title>
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <div id="container" style="width: fit-content;height: fit-content;position: relative;">
        <video id="video" src=""></video>
        <div id="filter" class="filter"></div>
    </div>
    <select id="select">
        <option value="">无滤镜</option>
        <option value="style1">滤镜1</option>
        <option value="style2">滤镜2</option>
        <option value="style3">滤镜3</option>
    </select>

    <h3>截图展示</h3>
    <button id="snap">截图</button>
</body>
<script src="./index.js"></script>
</html>

js:

javascript 复制代码
//获取视频流

const constraints = {
    video: {
        width: { min: 300, ideal: 600, max: 900 },
        height: { min: 300, ideal: 600, max: 900 },
        frameRate: { ideal: 60, max: 120 }, //帧率
    }
}

navigator
    .mediaDevices
    .getUserMedia(constraints)
    .then(function (stream) {
        const video = document.querySelector('video')
        video.srcObject = stream;
        video.onloadedmetadata = function (e) {
            video.play();
        }
    })
    .catch(function (err) {
        console.log("启动失败", err)
    })

//设置视频流滤镜
const video = document.querySelector('.filter')
const selectVal = document.querySelector('#select')
selectVal.addEventListener('change', () => {
    video.className = 'filter' // 清空之前的类名
    if (selectVal.value) {
        video.classList.add(selectVal.value) // 添加新的类名
    }
})

const snapButton = document.querySelector('#snap');
snapButton.addEventListener('click', () => {
    const canvas = document.createElement('canvas')
    const video = document.getElementById('video');
    const filterDiv = document.getElementById('filter');
    console.log(video,filterDiv)
    const ctx = canvas.getContext('2d');

    // 设置 Canvas 的宽高与容器相同
    const container = document.getElementById('container');
    canvas.width = container.offsetWidth;
    canvas.height = container.offsetHeight;

    // 绘制视频的当前帧
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

    // 绘制滤镜层
    ctx.fillStyle = window.getComputedStyle(filterDiv).backgroundColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 导出图像并显示
    const imgData = canvas.toDataURL('image/png');
    const img = document.createElement('img');
    img.src = imgData;
    document.body.appendChild(img);
})

这里注意: 报错为OverconstrainedError时,看一下自己分辨率是否过大

css:

css 复制代码
:root {
    --back-style: unset;
}

.filter {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: var(--back-style);
    z-index: 2;
    pointer-events: none;
}

.style1 {
    --back-style: rgba(0, 0, 0, 0.2);
}

.style2 {
    --back-style: rgba(255, 255, 255, 0.2);
}

.style3 {
    --back-style: rgba(0, 0, 255, 0.2);
}
相关推荐
_洛_神14 小时前
Webrtc编译官方示例实现视频通话
音视频·webrtc
EasyCVR16 小时前
跨平台IPC通信、嵌入式WebRTC轻量化引擎:解析EasyRTC在ARM/Linux平台的性能突破
linux·arm开发·webrtc
GDAL17 小时前
WebRTC协议全面教程:原理、应用与优化指南
webrtc
m0_748240022 天前
WebRTC实现双端音视频聊天(Vue3 + SpringBoot)
spring boot·音视频·webrtc
TSINGSEE3 天前
EasyRTC轻量级Webrtc音视频通话SDK,助力带屏IPC在嵌入式设备中的应用
arm开发·微信·架构·音视频·webrtc
堕落年代3 天前
WebRTC建立Description的通信的实际的原理
网络·webrtc
爱学习的大牛1233 天前
如何在 Flutter 中使用 WebRTC
flutter·webrtc
_洛_神3 天前
Windows平台编译webrtc
windows·webrtc
EasyCVR4 天前
EasyRTC嵌入式音视频通信SDK:WebRTC技术下的硬件与软件协同演进,开启通信新时代
linux·运维·服务器·c语言·音视频·webrtc