目录

  • 打开摄像头/关闭摄像头
  • 静音/解除静音
  • 打开视频/关闭视频
  • 截图且下载

打开摄像头/关闭摄像头

效果图

HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>打开摄像头</title>
<link rel="stylesheet" href="../../../static/layui/css/layui.css">
</head>
<body>
<div id="container">
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<video id="video-local" autoplay playsinline width="400px" height="400px"></video>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<button type="button" class="layui-btn layui-btn-normal" onclick="openCamera()">打开摄像头</button>
<button type="button" class="layui-btn layui-btn-danger" onclick="stopVideo()">关闭摄像头</button>
</div>
</div>
<blockquote class="layui-elem-quote layui-text" style="margin-top: 15px;">
<p>显示摄像头预览的内容,网页上由元素video来呈现。</p>
<p>点击打开摄像头按钮后,浏览器会询问是否允许,请点击“允许”。</p>
</blockquote>
</div>
</body>
</html>

javaScript

   let videoElem = document.querySelector('video');

    /**
* MediaDevices.getUserMedia()方法在用户允许后,按照请求,拿到stream。 stream可以包含视频或音频。前面的设定里,我们只使用视频。
* 如果用户拒绝了使用摄像头申请,或者申请的媒体不可用,即表现为被拒绝。 用户拒绝会报NotAllowedError,找不到符合要求的设备会报NotFoundError DOMException。
* @param e
* @returns {Promise<void>}
*/
function openCamera() {
if (window.stream != null) {
alert('摄像头已打开,请勿重新打开摄像头');
return false;
}
const constraints = {
audio: true,
video: true
};
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(error => {
console.error(error)
});
} /**
* 成功获取到流
* @param stream
*/
function gotStream(stream) {
window.stream = stream;
videoEle.srcObject = stream;
} /**
* 关闭摄像头
* 获取到video中的流,并将流中的轨道关闭
*/
function stopVideo() {
// 获取video中的流
const stream = videoElem.srcObject;
// 判断stream 是否为空
if (stream == null) {
return;
}
// 获取流中的所有轨道
const tracks = stream.getTracks();
tracks.forEach(function (track) {
track.stop();
});
videoElem.srcObject = null;
window.stream = null;
}

静音/解除静音

效果图





前端代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>静音-解除静音</title>
<link rel="stylesheet" href="../../../static/layui/css/layui.css">
</head>
<body>
<div id="container">
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<video id="video-local" autoplay playsinline width="400px" height="400px"></video>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<button type="button" class="layui-btn layui-btn-normal" onclick="openCamera()">打开摄像头</button>
<button id="mute" type="button" class="layui-btn layui-btn-normal" onclick="muted()">静音</button>
<button id="unmute" type="button" class="layui-btn layui-btn-normal" onclick="unmuted()">解除静音</button>
</div>
</div>
<blockquote class="layui-elem-quote layui-text" style="margin-top: 15px;">
<p>1.显示摄像头预览的内容,网页上由元素video来呈现。</p>
<p>2.点击打开摄像头按钮后,浏览器会询问是否允许,请点击“允许”。</p>
<p>3.打开摄像头获取到浏览器摄像头数据后,可以对获取到的流数据进行静音以及解除静音相关操作</p>
</blockquote>
</div>
</body>
</html>

