通过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);
}
相关推荐
kkk_皮蛋11 小时前
写一个最简单的 WebRTC Demo(实操篇)
webrtc
kkk_皮蛋14 小时前
WebRTC 架构概览(整体框架篇)
webrtc
联系QQ8762239651 天前
基于模型预测MPC的燃油汽车车速控制探索
webrtc
dualven_in_csdn3 天前
【webrtc】继续编译aar 2025-12-12
webrtc
kkk_皮蛋4 天前
WebRTC 是什么?能做什么?(概览篇)
webrtc
kkk_皮蛋5 天前
WebRTC 中的临界锁实现:从 CritScope 到 RAII 机制的深度解析
webrtc·策略模式
嘻哈baby5 天前
WebRTC实时通信原理与P2P连接实战
网络协议·webrtc·p2p
好游科技5 天前
使用WebRTC开发直播系统与音视频语聊房实践指南
音视频·webrtc·im即时通讯·社交软件·私有化部署im即时通讯·社交app
好游科技5 天前
语音语聊系统开发深度解析:WebRTC与AI降噪技术如何重塑
人工智能·webrtc·交友·im即时通讯·社交软件·社交语音视频软件
福大大架构师每日一题5 天前
pion/webrtc v4.1.7 版本更新详解
webrtc