首页 > 其他分享 >一文带你看懂浏览器采集音视频

一文带你看懂浏览器采集音视频

时间:2023-12-07 21:07:52浏览次数:26  
标签:mediaDevices 浏览器 一文 stream track 音视频 video getUserMedia constraints

navigator.mediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据

本文所有API基本来源于MDN文档,MDN文档在mediaDevices模块翻译也是有的翻译了,有的没有翻译,有的通过链接打开是404(可以将url中的zh-CN改成en-US来查看英文版本),在代码实践(Chrome x86_64 88)中有的API与MDN上也不尽相同,因此基本是按代码实践中的API来罗列。 如果您发现有错误描述,可以留言,我会在第一时间验证,修改。

0. 前提

  1. navigator.getUserMedia已被废弃,请使用navigator.mediaDevices.getUserMedia
  2. 浏览器要获取摄像头权限需要开启本地端口或者https服务;

1. mediaDevices

mediaDevices上提供了4个方法和一个监听事件

方法:

  • enumerateDevices: 获取系统可用的媒体输入和输出设备
  • getSupportedConstraints: 返回一个输入设备可支持的约束属性
  • getDisplayMedia: 开启屏幕共享
  • getUserMedia: 开启媒体输入设备

事件:

  • devicechange

1.1 enumerateDevices

enumerateDevices返回一个promise,如果正确执行可以得到一个MediaDeviceInfo的数组,每项分别有4个属性(都是只读)。

TIPS: 如果页面未获取浏览器设备权限,则返回的deviceId和label都是空字符串。调用mediaDevices.getUserMedia会触发询问权限

navigator.mediaDevices.enumerateDevices().then(res => console.table(res));

一文带你看懂浏览器采集音视频_webrtc

  • deviceId: 代表设备的id,随机生成,该网页与其他网页获取的id不同;
  • label: 设备的别名
  • kind: 枚举值 audioinput audiooutput videoinput,因为视频输出靠屏幕,因此没有videooutput这个选项
  • groupId: 如果设备是同一个物理设备,那么这些设备的groupId就是同一个

1.2 getUserMedia

浏览器获取视频、音频的入口

window.addEventListener('load', initMedia);

async function initMedia() {
	const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
	console.log(stream);
}
  1. 初次调用后会询问权限策略:允许或者禁止。允许后会获取永久权限,如果想再改成询问,需要点击地址栏前的小叹号修改;
  2. 接口参数十分复杂,放到1.4节详细讲解;
  3. 返回的stream表示媒体流,内部可以包括多个媒体轨道track,比如视频轨和音频轨。stream和track的关系如下图所示:

一文带你看懂浏览器采集音视频_webrtc_02

1.2.1 stream

stream上有2个重要的属性 active 代表该流是否为活动状态 和 id 代表流的唯一值

简而言之,stream就是管理tarck的集合,在stream上有操作track的一些增删查方法:

  • addTrack: 将track添加到stream中
  • getTracks getVideoTracks getAudioTracks:顾名思义,会返回track list
  • getTrackById: track是有id属性,可以根据id在stream中获取该track,如果不存在会返回null
  • removeTrack: 传入值是MediaStreamTrack对象,而非trackId

同时stream也可以订阅track相关的事件:

  • onaddtrack
  • onremovetrack

除此之外stream上还有clone方法,返回MediaStream的克隆版本,并且会返回一个新的id;

1.2.2 track

视频/音频轨道

async function initMedia() {
	window.stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
	console.log(stream.getTracks());
}

一文带你看懂浏览器采集音视频_webrtc_03

上面有一些重要的属性和方法:

  1. 属性(除了enabled外,全是只读):
  • id: 代表唯一值
  • kind: "audio" | "video"
  • enabled: 表示该轨道是否可用,可以被手动设置,设置为false后,视频黑屏,音频静音
  • label: 和mediaDevices.enumerateDevices返回值设备的label相对应
  • muted: 是否静音
  • readyState: 枚举值, "live"表示输入设备正常连接,"ended"表示没有更多的数据
  1. 方法:
  • getConstraints(): 返回创建该轨道的约束(getUserMedia的参数),只以video为例,video可设置的选项很多,会在1.4详细解读