javaScript

    const constraints = {
audio: true,
video: true
}; let localStream = null;
let videoEle = document.querySelector('video');
/**
* MediaDevices.getUserMedia()方法在用户允许后,按照请求,拿到stream。 stream可以包含视频或音频。前面的设定里,我们只使用视频。
* 如果用户拒绝了使用摄像头申请,或者申请的媒体不可用,即表现为被拒绝。 用户拒绝会报NotAllowedError,找不到符合要求的设备会报NotFoundError DOMException。
* @param e
* @returns {Promise<void>}
*/
function openCamera() {
if(localStream!=null){
alert('摄像头已打开,请勿重新打开摄像头');
return false;
}
navigator.mediaDevices.getUserMedia(constraints).then(stream=>{
localStream = stream;
videoEle.srcObject = stream;
}).catch(error=>{
alert('打开摄像头失败');
console.error('打开摄像头失败',error)
});
} function muted() {
if(localStream==null){
alert('请打开音视频');
return false;
}
const tracks = localStream.getTracks();
tracks.forEach(track => {
if(track.kind === 'audio'){
track.enabled = false
}
console.log(track)
});
alert('静音开启,u can`t speak ')
} function unmuted() {
if(localStream==null){
alert('请打开音视频');
return false;
}
const tracks = localStream.getTracks();
tracks.forEach(track => {
if(track.kind === 'audio'){
track.enabled = true
}
console.log(track)
});
alert('解除静音,u can speak ')
}
}

打开视频/关闭视频

效果图

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>打开视频/关闭视频</title>
<link rel="stylesheet" href="../../../static/layui/css/layui.css">
</head>
<body>
<div id="container">
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<video id="video-local" autoplay playsinline width="400px" height="400px"></video>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<button type="button" class="layui-btn layui-btn-normal" onclick="openCamera()">打开摄像头</button>
<button id="openVideo" type="button" class="layui-btn layui-btn-normal" onclick="openVideo()">打开视频</button>
<button id="closeVideo" type="button" class="layui-btn layui-btn-normal" onclick="closeVideo()">关闭视频</button>
</div>
</div>
<blockquote class="layui-elem-quote layui-text" style="margin-top: 15px;">
<p>1.显示摄像头预览的内容,网页上由元素video来呈现。</p>
<p>2.点击打开摄像头按钮后,浏览器会询问是否允许,请点击“允许”。</p>
<p>3.打开摄像头获取到浏览器摄像头数据后,可以对获取到的流数据进行打开视频/关闭视频相关操作</p>
</blockquote>
</div> </body>
</html>

javaScript

 const constraints = {
audio: true,
video: true
}; let localStream = null;
let videoEle = document.querySelector('video');
/**
* MediaDevices.getUserMedia()方法在用户允许后,按照请求,拿到stream。 stream可以包含视频或音频。前面的设定里,我们只使用视频。
* 如果用户拒绝了使用摄像头申请,或者申请的媒体不可用,即表现为被拒绝。 用户拒绝会报NotAllowedError,找不到符合要求的设备会报NotFoundError DOMException。
* @param e
* @returns {Promise<void>}
*/
function openCamera() {
if(localStream!=null){
alert('摄像头已打开,请勿重新打开摄像头');
return false;
}
navigator.mediaDevices.getUserMedia(constraints).then(stream=>{
localStream = stream;
videoEle.srcObject = stream;
}).catch(error=>{
alert('打开摄像头失败');
console.error('打开摄像头失败',error)
});
} function openVideo() {
if(localStream==null){
alert('请打开音视频');
return false;
}
const tracks = localStream.getTracks();
tracks.forEach(track => {
if(track.kind === 'video'){
track.enabled = true
}
console.log(track)
});
alert('打开视频,u can see u ')
} function closeVideo() {
if(localStream==null){
alert('请打开音视频');
return false;
}
const tracks = localStream.getTracks();
tracks.forEach(track => {
if(track.kind === 'video'){
track.enabled = false
}
console.log(track)
});
alert('关闭视频,u can`t see u ')
}

视频截图

效果图

HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>截屏</title>
<link rel="stylesheet" href="../../../static/layui/css/layui.css"> </head>
<body>
<div id="container">
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<video id="video-local" autoplay playsinline width="400px" height="400px"></video>
</div>
</div>
<div class="layui-row">
<div class="layui-col-xs6 layui-col-md12" style="text-align: center">
<button type="button" class="layui-btn layui-btn-normal" onclick="openCamera()">打开摄像头</button>
<button type="button" class="layui-btn layui-btn-normal" onclick="getCapure()">截图</button>
</div>
</div>
<canvas id="mainCanvas"></canvas>
<div id="list" style="display: grid; grid-template-columns: repeat(auto-fill, 100px);
column-gap: 20px; row-gap: 20px;"></div>
<blockquote class="layui-elem-quote layui-text" style="margin-top: 15px;">
<p>1.获取摄像头数据,点击截图,展示截图数据</p>
</blockquote>
</div>
</body>
</html>

