通过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);
}
相关推荐
appcanLiYunLong1 天前
Webrtc让浏览器实现无服务器中转的安全私密聊天
安全·serverless·webrtc
Tiger_Hu1 天前
通过WebRTC源码入门OpenGL ES
android·webrtc·opengl
feiyangqingyun2 天前
推流265视频,网页如何支持显示265的webrtc
音视频·webrtc
半兽先生4 天前
WebRtc 视频流卡顿黑屏解决方案
java·前端·webrtc
mo47764 天前
webrtc pacer模块(一) 平滑处理的实现
webrtc
Thread.sleep(0)11 天前
WebRTC源码解析:Android如何渲染画面
android·webrtc
chen_song_14 天前
WebRTC的ICE之TURN协议的交互流程中继转发Relay媒体数据的turnserver的测试
算法·音视频·webrtc·交互·媒体
程序员阿灿14 天前
ZLMediaKit 源码分析——[3] ZLToolKit 中EventPoller之网络事件处理
网络·webrtc·zlmediakit·zltoolkit
EasyCVR15 天前
视频AI赋能水利行业生态治理,水电站大坝漂浮物实时监测与智能预警方案
webrtc·智能硬件
拖孩17 天前
[特殊字符]我在 Chatterbox(话匣子)中 WebRTC 的使用-上篇(基本介绍)
开发语言·php·webrtc