async function initMedia() {
  // case 1 只是简单打开视频
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  const track = stream.getTracks()[0];
  console.log(track.getConstraints()); // {} 表示没有任何约束
  
  // case 2 指定视频宽高
  const stream = await navigator.mediaDevices.getUserMedia({ video: {
      width: 640,
      height: 320
  } });
  const track = stream.getTracks()[0];
  console.log(track.getConstraints()); // {height: 320, width: 640}
}
  • applyConstraints(): 给该轨道应用新的约束
async function initMedia() {
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    const track = stream.getTracks()[0];
    let constraints = track.getConstraints();
    console.log('old constraints: ', constraints); // {}

    constraints.width = 640;
    constraints.height = 320;
    await track.applyConstraints(constraints);
    console.log('new constraints: ', track.getConstraints()); // {height: 320, width: 640}
}
  • getSettings(): 和getConstraints不同的是,getSettings会返回浏览器添加的默认约束和自己明确添加的约束,也就是轨道的所有约束
async function initMedia() {
    const stream = await navigator.mediaDevices.getUserMedia({ video: {
        width: 320,
        height: 240,
    } });
    const track = stream.getTracks()[0];
    let constraints = track.getConstraints();
    let settings = track.getSettings();
    console.log('constraints 1: ', constraints); // {height: 240, width: 320}
    console.log('settings 1: ', settings); // {aspectRatio:1.3333333333333333,deviceId: "ac5572f202526708aa9d0984ac3d7214873266ea014b93d22fc850cb565915f6",frameRate:30.000030517578125,groupId: "ab4cc46dac787502a6c20285b385ea5376aaafe7fa7c77be6d63006308465639",height: 240,resizeMode: "crop-and-scale",width: 320}

    constraints.width = 640;
    constraints.height = 480;
    constraints.frameRate = 25;
    await track.applyConstraints(constraints);
    constraints = track.getConstraints();
    settings = track.getSettings();
    console.log('constraints 2: ', constraints); // {height: 480, width: 640, frameRate: 25}
    console.log('settings 2: ', settings); // {aspectRatio: 1.3333333333333333, deviceId: "ac5572f202526708aa9d0984ac3d7214873266ea014b93d22fc850cb565915f6",frameRate: 25,groupId: "ab4cc46dac787502a6c20285b385ea5376aaafe7fa7c77be6d63006308465639",height: 480,resizeMode: "none",width: 640}
  }
  • getCapabilities(): 方法返回一个 MediaTrackCapabilities 对象,此对象表示每个可调节属性的值或者范围,该特性依赖于平台和user agent。

video的宽高是可以设置的,但是设置的范围是多少呢,可以通过该方法来查看:

async function initMedia() {
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    const track = stream.getTracks()[0];
    console.log(track.getCapabilities());
}

可以得到类似以下的结果:

{
    "aspectRatio":{
        "max":1280,
        "min":0.001388888888888889
    },
    "deviceId":"ac5572f202526708aa9d0984ac3d7214873266ea014b93d22fc850cb565915f6",
    "facingMode":[

    ],
    "frameRate":{
        "max":30.000030517578125,
        "min":0
    },
    "groupId":"f04ed7a36ef8757794bb5db771115bf857b73332e68bf39ec42b30667a76fdca",
    "height":{
        "max":720,
        "min":1
    },
    "resizeMode":[
        "none",
        "crop-and-scale"
    ],
    "width":{
        "max":1280,
        "min":1
    }
}
  • clone(): 克隆一个track的备份,和stream一样,会产出一个新的id
  • stop(): stop后,readyState的状态就变成了ended

1.3 getDisplayMedia