javaScript

 const video = document.querySelector('video');
const constraints = {
audio: false,
video: true
}; const list = document.querySelector('#list'); // 拿来存放多个元素 function openCamera() {
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(onError);
} /**
* 成功获取流数据
* @param stream
*/
function gotStream(stream) {
window.stream = stream;
video.srcObject = stream;
}
/**
* 获取流发生错误
* @param stream
*/
function onError(error) {
console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
} /**
* 捕获
*/
function getCapure(){
const mCanvas = window.canvas = document.querySelector('#mainCanvas');
mCanvas.width = 480;
mCanvas.height = 360; // 开始截取
mCanvas.width = video.videoWidth;
mCanvas.height = video.videoHeight;
mCanvas.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height);
// 新增1张
var divItem = document.createElement("div");
divItem.style.display = "block";
divItem.width = 100;
divItem.height = divItem.width * video.videoHeight / video.videoWidth; // 计算一下比例
divItem.style.width = divItem.width + "px";
divItem.style.height = divItem.height + "px";
var c1 = document.createElement("canvas");
c1.width = divItem.width;
c1.height = divItem.height;
c1.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height, 0, 0, c1.width, c1.height);
divItem.appendChild(c1);
list.appendChild(divItem);
} /**
* 清除记录
*/
function clear(){
var child = list.lastElementChild;
while (child) {
list.removeChild(child);
child = list.lastElementChild;
}
}

写在最后学习参考视频讲解比较详细:https://space.bilibili.com/394612055/video?tid=0&page=2&keyword=&order=pubdate

Web网页音视频通话之Webrtc相关操作(一)的更多相关文章

  1. iOS下WebRTC音视频通话(一)

    在iOS下做IM功能时,难免都会涉及到音频通话和视频通话.QQ中的QQ电话和视频通话效果就非常好,但是如果你没有非常深厚的技术,也没有那么大的团队,很难做到QQ那么快速和稳定的通话效果. 但是利用We ...

  2. iOS下WebRTC音视频通话(三)-音视频通话

    前两篇文章记录了音视频通话的一些概念和一些流程,以及一个局域网内音视频通话的示例. 今天以一个伪真实网络间的音视频通话示例,来分析WebRTC音视频通话的过程. 上一篇因为是在相同路由内,所以不需要穿 ...

  3. iOS下WebRTC音视频通话(二)-局域网内音视频通话

    这里是iOS 下WebRTC音视频通话开发的第二篇,在这一篇会利用一个局域网内音视频通话的例子介绍WebRTC中常用的API. 如果你下载并编译完成之后,会看到一个iOS 版的WebRTC Demo. ...

  4. 鹅厂优文|打通小程序音视频和webRTC

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯视频云终端技术总监常青, 2008 年毕业加入腾讯,一直从事客户端研发相关工作,先后参与过 PC QQ.手机QQ.QQ物联 等产品 ...

  5. 腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践

    1.概述 本文来自腾讯视频云终端技术总监rexchang(常青)技术分享,内容分别介绍了微信小程序视音视频和WebRTC的技术特征.差异等,并针对两者的技术差异分享和总结了微信小程序视音视频和WebR ...

  6. WebRTC相关的基础知识点

    这里主要用来记录自己整理的和webRTC相关的一些基本的知识点,后续整理的一些基础和零碎的知识点都会更新在这里.内容大部分来自于webRTC官网.w3c以及一些前辈们的博客中的文章和相关书籍等. 20 ...

  7. JS实现Web网页打印功能(IE)

    问题描述:     JS实现Web网页打印功能 问题解决:     这里主要使用WebBrowser控件的ExeWB在IE中打印功能的实现 WebBrowser介绍:         WebBrows ...

  8. Android音视频通话过程中最小化成悬浮框的实现(类似Android8.0画中画效果)

    关于音视频通话过程中最小化成悬浮框这个功能的实现,网络上类似的文章很多,但是好像还没看到解释的较为清晰的,这里因为项目需要实现了这样的一个功能,今天我把它记录下来,一方面为了以后用到便于自己查阅,一方 ...

  9. 二、Uniapp+vue+腾讯IM+腾讯音视频开发仿微信的IM聊天APP,支持各类消息收发,音视频通话,附vue实现源码(已开源)-腾讯云后台配置TXIM

    项目文章索引 1.项目引言 2.腾讯云后台配置TXIM 3.配置项目并实现IM登录 4.会话好友列表的实现 5.聊天输入框的实现 6.聊天界面容器的实现 7.聊天消息项的实现 8.聊天输入框扩展面板的 ...

  10. Web自动化测试怎么做呢?好!接下来我们就开始Web网页测试针对性的流程解析啦!!!

    前言 测试行业现在70%是以手工测试为主,那么只有20%是自动化测试,剩下的10%是性能测试. 有人可能会说,我现在做手工,我为什么要学自动化呢?我去学性能更好性能的人更少? 其实,性能的要求比自动化 ...

