目录

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

打开摄像头/关闭摄像头

效果图

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. PHP开发者交流群

    PHP开发者交流群 欢迎大家加入学习讨论 QQ群(493834732)

  2. PHP创建SqlLite数据表并让ID自增

    <?php class MyDB extends SQLite3 { function __construct() { $this->open('test.db'); } } $db = ...

  3. CSS笔记(待完善)

    CSS笔记 css权重 ID(100)> class(10)> element(1) css最高权重 !important 块元素(block) 可以设置宽度和高度,独立成行. h1~h6 ...

  4. js计算当前时间差

    1 function timesFun(timesData) { 2 //如果时间格式是正确的,那下面这一步转化时间格式就可以不用了 3 var dateBegin = new Date(timesD ...

  5. C# 笔迹擦除8边形

    擦除区域与橡皮大小不一致 测试反馈,擦除区域与真实的橡皮大小不一致: 上图中,橡皮显示是圆形的,但擦除效果是一个"8边形"区域. 找了一台8K屏,确实是能复现的: 看到这个诡异的8 ...

  6. [OpenCV-Python] 4 图像读取

    文章目录 OpenCV-Python: II OpenCV 中的 Gui 特性 4 图片 4.1 读入图像 4.2 显示图像 4.3 保存图像 4.4 总结一下 OpenCV-Python: II O ...

  7. 2022-09-23:整数数组 stations 表示 水平数轴 上各个加油站的位置。给你一个整数 k 。 请你在数轴上增设 k 个加油站, 新增加油站可以位于 水平数轴 上的任意位置,而不必放在整数

    2022-09-23:整数数组 stations 表示 水平数轴 上各个加油站的位置.给你一个整数 k . 请你在数轴上增设 k 个加油站, 新增加油站可以位于 水平数轴 上的任意位置,而不必放在整数 ...

  8. ModuleNotFoundError: No module named 'flask_mail'

    ModuleNotFoundError: No module named 'flask_mail' 解决: pip install flask_mail

  9. Midjourney|文心一格prompt教程[基础篇]:注册使用教程、风格设置、参数介绍、隐私模式等

    Midjourney|文心一格prompt教程[基础篇]:注册使用教程.风格设置.参数介绍.隐私模式等 开头讲一下为什么选择Midjourney和文心一格,首先Midjourney功能效果好不多阐述: ...

  10. 源端为备库的场景下Duplicate失败问题

    环境: Oracle 11.2.0.3 + OEL 7.9 A -> B -> C 级联ADG环境:db11g -> db11gadg -> db11gcas 之前测试提到,从 ...