调用后会在所有屏幕/应用/Chrome标签页中选择一个共享画面

一文带你看懂浏览器采集音视频_webrtc_04

因为是共享屏幕,即使约束不添加video选项,stream中也有默认添加一个video。其他约束、stream、track就和getUserMedia一样了,不再赘述

1.4 getSupportedConstraints

返回一个对象,该对象表明可以约束MediaStreamTrack的属性

const constraints = navigator.mediaDevices.getSupportedConstraints();
console.log(constraints);

一文带你看懂浏览器采集音视频_webrtc_05

getUserMediagetDisplayMedia这两个方法接收一个对象作为参数,对象中可以分别对video和audio设置具体的参数(称之为constraints即约束)。通过getSupportedConstraints获取的属性就是设置约束的具体内容,这些属性可以分为通用设置、只对video设置、只对aduio设置

navigator.mediaDevices.getUserMedia({
	video: {},
    audio: {},
})
1.4.1 通用设置 deviceId & groupId

通用设置,可以指定外设,可以通过mediaDevices.enumerateDevices来查询外设的deviceId或者groupId

navigator.mediaDevices.getUserMedia({ video: {
	deviceId: 'xxx-xxx'
} });
1.4.2 video width & height

这两个属性只对video来设置,设置方法一样,单拿一个来讲,一共有3种设置方式:

  1. 不设置:使用的是浏览器的默认值,如何获取默认值是多少?可以通过track.getSettings来获取
navigator.mediaDevices.getUserMedia({ video: true });
  1. 精确值:宽度和高度分别设置2个值,有没有范围呢?有。如何获取范围值呢?可以通过track.getCapabilities来获取
navigator.mediaDevices.getUserMedia({ video: {
	width: 640,
    height: 480,
} });
  1. 范围: 会在这个范围内尽量满足, ideal是最理想的值,如果ideal在可设置的范围内,那么就会应用ideal的值;如果min的值超出的浏览器的最大值,那么就会按浏览器的最大提供的能力来展示;
navigator.mediaDevices.getUserMedia({ video: {
	width: { min: 1024, ideal: 1280, max: 1920 },
    height: { min: 776, ideal: 720, max: 1080 }
} });
1.4.3 video frameRate

属性只对video生效,也分为不设置、精确值、范围值来设置,不再赘述

1.4.4 video facingMode

一般用在移动设备上,选择开启前置或者后置摄像头

navigator.mediaDevices.getUserMedia({ video: {
	facingMode: 'user'
} });

值为枚举值:

  • 'user': 前置摄像头
  • 'environment': 后置摄像头
  • 'left':视频源面向用户但在他们的左边,例如一个对准用户但在他们的左肩上方的摄像机。
  • 'right': 视频源面向用户但在用户的右边,例如,摄像机对准用户但在他们的右肩上
1.4.5 video aspectRatio

设置采集图像的宽高比

async function initMedia() {
    const stream = await navigator.mediaDevices.getUserMedia({
        video: {
            width: 640,
            aspectRatio: 2,
        }
    });

    // 宽度 640 高度 320
    localvideo.srcObject = stream;
}
1.4.6 audio autoGainControl & noiseSuppression & echoCancellation

这3个属性通过track.getSettings来看默认值都是true。 autoGainControl是自动音量调节; noiseSuppression是噪声消除; echoCancellation是回声消除;

噪声消除和回声消除是浏览器内置算法消除的,一定不要设置成false

1.4.7 audio channelCount & sampleRate & sampleSize

音频三要素,分别是声道数、采样率、位深。我在浏览器中得到的默认值是 1 48k 16bit 可以得到未压缩的码率:48k * 16 * 1 = 768kb/s

1.4.8 audio latency

可以接受的延迟,值是数字,也可以设置范围

x. 参考文档

标签:mediaDevices,浏览器,一文,stream,track,音视频,video,getUserMedia,constraints
From: https://blog.51cto.com/u_16419719/8727235