随机推荐

  1. ResNet50的猫狗分类训练及预测

    相比于之前写的ResNet18,下面的ResNet50写得更加工程化一点,这还适用与其他分类. 我的代码文件结构 1. 数据处理 首先已经对数据做好了分类 文件夹结构是这样 开始划分数据集 split ...

  2. TF-IDF定义及实现

    TF-IDF定义及实现 定义 ​ TF-IDF的英文全称是:Term Frequency - Inverse Document Frequency,中文名称词频-逆文档频率,常用于文本挖掘,资讯检索等 ...

  3. 谈一谈Python中的装饰器

    1.装饰器基础介绍 1.1 何为Python中的装饰器? Python中装饰器的定义以及用途: 装饰器是一种特殊的函数,它可以接受一个函数作为参数,并返回一个新的函数.装饰器可以用来修改或增强函数的行 ...

  4. 用 Gaussian Process 建模 state-action 空间相关性,加速 Multi-Fidelity RL

    目录 全文快读 1 intro 3 背景 4 method 4.1 model-based 算法:GP-VI-MFRL 4.2 model-free 算法:GPQ-MFRL 5 experiment ...

  5. c/c++快乐算法第三天

    c/c++感受算法快乐(3) 开始时间2023-04-16 22:21:10 结束时间2023-04-17 00:09:34 前言:很好,这周就要结束了,大家都回学校了么,嘻嘻.回顾一下昨天的算法题, ...

  6. 《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(14)-Charles过滤网络请求

    1.简介 在日常工作测试中,经常要抓包看请求的request,response是不是传的对,返回的字段值对不对,众多的请求中看得眼花缭乱,如何找到自己想要的请求,那么我们就需要过滤请求.Charles ...

  7. 从 HTTP 到 gRPC:APISIX 中 etcd 操作的迁移之路

    罗泽轩,API7.ai 技术专家/技术工程师,Apache APISIX PMC 成员. 原文链接 Apache APISIX 现有基于 HTTP 的 etcd 操作的局限性 etcd 在 2.x 版 ...

  8. 容器云平台监控告警体系(五)—— Prometheus发送告警机制

    1.概述 在Prometheus的架构中告警被划分为两个部分,在Prometheus Server中定义告警规则以及产生告警,Alertmanager组件则用于处理这些由Prometheus产生的告警 ...

  9. JUC中常见的集合

    Map: HashMap ===> ConcurrentHashMap List: ArrayList ===> CopyOnWriteArrayList Set: HashSet === ...

  10. 进程间通信WebSocket 服务端未启动时,客户端重连报错

    当WebSocket服务端未启动时,我们在客户端申请连接,会报 System.Net.Sockets.SocketException 异常. 当然,我们调试时异常设置默认是不勾选这个的.所以不影响正常 ...