系列文章目录
第一篇 基于SRS 的 WebRTC 环境搭建
第二篇 基于SRS 实现RTSP接入与WebRTC播放
第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建
第四篇 WebRTC学习一:获取音频和视频设备
第五篇 WebRTC学习二:WebRTC音视频数据采集
第六篇 WebRTC学习三:WebRTC音视频约束
第七篇 WebRTC学习四:WebRTC常规视觉滤镜
第八篇 WebRTC学习五:从视频中提取图片
文章目录
前言
在前几篇文章中,我们探讨了WebRTC的环境搭建、音视频数据采集、音视频约束以及如何应用视觉滤镜。本篇文章将进一步扩展我们对WebRTC的理解,介绍如何从应用视觉滤镜的实时视频流中提取一张静态图片。我们将使用HTML5的Canvas API来实现这一功能,探索相关的网页端代码和JavaScript实现逻辑。
一、概述
提取视频流中的静态图片在许多应用场景中非常实用,比如视频通话中的截图、实时监控的快照等。本篇文章将介绍如何使用Canvas API从WebRTC的视频流中获取一张图片,并展示其实现方法。
二、修改页面布局
在前面实现的基础上,对页面进行了布局上的调整。
1、视频和 Canvas 布局:视频和 Canvas 将并排显示,左边是视频,右边是 Canvas,且保持相等宽度。
2、控件的排布:控件 (音频、视频源选择和滤镜选择等) 保持在顶部,整齐排列。
3、按钮位置: “Take snapshot” 按钮位于视频和 Canvas 下面,且居中显示。以下是修改后的HTML结构:
1.页面修改
页面代码如下:
<div id="videoContainer">
<video autoplay playsinline id="player"></video>
<canvas id="picture" width="400" height="320"></canvas>
</div>
<button id="snapshot">Take snapshot</button>
2.css样式
代码如下:
#player {
width: 400px; /* 设置视频宽度 */
height: auto; /* 自动高度 */
border: 1px solid #ccc; /* 可选,给视频一个边框 */
}
#picture {
width: 400px; /* 设置Canvas宽度 */
height: auto; /* 自动高度 */
border: 1px solid #ccc; /* 可选,给画布一个边框 */
background-color: bisque;
margin-left: 20px; /* 视频和画布之间的间距 */
}
button {
margin-top: 10px; /* 按钮与其它元素之间的间距 */
}
三、实现功能
在原来的基础上增加获取图片功能,主要是通过HTML5 Canvas getContext函数获取上下文,drawImage函数绘制图像。
核心代码如下:
const snapshot = document.querySelector('button#snapshot');
const picture = document.querySelector('canvas#picture');
// 快照功能
snapshot.onclick = function () {
const context = picture.getContext('2d');
// 清空 Canvas
context.clearRect(0, 0, picture.width, picture.height);
// 应用滤镜
context.filter = getFilterValue(filterSelect.value);
// 绘制视频帧
context.drawImage(videoplay, 0, 0, picture.width, picture.height);
// 清除滤镜设置(可选,便于后续操作)
context.filter = 'none';
};
四、完整示例代码
1.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="./css/style.css"> <!-- 引入CSS文件 -->
</head>
<body>
<div id="controls">
<div>
<label>Audio Source:</label>
<select id="audioSource"></select>
</div>
<div>
<label>Audio Output:</label>
<select id="audioOutput"></select>
</div>
<div>
<label>Video Source:</label>
<select id="videoSource"></select>
</div>
<div>
<label>Filter:</label>
<select id="filter">
<option value="none">None</option>
<option value="blur">Blur</option>
<option value="grayscale">Grayscale</option>
<option value="invert">Invert</option>
<option value="sepia">sepia</option>
</select>
</div>
</div>
<div id="videoContainer">
<video autoplay playsinline id="player"></video>
<canvas id="picture" width="400" height="320"></canvas>
</div>
<button id="snapshot">Take snapshot</button>
<script src="./js/client.js"></script>
</body>
</html>
2.css代码
style.css文件内容如下:
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
}
#controls {
display: flex;
justify-content: space-between;
width: 100%;
max-width: 800px; /* 设置一个最大宽度 */
margin-bottom: 20px; /* 控件与视频和画布的间距 */
}
#videoContainer {
display: flex;
}
#player {
width: 400px; /* 设置视频宽度 */
height: auto; /* 自动高度 */
border: 1px solid #ccc; /* 可选,给视频一个边框 */
}
#picture {
width: 400px; /* 设置Canvas宽度 */
height: auto; /* 自动高度 */
border: 1px solid #ccc; /* 可选,给画布一个边框 */
background-color: bisque;
margin-left: 20px; /* 视频和画布之间的间距 */
}
button {
margin-top: 10px; /* 按钮与其它元素之间的间距 */
}
select {
margin-right: 10px; /* 下拉框之间的间距 */
}
.none {
-webkit-filter:none;
}
.blur {
-webkit-filter: blur(3px);
}
.grayscale {
-webkit-filter: grayscale(1);
}
.invert {
-webkit-filter: invert(1);
}
.sepia {
-webkit-filter: sepia(1);
}
3.js代码
client.js文件内容如下:
'use strict';
const audioSource = document.querySelector('select#audioSource');
const audioOutput = document.querySelector('select#audioOutput');
const videoSource = document.querySelector('select#videoSource');
const filterSelect = document.querySelector('select#filter');
const videoplay = document.querySelector('video#player');
const snapshot = document.querySelector('button#snapshot');
const picture = document.querySelector('canvas#picture');
// 获取设备列表
function gotDevices(deviceInfos) {
deviceInfos.forEach(deviceInfo => {
const option = document.createElement('option');
option.text = deviceInfo.label;
option.value = deviceInfo.deviceId;
switch (deviceInfo.kind) {
case "audioinput":
audioSource.appendChild(option);
break;
case "audiooutput":
audioOutput.appendChild(option);
break;
case "videoinput":
videoSource.appendChild(option);
break;
}
});
}
// 获取媒体流
function gotMediaStream(stream) {
videoplay.srcObject = stream;
return navigator.mediaDevices.enumerateDevices();
}
// 处理错误
function handleError(err) {
console.error('getUserMedia error:', err);
}
// 启动媒体流
function start() {
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
console.error('getUserMedia is not supported!');
return;
}
const constraints = {
video: {
width: 640,
height: 480,
frameRate: 30,
facingMode: "environment",
deviceId: videoSource.value ? { exact: videoSource.value } : undefined, // 确保使用确切的设备ID
},
audio: {
noiseSuppression: true,
echoCancellation: true
}
};
navigator.mediaDevices.getUserMedia(constraints)
.then(gotMediaStream)
.then(gotDevices)
.catch(handleError);
}
// 滤镜选择更改事件
filterSelect.onchange = function () {
videoplay.className = filterSelect.value;
};
// 快照功能
snapshot.onclick = function () {
const context = picture.getContext('2d');
// 清空 Canvas
context.clearRect(0, 0, picture.width, picture.height);
// 应用滤镜
context.filter = getFilterValue(filterSelect.value);
// 绘制视频帧
context.drawImage(videoplay, 0, 0, picture.width, picture.height);
// 清除滤镜设置(可选,便于后续操作)
context.filter = 'none';
};
// 获取滤镜值
function getFilterValue(filter) {
switch (filter) {
case 'blur':
return 'blur(3px)';
case 'grayscale':
return 'grayscale(1)';
case 'invert':
return 'invert(1)';
case 'sepia':
return 'sepia(1)';
default:
return 'none';
}
}
// 初始化
start();
videoSource.onchange = start;
五、运行效果
在浏览器中打开 index.html 文件,通过右上Filter下拉菜单选择不同的视觉滤镜,实时视频中可即时看到效果,点击“Task snapshot”按钮,可以看到抓取到的图片,图片上右键单击,选择图片另存为,即可保存图片到磁盘。下图是我的浏览器上显示的效果。
总结
在本篇文章中,我们学习了如何从WebRTC的视频流中提取静态图片,结合了HTML5的Canvas API。通过这种方式,我们可以轻松实现实时图像捕获的功能。这为我们后续更复杂的WebRTC应用奠定了基础。
希望能给大家提供一些帮助和启发。欢迎留言讨论!
标签:视频,Canvas,const,picture,filter,提取,WebRTC From: https://blog.csdn.net/wel_006/article/details/143081288你好,我是阿灿,慢慢理解世界,慢慢更新自己。