相关文章

  • Game = Rust + WebAssembly + 浏览器
    ❝努力成为一个情绪价值的提供者❞大家好,我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder。前言在上一篇Rust编译为WebAssembly在前端项目中使用我们通过一个简单的HelloWorld的Demo,讲述了如何将Rust编译为WebAssembly,并在前端项目中使用。虽然,......
  • 软件测试/人工智能|一文告诉你Python字符串的相关操作
    前言字符串是一个非常重要的数据类型之一。它允许程序员处理文本信息,无论是简单的字母、数字还是复杂的文本数据,都可以用字符串来表示和操作。什么是字符串?在Python中,字符串是由字符序列组成的不可变的数据类型。它可以包含字母、数字、符号和空格等内容。字符串在单引号('')或双引......
  • 配置webDriver(Chrome浏览器)
    1.查看Chrome浏览器版本号方法1:Chrome浏览器,设置 >  关于Chrome 方法2:在Chrome浏览器的地址栏,输入chrome://version/,回车后即可查看到对应版本 2.下载ChromeDriverChromeDriver下载地址:https://googlechromelabs.github.io/chrome-for-testing/......
  • 解决selenium打开edge浏览器闪退问题
     1、需保证浏览器驱动为对应版本,官方给的下载驱动的地址为:https://developer.microsoft.com/zh-cn/microsoft-edge/tools/webdriver/下载完驱动放在如下文件夹编辑2、edge浏览器默认安装路径为:C:\ProgramFiles(x86)\Microsoft\Edge\Application3、我解决问题的方法,增加配置代码......
  • 一文详解安全随机数
    本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-安全随机数》,作者:MDKing。随机数的使用场景使用随机数可分类安全场景跟非安全场景。非安全场景需要生成的越快越好。安全场景使用的随机数必须足够安全,保证不能被预测到。常见的非安全场景:数据的索引号、标识;......
  • 配置webDriver(火狐浏览器)
    1.查看浏览器版本号在下载火狐浏览器的驱动之前,先确认自己火狐浏览器的版本号。火狐浏览器:设置 >常规>(下拉)Firefox更新,可以看到版本号。我的浏览器版本:120.0.1(64位)     如果想下载其他火狐浏览器的版本,可以到下面这个链接:https://ftp.mo......
  • 一文详解安全随机数
    本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-安全随机数》,作者:MDKing。随机数的使用场景使用随机数可分类安全场景跟非安全场景。非安全场景需要生成的越快越好。安全场景使用的随机数必须足够安全,保证不能被预测到。常见的非安全场景:数据的索引号、标识;文件的名称或......
  • Chrome浏览器对不同标签页进行着色
    方法1:使用标签组Chrome浏览器的标签组功能允许您将标签分组在一起,并为每个组分配不同的颜色。要创建标签组,请右键单击一个标签,然后选择“添加到新组”。您还可以将标签拖放到另一个标签上以将其添加到组中。要更改标签组的颜色,请单击标签组的圆点,然后选择“更改颜色”。您可以......
  • Web开发学习HTTP协议、通过浏览器控制台学习HTTP协议。
    @目录HTTP协议1.HTTP协议是什么?2.HTTP协议的特点3.什么是URL?4.通过浏览器控制台学习HTTP协议RequestHeaders请求数据格式说明ResponseHeaders请求数据格式说明5.HTTP工作原理HTTP协议1.HTTP协议是什么?HTTP协议是一种超文本传输协议,规定了浏览器和服务器之间的数据传输的规则......
  • 不再支持安卓 7.0!谷歌Chrome浏览器120稳定版发布
    今天,谷歌面向所有支持平台,发布了Chrome浏览器的120稳定版更新,该版本不再支持安卓7.0/7.1系统。在新功能上,Chrome浏览器120稳定版推出一项新的“主动安全检查”功能,该功能会定期运行,检查浏览器是否存在安全问题,并在检查完成之后通知用户。在设置中也为此新增了一个新的“安全检......