当前位置: 首页 > news >正文

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

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

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

代码:

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:


//获取视频流

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:

: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);
}

相关文章:

  • 同旺科技USB to SPI 适配器 ---- 指令循环发送功能
  • Baklib智能内容推荐的核心是什么?
  • Vue3前端开发:组件化设计与状态管理
  • 文献分享: XTR——优化Token级检索的高效多向量模型
  • nginx5天时间从0到熟练掌握学习计划
  • 坐标变换其一 ccf-csp 2023-9-1
  • 自定义reset50模型转换到昇腾om
  • dijkstra(堆优化版)
  • 长沙搞么子
  • 数字证书 与 数字签名 介绍
  • C语言 转义字符
  • 从GTC2025首次量子日看英伟达量子AI融合算力网络前景与趋势
  • Deepseek训练成AI图片生成机器人
  • 线程的概念和控制
  • Kotlin 协程基础知识汇总(一)
  • vue3:十一、主页面布局(进入指定菜单页面,默认锁定到左侧菜单)
  • 【MySQL】全面学习数据库查询技巧:查询指令深度学习指南
  • 损失函数理解(二)——交叉熵损失
  • C# WebForm显示bootstrap模态对话框
  • 《燃气管网运行工》考试资料分享,附答案
  • 2024“好评中国”网络评论大赛结果揭晓
  • 杜前任宁波中院代理院长,卸任宁波海事法院院长
  • 消费维权周报|上周违规经营类投诉较多,涉诱导加盟等
  • 国家发改委回应美加征关税:典型的单边主义霸凌做法
  • 学大教育:去年净利润1.797亿元,学习中心增加约60所
  • 万能险新规落地:保险期限不得低于五年,明确万能险销售“负面清单”